Skip to content

Commit 19ed270

Browse files
committed
docs: Document recent dev changes and rewrite temporary chat retention
Cover the user-facing and admin-facing changes merged to LibreChat dev over the last two weeks: required two-factor authentication, passkeys, email address change, ephemeral retention mode, the redesigned message composer, chat list filters, unread replies and notifications, project instructions and files, conversation starters in the Agent Builder, the Agent Marketplace, undocking artifacts, Bash output rendering, theme appearance keys and roles, config override validation, and the new librechat.yaml keys. Rewrite the temporary chat page against the merged retention code, drop the outdated screenshots, and fix pages that still described the old attach and MCP dropdowns.
1 parent bf64999 commit 19ed270

38 files changed

Lines changed: 1579 additions & 161 deletions

‎content/docs/configuration/authentication/OAuth2-OIDC/azure.mdx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ SHAREPOINT_PICKER_GRAPH_SCOPE=Files.Read.All
184184
### Usage
185185

186186
When properly configured:
187-
1. Users will see "From SharePoint" option in the file attachment menu
187+
1. Users will see a **From SharePoint** option in the **Attach** section of the [composer's **+** palette](/docs/features/composer#add-files)
188188
2. Clicking it opens the native SharePoint file picker
189189
3. Users can browse and select files from any SharePoint site or OneDrive they have access to
190190
4. Selected files are downloaded and attached to the conversation

‎content/docs/configuration/authentication/email.mdx‎

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,52 @@ EMAIL_FROM_NAME=LibreChat
203203
ALLOW_PASSWORD_RESET=true
204204
```
205205

206+
## Email Address Change
207+
208+
<Callout type="info" title="Availability">
209+
Newer than **v0.8.8**. Available now on LibreChat's `dev` and `canary` branches, and in the next release.
210+
</Callout>
211+
212+
Users with a local (email and password) account can change their registered email address themselves from **Settings > Account**. The feature is on by default and needs working email delivery (Mailgun or SMTP, configured above): without it, the option is hidden.
213+
214+
### User flow
215+
216+
1. In **Settings > Account**, next to **Email address**, the user selects **Change**.
217+
2. In the **Change email address** dialog, they enter the **New email address** and their **Current password**, then select **Send verification link**.
218+
3. LibreChat first sends a security notice ("Email change requested") to the current address, with the requested address and the request IP. It sends this before checking the password, so the account owner hears about every attempt, including rejected ones. If the request passes the checks below, a verification link goes to the new address.
219+
4. The address changes only when the link is opened. Both the old and new addresses then receive a "Your email address was changed" notice, and the new address is marked as verified.
220+
221+
The request is rejected when the password is wrong, the new address equals the current one, the new address already belongs to another account, or its domain is not in [`registration.allowedDomains`](/docs/configuration/librechat_yaml/object_structure/registration#alloweddomains). Accounts that sign in through OAuth, OpenID Connect, SAML, or LDAP cannot use this flow.
222+
223+
The verification link is single-use and expires after `tokenTTLSeconds` (15 minutes by default). It also stops working if the password or email of the account changes before it is opened. Completing a change invalidates any password reset links issued for the previous address.
224+
225+
### Configuration
226+
227+
<OptionTable
228+
options={[
229+
[
230+
'ALLOW_EMAIL_CHANGE',
231+
'boolean',
232+
'Allow local-account users to change their email address. Enabled when omitted. Overridden by emailChange.enabled in librechat.yaml.',
233+
'# ALLOW_EMAIL_CHANGE=true',
234+
],
235+
]}
236+
/>
237+
238+
In `librechat.yaml`, the `emailChange` block takes precedence over `ALLOW_EMAIL_CHANGE` and also sets the link lifetime:
239+
240+
```yaml filename="librechat.yaml"
241+
emailChange:
242+
enabled: true
243+
tokenTTLSeconds: 900 # 60 to 86400, default 900 (15 minutes)
244+
```
245+
246+
Each field falls back independently: `enabled` to `ALLOW_EMAIL_CHANGE` and then `true`; `tokenTTLSeconds` to `900`. Rate limits for requesting a change and for opening links are set under [`rateLimits.emailChange` and `rateLimits.emailChangeConfirm`](/docs/configuration/librechat_yaml/object_structure/config#ratelimits), or with the matching [environment variables](/docs/configuration/dotenv#email-change-rate-limiting).
247+
248+
<Callout type="warning" title="Multi-node rollouts">
249+
Set `ALLOW_EMAIL_CHANGE=false` (or `emailChange.enabled: false`) until every node runs a version that includes this feature. Older nodes issue and accept password reset links that are not bound to an address, so a link held by the previous owner of an address could outlive the change and reset the renamed account.
250+
</Callout>
251+
206252
## Troubleshooting
207253

208254
### Mailgun Issues

‎content/docs/configuration/authentication/index.mdx‎

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,68 @@ Quick Tips:
6060
alt="User registration screen"
6161
/>
6262

63+
Related sign-in options for local accounts:
64+
65+
- [Passkeys](/docs/configuration/authentication/passkeys): passwordless sign-in with a device screen lock or security key (`ALLOW_PASSKEY_LOGIN`).
66+
- [Email address change](/docs/configuration/authentication/email#email-address-change): lets users change their registered email from **Settings > Account** (`ALLOW_EMAIL_CHANGE`, on by default).
67+
68+
## Required Two-Factor Authentication
69+
70+
<Callout type="info" title="Availability">
71+
Newer than **v0.8.8**. Available now on LibreChat's `dev` and `canary` branches, and in the next release.
72+
</Callout>
73+
74+
Users can always turn on two-factor authentication (TOTP) themselves from **Settings > Account**. To make it mandatory, set:
75+
76+
```bash filename=".env"
77+
ENFORCE_TWO_FACTOR_AUTHENTICATION=true
78+
```
79+
80+
**Who it applies to:** local (email and password) and LDAP accounts. Accounts that sign in through OAuth, OpenID Connect, or SAML are not affected, because their identity provider is responsible for MFA. A federated account that tries to sign in with a password while enforcement is on is told to use its identity provider instead.
81+
82+
**What users see:** a user without 2FA who signs in (with a password, LDAP credentials, or a passkey) gets no session until setup is complete. They land on a **Two-Factor Authentication Required** screen ("Your administrator requires two-factor authentication. Set it up before continuing."), scan a QR code with an authenticator app, enter a code to verify, and save their backup codes. Users who are already signed in are moved into the same setup the next time their session is checked or refreshed, and access tokens issued before enrollment stop working. The setup session lasts 10 minutes; if it expires, the user returns to the login page and starts again.
83+
84+
**After enrollment:** the **Disable 2FA** control in **Settings > Account** shows **Required by administrator**, and the server rejects attempts to disable 2FA while the policy is on. Users can still regenerate backup codes.
85+
86+
<OptionTable
87+
options={[
88+
[
89+
'ENFORCE_TWO_FACTOR_AUTHENTICATION',
90+
'boolean',
91+
'Require local and LDAP accounts to enroll in 2FA before a full session is issued. Default: false.',
92+
'ENFORCE_TWO_FACTOR_AUTHENTICATION=false',
93+
],
94+
[
95+
'TWO_FACTOR_TEMP_MAX',
96+
'integer',
97+
'Two-factor code attempts (sign-in challenge and enrollment confirmation) per TWO_FACTOR_TEMP_WINDOW. Defaults to LOGIN_MAX (7).',
98+
'# TWO_FACTOR_TEMP_MAX=7',
99+
],
100+
[
101+
'TWO_FACTOR_TEMP_WINDOW',
102+
'integer',
103+
'Window in minutes for TWO_FACTOR_TEMP_MAX. Defaults to LOGIN_WINDOW (5).',
104+
'# TWO_FACTOR_TEMP_WINDOW=5',
105+
],
106+
[
107+
'TWO_FACTOR_SETUP_MAX',
108+
'integer',
109+
'Enrollment steps that check no guessable code (starting setup, acknowledging backup codes, finishing). Kept separate so wrong codes cannot strand an enrollment. Default: 20.',
110+
'# TWO_FACTOR_SETUP_MAX=20',
111+
],
112+
[
113+
'TWO_FACTOR_SETUP_WINDOW',
114+
'integer',
115+
'Window in minutes for TWO_FACTOR_SETUP_MAX. Defaults to TWO_FACTOR_TEMP_WINDOW.',
116+
'# TWO_FACTOR_SETUP_WINDOW=5',
117+
],
118+
]}
119+
/>
120+
121+
<Callout type="info" title="Environment only">
122+
`ENFORCE_TWO_FACTOR_AUTHENTICATION` and the `TWO_FACTOR_TEMP_*` and `TWO_FACTOR_SETUP_*` limits are process-wide `.env` settings. They apply before a request or tenant configuration is available, so they cannot be set in `librechat.yaml` or per tenant. Set the same values on every replica. The separate budget for managing 2FA from settings is [`rateLimits.twoFactorManagement`](/docs/configuration/librechat_yaml/object_structure/config#ratelimits).
123+
</Callout>
124+
63125
## Session Expiry and Refresh Token
64126

65127
- Default values: session expiry: 15 minutes, refresh token expiry: 7 days
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"title": "Authentication",
33
"icon": "Lock",
4-
"pages": ["email", "ldap", "OAuth2-OIDC", "SAML"]
4+
"pages": ["email", "passkeys", "ldap", "OAuth2-OIDC", "SAML"]
55
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
---
2+
title: Passkeys
3+
icon: KeyRound
4+
description: Let users sign in without a password using a device screen lock or a security key (WebAuthn). Covers enabling passkeys, the relying party settings, enrollment limits, and how passkeys interact with two-factor authentication.
5+
---
6+
7+
Passkeys let users with a local (email and password) account sign in with their device screen lock, a password manager, or a hardware security key instead of typing a password. LibreChat implements them with WebAuthn. They are off by default.
8+
9+
<Callout type="info" title="Availability">
10+
Newer than **v0.8.8**. Available now on LibreChat's `dev` and `canary` branches, and in the next release.
11+
</Callout>
12+
13+
Use passkeys when you want a phishing-resistant, passwordless sign-in for local accounts. Accounts that sign in through OAuth, OpenID Connect, SAML, or LDAP keep using their provider and cannot add passkeys.
14+
15+
## Enable passkeys
16+
17+
<Steps>
18+
<Step>
19+
20+
**Serve LibreChat over HTTPS.** Browsers only allow WebAuthn in a secure context. `http://localhost` is exempt, so local testing works without TLS.
21+
22+
</Step>
23+
<Step>
24+
25+
**Turn the feature on in `.env`.** For a standard deployment, this is the only required setting. The relying party ID and allowed origins are derived from `DOMAIN_CLIENT` and `DOMAIN_SERVER`.
26+
27+
```bash filename=".env"
28+
ALLOW_PASSKEY_LOGIN=true
29+
```
30+
31+
</Step>
32+
<Step>
33+
34+
**Pin the relying party ID (recommended).** Each passkey is permanently bound to the RP ID it was created under. If `DOMAIN_CLIENT` might ever change, set `PASSKEY_RP_ID` now so existing passkeys keep working.
35+
36+
```bash filename=".env"
37+
PASSKEY_RP_ID=chat.example.com
38+
```
39+
40+
</Step>
41+
<Step>
42+
43+
**Restart LibreChat.** The login page shows **Sign in with a passkey**, and **Settings > Account** shows a **Passkeys** section.
44+
45+
</Step>
46+
</Steps>
47+
48+
## Configuration reference
49+
50+
<OptionTable
51+
options={[
52+
[
53+
'ALLOW_PASSKEY_LOGIN',
54+
'boolean',
55+
'Enables passkey sign-in and the Passkeys section in account settings. Default: false.',
56+
'ALLOW_PASSKEY_LOGIN=true',
57+
],
58+
[
59+
'PASSKEY_RP_ID',
60+
'string',
61+
'Relying party ID: the domain passkeys are bound to. Must be a domain name (not an IP address) equal to, or a parent domain of, the host users visit. Defaults to the hostname of DOMAIN_CLIENT, or localhost.',
62+
'# PASSKEY_RP_ID=chat.example.com',
63+
],
64+
[
65+
'PASSKEY_RP_NAME',
66+
'string',
67+
'Name the authenticator shows when creating or using a passkey. Defaults to APP_TITLE, then LibreChat.',
68+
'# PASSKEY_RP_NAME=LibreChat',
69+
],
70+
[
71+
'PASSKEY_ORIGINS',
72+
'string',
73+
'Comma-separated list of origins allowed to run passkey ceremonies. Defaults to DOMAIN_CLIENT and DOMAIN_SERVER.',
74+
'# PASSKEY_ORIGINS=https://chat.example.com',
75+
],
76+
[
77+
'MAX_PASSKEYS_PER_USER',
78+
'integer',
79+
'Passkeys each account may enroll, from 1 to 100. Overridden by passkeys.perUserMax in librechat.yaml. Default: 20.',
80+
'# MAX_PASSKEYS_PER_USER=20',
81+
],
82+
[
83+
'PASSKEY_STEPUP_MAX',
84+
'integer',
85+
'Password-confirmed passkey add or remove attempts allowed per user in PASSKEY_STEPUP_WINDOW. Default: 20.',
86+
'PASSKEY_STEPUP_MAX=20',
87+
],
88+
[
89+
'PASSKEY_STEPUP_WINDOW',
90+
'integer',
91+
'Window in minutes for PASSKEY_STEPUP_MAX. Default: 15.',
92+
'PASSKEY_STEPUP_WINDOW=15',
93+
],
94+
[
95+
'PASSKEY_MAX',
96+
'integer',
97+
'Passkey sign-in requests allowed per IP in PASSKEY_WINDOW. One sign-in uses two requests. Requests over the limit get HTTP 429; they are not scored as violations because no user is signed in yet. Default: 20.',
98+
'# PASSKEY_MAX=20',
99+
],
100+
[
101+
'PASSKEY_WINDOW',
102+
'integer',
103+
'Window in minutes for PASSKEY_MAX. Default: 5.',
104+
'# PASSKEY_WINDOW=5',
105+
],
106+
]}
107+
/>
108+
109+
### Per-user limit in `librechat.yaml`
110+
111+
You can also set the enrollment cap in `librechat.yaml`:
112+
113+
```yaml filename="librechat.yaml"
114+
passkeys:
115+
perUserMax: 10
116+
```
117+
118+
The cap resolves in this order: `passkeys.perUserMax` in `librechat.yaml`, then `MAX_PASSKEYS_PER_USER`, then the default of `20`. Values outside `1` to `100` are ignored and the next source is used. When a user reaches the cap, **Settings > Account** shows "You have reached the maximum number of passkeys". See [`passkeys`](/docs/configuration/librechat_yaml/object_structure/config#passkeys) in the config reference.
119+
120+
## What users see
121+
122+
**Adding a passkey**
123+
124+
1. Open **Settings > Account**, find **Passkeys**, and select **Manage**.
125+
2. Select **Add passkey**.
126+
3. Enter the account password in the **Confirm your password** dialog. A passkey is a complete sign-in on its own, so LibreChat asks for the password before creating one.
127+
4. Complete the browser or device prompt. The new passkey appears in the list with a default name such as **This device**, **Phone or tablet**, or **Security key**.
128+
129+
Each entry shows when it was added and last used, and a **Synced** badge when the authenticator reports that the passkey is backed up (for example, by a password manager). Users can rename a passkey, and removing one (**Remove passkey**) also asks for the account password.
130+
131+
**Signing in**
132+
133+
On the login page, users select **Sign in with a passkey** and approve the device prompt. If the account has two-factor authentication enabled, LibreChat still asks for the 2FA code afterward, exactly as it does after a password sign-in.
134+
135+
## Behavior and caveats
136+
137+
- **Local accounts only.** Passkey enrollment and sign-in are limited to local accounts. Accounts created through an identity provider or LDAP must keep authenticating through that provider.
138+
- **Works with email login disabled.** The **Sign in with a passkey** button and its routes depend only on `ALLOW_PASSKEY_LOGIN`. With `ALLOW_EMAIL_LOGIN=false`, existing local users can still sign in with passkeys they enrolled earlier.
139+
- **Two-factor authentication.** Passkey sign-in goes through the same 2FA gate as password sign-in. With [`ENFORCE_TWO_FACTOR_AUTHENTICATION=true`](/docs/configuration/authentication#required-two-factor-authentication), a user who has not enrolled in 2FA is sent to the setup flow after signing in with a passkey.
140+
- **Changing the RP ID orphans passkeys.** Passkeys created under one RP ID never work under another. Changing `PASSKEY_RP_ID`, or changing `DOMAIN_CLIENT` while `PASSKEY_RP_ID` is unset, leaves every existing passkey unusable; users must sign in another way and enroll again.
141+
- **Origins must match.** If users reach LibreChat on an origin not covered by `PASSKEY_ORIGINS` (or the derived defaults), the browser shows "Passkeys are not available on this domain". Add every public origin to `PASSKEY_ORIGINS` when you serve LibreChat on more than one.
142+
- **Password reset removes passkeys.** A completed password reset signs the account out everywhere and deletes all of its passkeys, so a passkey enrolled before the reset can no longer be used to get in. Users enroll again afterward.

0 commit comments

Comments
 (0)