Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔑feat: SAML authentication #255

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions pages/docs/configuration/authentication/SAML/_meta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default {
index: 'Intro',
Configuration_Examples: {
type: 'separator',
},
auth0: 'Auth0',
}
86 changes: 86 additions & 0 deletions pages/docs/configuration/authentication/SAML/auth0.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
title: Auth0
description: Learn how to configure LibreChat to use Auth0 for user authentication.
---

# Auth0

## Step 1: Create a SAML Application in Auth0

1. Log in to your Auth0 Dashboard.
2. Navigate to `Applications > Applications`.
3. Click `Create Application`.
4. Enter an Application Name (e.g., `LibreChat`) and select `Regular Web Application`.
5. Click `Create`.

![auth0-1](/images/docs/configuration/authentication/SAML/auth0/1.png)


## Step 2: Configure the SAML Add-On

1. Open the newly created application in Auth0.
2. Go to the `Addons` tab.
3. Click the slider to enable the `SAML2 Web App`.
4. Click `SAML2 Web App` panel.
5. Configure the following settings:
- **Application Callback URL**: Set this to your LibreChat SAML callback URL:
`https://YOUR_DOMAIN/oauth/saml/callback`
- **Settings (JSON Format)**: Use the following configuration:
```json
{
"mappings": {
"email": "email",
"name": "username"
}
}
```
<Callout type="note" title="note">
If your application requires additional attributes such as `given_name`,
`family_name`, `username` or `picture`, ensure these mappings are properly
configured in the Auth0 SAML settings.
</Callout>
6. Click `Save`.


![auth0-2](/images/docs/configuration/authentication/SAML/auth0/2.png)
![auth0-3](/images/docs/configuration/authentication/SAML/auth0/3.png)

## Step 3: Obtain the Auth0 SAML Metadata

1. Once SAML is enabled, go back to the `SAML2 Web App` settings.
2. Go to the `Usage` tab.
3. Click on `Identity Provider Certificate: Download Atuh0 certificate`.
4. Use the `Issuer` to `SAML_ISSUER`
5. Use the `Identity Provider Login URL` to `SAML_ENTRY_POINT`.
6. Copy the donwloaded cert file to your project folder

![auth0-4](/images/docs/configuration/authentication/SAML/auth0/4a.png)

## Step 4: Configure LibreChat with SAML

Open the `.env` file in your project folder and add the following variables:

```bash filename=".env"
SAML_ENTRY_POINT=https://dev-xxxxx.us.auth0.com/samlp/aaaaaa
SAML_ISSUER=urn:dev-xxxxx.us.auth0.com
SAML_CERT=dev-xxxxx.pem
SAML_CALLBACK_URL=/oauth/saml/callback
SAML_SESSION_SECRET=[JustGenerateARandomSessionSecret]

# Attribute mappings (optional)
SAML_EMAIL_CLAIM=
SAML_USERNAME_CLAIM=
SAML_GIVEN_NAME_CLAIM=
SAML_FAMILY_NAME_CLAIM=
SAML_PICTURE_CLAIM=
SAML_NAME_CLAIM=

# Logint buttion settings (optional)
SAML_BUTTON_LABEL=
SAML_IMAGE_URL=

# Whether the SAML Response should be signed.
# - If "true", the entire `SAML Response` will be signed.
# - If "false" or unset, only the `SAML Assertion` will be signed (default behavior).
# SAML_USE_AUTHN_RESPONSE_SIGNED=
```
131 changes: 131 additions & 0 deletions pages/docs/configuration/authentication/SAML/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
title: Intro
description: How to configure SAML for LibreChat
---

# SAML Authentication

## Overview

SAML (Security Assertion Markup Language) is a widely used authentication
protocol that enables Single Sign-On (SSO). It allows users to authenticate once
with an Identity Provider (IdP) and gain access to multiple services without
needing to log in again.

<Callout type="warning" title="SLO (Single Logout) Not Supported">
Single Logout (SLO) is not supported in this implementation.
</Callout>

<Callout type="warning" title="Mutual Exclusion of OpenID and SAML">
If OpenID authentication is enabled, SAML authentication will be automatically disabled.

Only one authentication method can be active at a time.
</Callout>

## Authentication Method Activation Based on Environment Variables

The following table indicates which authentication method is enabled depending
on the environment variable settings:

| OIDC | SAML | Active Authentication Method |
| -------- | -------- | ---------------------------- |
| ✅Enabled | ❌Disabled | OpenID Connect (OIDC) |
| ❌Disabled | ✅Enabled | SAML |
| ✅Enabled | ✅Enabled | OpenID Connect (OIDC) |
| ❌Disabled | ❌Disabled | No authentication enabled |

