LibreChat with Azure Entra ID & SharePoint: Complete Enterprise Integration Guide

Integrating LibreChat with Microsoft Azure Entra ID (formerly Azure AD) and SharePoint is technically demanding and requires precise configuration of multiple components. This guide documents the complete setup process, including all pitfalls and their solutions.

What we achieve:

  • Single Sign-On (SSO) with Microsoft Entra ID
  • SharePoint/OneDrive File Picker integration
  • Azure Blob Storage for file uploads
  • Entra ID People Search for sharing features

Prerequisites

  • Azure Subscription with Entra ID (Azure AD)
  • LibreChat v0.8.1 or higher
  • SharePoint Online tenant
  • Admin rights for Azure AD and SharePoint

Azure AD App Registration

Create New App Registration

  1. Navigate to Azure Portal > Entra ID > App registrations
  2. Click New registration
  3. Configure:
    • Name: LibreChat (or your preferred name)
    • Supported account types: “Accounts in this organizational directory only”
    • Redirect URI: https://your-domain.com/oauth/openid/callback

Create Client Secret

  1. Go to Certificates & secrets
  2. Click New client secret
  3. Choose a validity period (recommended: 24 months)
  4. IMPORTANT: Copy the Secret Value immediately - it’s only shown once!

Note Important IDs

Record the following values from the Overview page:

  • Application (client) ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  • Directory (tenant) ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  • Object ID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (for API calls)

API Exposition for On-Behalf-Of (OBO) Flow

CRITICAL: Without this configuration, SharePoint integration will NOT work!

The OBO flow allows LibreChat to exchange the user token for a Microsoft Graph token. For this, the app must expose an API.

Set Application ID URI

az ad app update \
  --id <APPLICATION_CLIENT_ID> \
  --identifier-uris "api://<APPLICATION_CLIENT_ID>"

Create OAuth2 Permission Scope

# Generate scope ID
SCOPE_ID=$(uuidgen | tr '[:upper:]' '[:lower:]')

# Add API scope
az rest --method PATCH \
  --uri "https://graph.microsoft.com/v1.0/applications/<OBJECT_ID>" \
  --body '{
    "api": {
      "oauth2PermissionScopes": [
        {
          "adminConsentDescription": "Allow the application to access LibreChat on behalf of the signed-in user.",
          "adminConsentDisplayName": "Access LibreChat",
          "id": "'$SCOPE_ID'",
          "isEnabled": true,
          "type": "User",
          "userConsentDescription": "Allow the application to access LibreChat on your behalf.",
          "userConsentDisplayName": "Access LibreChat",
          "value": "default"
        }
      ]
    }
  }'

Add App as Pre-Authorized Client

The app must authorize itself as a trusted client for the OBO flow:

# Get scope ID
SCOPE_ID=$(az ad app show --id <APPLICATION_CLIENT_ID> \
  --query "api.oauth2PermissionScopes[0].id" -o tsv)

# Add pre-authorization
az rest --method PATCH \
  --uri "https://graph.microsoft.com/v1.0/applications/<OBJECT_ID>" \
  --body '{
    "api": {
      "preAuthorizedApplications": [
        {
          "appId": "<APPLICATION_CLIENT_ID>",
          "delegatedPermissionIds": ["'$SCOPE_ID'"]
        }
      ]
    }
  }'

Token Configuration

IMPORTANT: Without the email claim in the token, existing users cannot authenticate!

LibreChat requires the email claim in the ID token to correctly identify users. By default, Entra ID does not include this claim.

Add Optional Claims

az rest --method PATCH \
  --uri "https://graph.microsoft.com/v1.0/applications/<OBJECT_ID>" \
  --body '{
    "optionalClaims": {
      "idToken": [
        {
          "name": "email",
          "source": null,
          "essential": true,
          "additionalProperties": []
        },
        {
          "name": "upn",
          "source": null,
          "essential": false,
          "additionalProperties": []
        }
      ],
      "accessToken": [
        {
          "name": "email",
          "source": null,
          "essential": true,
          "additionalProperties": []
        }
      ]
    }
  }'

Verification