## SAML Certificate Format and Configuration

The `SAML_CERT` environment variable is used to specify the Identity Provider’s (IdP) signing certificate for validating SAML Responses. This certificate must be provided in **PEM format** and can be specified in one of the following ways:

### As a File Path (Relative or Absolute)

If `SAML_CERT` is set to a file path, the application will load the certificate from the specified file.
Both **relative paths** and **absolute paths** are supported.

```env
# Relative path (resolved based on the application root)
SAML_CERT=idp-cert.pem

# Absolute path
SAML_CERT=/path/to/idp-cert.pem
```

**Example File Content (`idp-cert.pem`):**

```
-----BEGIN CERTIFICATE-----
MIIDazCCAlOgAwIBAgIUKhXaFJGJJPx466rl...
-----END CERTIFICATE-----
```

### As a One-Line PEM String

The certificate can also be provided as a **one-line PEM string** (Base64-encoded, without line breaks).

```env
SAML_CERT="MIICizCCAfQCCQCY8tKaMc0BMjANBgkqh...W=="
```

This format is useful when storing the certificate directly in environment variables.

### As a Multi-Line PEM String (with \n escape sequences)

The certificate can also be provided as a **multi-line PEM string** where newlines are represented as \n.

```env
SAML_CERT="-----BEGIN CERTIFICATE-----\nMIIDazCCAlOgAwIBAgIUKhXaFJGJJPx466rl...\n-----END CERTIFICATE-----\n"
```

This format is useful when configuring certificates in .env files while preserving the full PEM structure.

### Certificate Format Requirements
- The certificate **must always be in PEM format** (Base64-encoded X.509 certificate).
- If provided as a file, it must be a valid **RFC7468 strict textual message PEM format**.
- When using a one-line certificate, ensure there are **no line breaks** in the value.
- When using a multi-line string, ensure newlines are represented as **\n** escape sequences.

For more details, refer to the [node-saml documentation](https://github.com/node-saml/node-saml/tree/master?tab=readme-ov-file#configuration-option-idpcert).


## Display Username Determination Flow Based on SAML Attributes

![auth0-1](/images/docs/configuration/authentication/SAML/username.png)

In SAML authentication, the display username is determined according to the following flow.

```mermaid
flowchart TD
A[Start] --> B{{Is SAML_NAME_CLAIM available?}}
B -- Yes --> C[Value of SAML_NAME_CLAIM]
B -- No --> D{{Are both SAML_GIVEN_NAME_CLAIM & SAML_FAMILY_NAME_CLAIM available?}}
D -- Yes --> E[Value of SAML_GIVEN_NAME_CLAIM / SAML_FAMILY_NAME_CLAIM]
D -- No --> F{{Is only SAML_GIVEN_NAME_CLAIM available?}}
F -- Yes --> G[Value of SAML_GIVEN_NAME_CLAIM]
F -- No --> H{{Is only SAML_FAMILY_NAME_CLAIM available?}}
H -- Yes --> I[Value of SAML_FAMILY_NAME_CLAIM]
H -- No --> J{{Is SAML_USERNAME_CLAIM available?}}
J -- Yes --> K[Value of SAML_USERNAME_CLAIM]
J -- No --> L[Value of SAML_EMAIL_CLAIM]
style C fill:#FFDEA5,stroke:#FFA500
style E fill:#FFDEA5,stroke:#FFA500
style G fill:#FFDEA5,stroke:#FFA500
style I fill:#FFDEA5,stroke:#FFA500
style K fill:#FFDEA5,stroke:#FFA500
style L fill:#FFDEA5,stroke:#FFA500
```

### Determination Rules

1. If `SAML_NAME_CLAIM` is provided, its value is used as the display username.
2. If both `SAML_GIVEN_NAME_CLAIM` and `SAML_FAMILY_NAME_CLAIM` are provided, their corresponding values are concatenated to form the username.
3. If only `SAML_GIVEN_NAME_CLAIM` is provided, its value is used.
4. If only `SAML_FAMILY_NAME_CLAIM` is provided, its value is used.
5. If `SAML_USERNAME_CLAIM` is provided, its value is used.
6. If none of the above attributes are provided, `SAML_EMAIL_CLAIM` is used as the display username.

By following this flow, an appropriate username is determined during SAML authentication.

## Configuration Examples
- [Auth0](/docs/configuration/authentication/SAML/auth0)

6 changes: 3 additions & 3 deletions pages/docs/configuration/authentication/index.mdx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
title: Authentication System
description: This guide explains how to use the user authentication system of LibreChat, which offers secure and easy email and social logins. You will learn how to set up sign up, log in, password reset, and more.
---
---

# Basic Configuration:

Expand All @@ -20,7 +20,7 @@ Here's an overview of the general configuration.
]}
/>