az ad app show --id <APPLICATION_CLIENT_ID> --query "optionalClaims" -o json

Expected output:

{
  "accessToken": [{"name": "email", "essential": true, ...}],
  "idToken": [{"name": "email", "essential": true, ...}, {"name": "upn", ...}],
  "saml2Token": []
}

Microsoft Graph API Permissions

Required Delegated Permissions

PermissionTypeDescription
User.ReadDelegatedRead user profile
Files.Read.AllDelegatedRead files (OneDrive/SharePoint)
offline_accessDelegatedObtain refresh tokens
People.ReadDelegatedSearch contacts/people
User.ReadBasic.AllDelegatedRead basic user info
GroupMember.Read.AllDelegated (Admin)Read group memberships

Add Permissions

In Azure Portal:

  1. API permissions > Add a permission
  2. Microsoft Graph > Delegated permissions
  3. Select the permissions listed above
  4. Click Grant admin consent

Or via CLI:

# Add User.Read
az ad app permission add \
  --id <APPLICATION_CLIENT_ID> \
  --api 00000003-0000-0000-c000-000000000000 \
  --api-permissions e1fe6dd8-ba31-4d61-89e7-88639da4683d=Scope

# Grant admin consent
az ad app permission admin-consent --id <APPLICATION_CLIENT_ID>

SharePoint API Permissions

Add SharePoint Permission

PermissionTypeDescription
AllSites.ReadDelegatedRead all SharePoint sites
# SharePoint API ID: 00000003-0000-0ff1-ce00-000000000000
az ad app permission add \
  --id <APPLICATION_CLIENT_ID> \
  --api 00000003-0000-0ff1-ce00-000000000000 \
  --api-permissions 4e0d77b0-96ba-4398-af14-3baa780278f4=Scope

SharePoint permissions require admin consent:

az ad app permission admin-consent --id <APPLICATION_CLIENT_ID>

LibreChat Environment Variables

OIDC Configuration

# OIDC base configuration
OPENID_ISSUER=https://login.microsoftonline.com/<TENANT_ID>/v2.0
OPENID_CLIENT_ID=<APPLICATION_CLIENT_ID>
OPENID_CLIENT_SECRET=<CLIENT_SECRET>
OPENID_CALLBACK_URL=/oauth/openid/callback
OPENID_BUTTON_LABEL=Microsoft Login

# CRITICAL: API scope MUST be included for OBO flow!
OPENID_SCOPE=api://<APPLICATION_CLIENT_ID>/default openid profile email offline_access

# Token reuse for SharePoint - MUST be enabled!
OPENID_REUSE_TOKENS=true

# Enable social login
ALLOW_SOCIAL_LOGIN=true

SharePoint Integration

# Enable SharePoint file picker
ENABLE_SHAREPOINT_FILEPICKER=true
SHAREPOINT_BASE_URL=https://<TENANT>.sharepoint.com
SHAREPOINT_PICKER_SHAREPOINT_SCOPE=https://<TENANT>.sharepoint.com/AllSites.Read
SHAREPOINT_PICKER_GRAPH_SCOPE=Files.Read.All

Entra ID People Search (Optional)

# Entra ID integration for people search in sharing system
USE_ENTRA_ID_FOR_PEOPLE_SEARCH=true
ENTRA_ID_INCLUDE_OWNERS_AS_MEMBERS=true

Azure Blob Storage (Optional)

# For Managed Identity (recommended):
AZURE_STORAGE_ACCOUNT_NAME=<STORAGE_ACCOUNT_NAME>
AZURE_STORAGE_PUBLIC_ACCESS=false
AZURE_CONTAINER_NAME=files

# OR for Connection String:
# AZURE_STORAGE_CONNECTION_STRING=DefaultEndpointsProtocol=https;AccountName=...

In librechat.yaml:

version: 1.3.1
cache: true
fileStrategy: "azure_blob"

Common Problems and Solutions

Problem 1: 401 Unauthorized Loop After Login

Symptoms:

  • Login with Entra ID succeeds
  • Immediately followed by 401 errors on all API endpoints
  • Browser shows endless token refresh attempts