> **Note:** OpenID does not support the ability to disable only registration.
> **Note:** OpenID and SAML do not support the ability to disable only registration.

Quick Tips:

Expand Down Expand Up @@ -78,7 +78,7 @@ sequenceDiagram

## JWT Secret and Refresh Secret

- You should use new secure values. The examples given are 32-byte keys (64 characters in hex).
- You should use new secure values. The examples given are 32-byte keys (64 characters in hex).
- Use this tool to generate some quickly: **[JWT Keys](/toolkit/creds_generator)**

<OptionTable
Expand Down
34 changes: 32 additions & 2 deletions pages/docs/configuration/dotenv.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ For more info see:
/>

### Trust proxy
Use the address that is at most n number of hops away from the Express application.
req.socket.remoteAddress is the first hop, and the rest are looked for in the X-Forwarded-For header from right to left.
Use the address that is at most n number of hops away from the Express application.
req.socket.remoteAddress is the first hop, and the rest are looked for in the X-Forwarded-For header from right to left.
A value of 0 means that the first untrusted address would be req.socket.remoteAddress, i.e. there is no reverse proxy.
The `TRUST_PROXY` environment variable default is set to `1`.

Expand Down Expand Up @@ -873,6 +873,36 @@ For more information:
]}
/>

#### [SAML](/docs/configuration/authentication/SAML)

For more information:
- [Auth0](/docs/configuration/authentication/SAML/auth0)

<Callout type="warning" title="Mutual Exclusion of OpenID and SAML">
If OpenID is enabled, SAML authentication will be automatically disabled.

Only one authentication method can be active at a time.
</Callout>

<OptionTable
options={[
['SAML_ENTRY_POINT', 'string', 'The SAML identity provider (IdP) entry point URL.', 'SAML_ENTRY_POINT='],
['SAML_ISSUER', 'string', 'The SAML service provider (SP) entity ID.', 'SAML_ISSUER='],
['SAML_CERT', 'string', 'The SAML signing certificate, provided as a file path or a one-line PEM string.', 'SAML_CERT='],
['SAML_CALLBACK_URL', 'string', 'The callback URL for SAML authentication.','SAML_CALLBACK_URL=/oauth/saml/callback'],
['SAML_SESSION_SECRET', 'string', 'The secret for SAML session storage.','SAML_SESSION_SECRET='],
['SAML_EMAIL_CLAIM', 'string', '<Optional>: The attribute in the SAML assertion containing the user email. (default: email)','SAML_EMAIL_CLAIM='],
['SAML_USERNAME_CLAIM', 'string', '<Optional>: The attribute in the SAML assertion containing the username. (default: username)','SAML_USERNAME_CLAIM='],
['SAML_GIVEN_NAME_CLAIM', 'string', '<Optional>: The attribute in the SAML assertion containing the given name. (default: given_name)','SAML_GIVEN_NAME_CLAIM='],
['SAML_FAMILY_NAME_CLAIM', 'string', '<Optional>: The attribute in the SAML assertion containing the family name. (default: family_name)','SAML_FAMILY_NAME_CLAIM='],
['SAML_PICTURE_CLAIM', 'string', '<Optional>: The attribute in the SAML assertion containing the profile picture URL. (default: picture)','SAML_PICTURE_CLAIM='],
['SAML_NAME_CLAIM', 'string', '<Optional>: The attribute in the SAML assertion containing the full name.','SAML_NAME_CLAIM='],
['SAML_BUTTON_LABEL', 'string', '<Optional>: The label for the SAML login button.','SAML_BUTTON_LABEL='],
['SAML_IMAGE_URL', 'string', '<Optional>: The URL of the SAML login button image.','SAML_IMAGE_URL='],
['SAML_USE_AUTHN_RESPONSE_SIGNED', 'boolean', '<Optional>: If "true", signs the entire SAML Response. Otherwise, only the Assertion is signed (default).', 'SAML_USE_AUTHN_RESPONSE_SIGNED=']
]}
/>

#### [LDAP/AD Authentication](/docs/configuration/authentication/ldap)

For more information: **[LDAP/AD Authentication](/docs/configuration/authentication/ldap)**
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.