Cause: OPENID_REUSE_TOKENS=true is enabled, but:

  • API is not exposed (missing api:// scope)
  • OR email claim is missing from token
  • OR app is not pre-authorized

Solution:

  1. Check API exposition (see section above)
  2. Check token configuration
  3. Check pre-authorization
  4. OIDC_SCOPE must contain the API scope: api://<CLIENT_ID>/default

Problem 2: SharePoint Picker is Empty

Symptoms:

  • Login works
  • SharePoint picker opens
  • No files/sites are displayed

Cause:

  • Guest account without SharePoint access
  • Missing SharePoint API permissions
  • OBO token exchange fails

Solution:

  1. Test with an internal account (not guest)
  2. Check SharePoint permissions and grant admin consent
  3. Check backend logs for [exchangeTokenForGraphAccess] Token exchange failed

Problem 3: Token Exchange Failed

Backend log:

[exchangeTokenForGraphAccess] Token exchange failed: server responded with an error

Cause: The OBO flow is not correctly configured.

Solution:

  1. Add API scope to OIDC_SCOPE: api://<CLIENT_ID>/default
  2. Add app as pre-authorized client
  3. Restart the app service

Problem 4: Existing Users Cannot Sign In

Symptoms:

  • New users can sign in
  • Old users (before OIDC activation) receive 401 errors

Cause: LibreChat bug (#9303): openIdJwtStrategy only searches for openidId, not email.

Solution:

  1. Add email claim as “essential” to the token
  2. OR: Manually set openidId in MongoDB for the user

Problem 5: Profile Picture Not Loading

Backend log:

[openidStrategy] downloadImage: Error downloading image at URL "https://graph.microsoft.com/v1.0/me/photo/$value": Error: Not Found (HTTP 404)

Cause: The user has no profile picture set in Entra ID.

Solution: This is not a critical error - LibreChat works without a profile picture.

Terraform Reference

App Service Configuration

resource "azurerm_linux_web_app" "librechat" {
  name                = "app-librechat"
  resource_group_name = azurerm_resource_group.main.name
  location            = azurerm_resource_group.main.location
  service_plan_id     = azurerm_service_plan.main.id

  site_config {
    always_on = true
    application_stack {
      docker_image_name   = "danny-avila/librechat:v0.8.1"
      docker_registry_url = "https://ghcr.io"
    }
  }

  app_settings = {
    # OIDC Configuration
    OPENID_ISSUER         = var.oidc_issuer_url
    OPENID_CLIENT_ID      = var.oidc_client_id
    OPENID_CLIENT_SECRET  = var.oidc_client_secret
    OPENID_CALLBACK_URL   = "/oauth/openid/callback"
    OPENID_SCOPE          = "api://${var.oidc_client_id}/default openid profile email offline_access"
    OPENID_BUTTON_LABEL   = "Microsoft Login"
    ALLOW_SOCIAL_LOGIN    = "true"

    # SharePoint Integration
    ENABLE_SHAREPOINT_FILEPICKER       = "true"
    SHAREPOINT_BASE_URL                = "https://${var.sharepoint_tenant}.sharepoint.com"
    SHAREPOINT_PICKER_SHAREPOINT_SCOPE = "https://${var.sharepoint_tenant}.sharepoint.com/AllSites.Read"
    SHAREPOINT_PICKER_GRAPH_SCOPE      = "Files.Read.All"
    OPENID_REUSE_TOKENS                = "true"

    # Entra ID People Search
    USE_ENTRA_ID_FOR_PEOPLE_SEARCH     = "true"
    ENTRA_ID_INCLUDE_OWNERS_AS_MEMBERS = "true"

    # Azure Blob Storage
    AZURE_STORAGE_ACCOUNT_NAME  = azurerm_storage_account.main.name
    AZURE_STORAGE_PUBLIC_ACCESS = "false"
    AZURE_CONTAINER_NAME        = "files"
  }

  identity {
    type = "SystemAssigned"
  }
}

# Storage Blob Data Contributor for Managed Identity
resource "azurerm_role_assignment" "librechat_blob" {
  scope                = azurerm_storage_account.main.id
  role_definition_name = "Storage Blob Data Contributor"
  principal_id         = azurerm_linux_web_app.librechat.identity[0].principal_id
}

Integration Checklist

  • App Registration created
  • Client Secret generated and securely stored
  • API exposed with api://<CLIENT_ID> URI
  • OAuth2 scope default created
  • App added as pre-authorized client
  • Email claim set as essential in token configuration
  • Microsoft Graph permissions added (User.Read, Files.Read.All, etc.)
  • SharePoint permission (AllSites.Read) added
  • Admin consent granted for all permissions
  • OIDC_SCOPE contains API scope: api://<CLIENT_ID>/default
  • OPENID_REUSE_TOKENS=true configured
  • SharePoint environment variables set

Critical Points Summary

  1. The API scope in OIDC_SCOPE is MANDATORY for the OBO flow
  2. OPENID_REUSE_TOKENS=true is MANDATORY for SharePoint
  3. Email claim must be essential for existing users
  4. Pre-authorization is MANDATORY for token exchange
  5. Admin consent is MANDATORY for SharePoint permissions

Debugging Tips

  1. Check backend logs: az webapp log tail --name <APP_NAME> --resource-group <RG>
  2. Search for: [openidStrategy], [exchangeTokenForGraphAccess], login success
  3. Browser DevTools: Network tab for 401 errors, Console for JavaScript errors
  4. Use incognito window: Cached tokens can cause issues

Known Limitations

SharePoint Does NOT Work for Guest Users

Guest users (external accounts) can sign in, but the SharePoint file picker remains empty.

Technical cause: LibreChat uses the On-Behalf-Of (OBO) flow for SharePoint. This flow has a fundamental limitation:

  1. Guest signs in -> Token is issued in the home tenant (e.g., partner.com)
  2. LibreChat attempts token exchange in the resource tenant (your organization)
  3. Exchange fails because OBO is not designed for cross-tenant scenarios
OBO Flow with Guest Users:

┌──────────────┐     Token (Home Tenant)     ┌───────────┐
│ Guest User   │ ──────────────────────────> │ LibreChat │
│ @partner.com │                             │           │
└──────────────┘                             └─────┬─────┘

                                                   │ Token Exchange
                                                   │ (OBO Flow)

                                           ┌───────────────┐
                                           │ Microsoft     │
                                           │ Graph API     │
                                           │ (Your Tenant) │
                                           └───────────────┘


                                              ❌ ERROR
                                        "Token from wrong tenant"

Workarounds:

OptionEffortDescription
Use internal accountsLowGuests get accounts in your tenant
LibreChat forkVery HighModify code to use PKCE flow
Feature requestLowRequest from LibreChat maintainers
Disable SharePoint for guestsLowGuests can only upload local files

Summary:

User TypeLoginChatSharePoint Picker
Internal (@yourdomain.com)YesYesYes
Guest (@external.yourdomain.com)YesYesNo
Guest (@partner.com)YesYesNo

Cosmos DB: $bitsAllSet Not Supported

Problem:

[PermissionService.findAccessibleResources] Error: $bitsAllSet not supported

Cause: LibreChat uses MongoDB operators for permission checks that Azure Cosmos DB (MongoDB API) does not fully support.

Impact: The sharing/permissions system may not work correctly.

Workaround:

  • Use real MongoDB (Atlas or self-hosted) instead of Cosmos DB
  • Or: Don’t use sharing features

References

Need Help with Your LibreChat Implementation?

Setting up LibreChat with Azure Entra ID and SharePoint integration can be complex and time-consuming. If you need professional support for your enterprise AI chat deployment, alfatier GmbH offers comprehensive implementation services:

  • Architecture design for secure, scalable LibreChat deployments
  • Azure infrastructure setup with Terraform and best practices
  • Entra ID integration including SSO, MFA, and conditional access
  • SharePoint and Microsoft 365 integration
  • Ongoing support and maintenance

Get in touch:

Kim Nis Neuhauss CEO & Founder, alfatier GmbH

Bernstorffstraße 95, 22767 Hamburg, Germany