Passkeys
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.
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.
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.
Enable passkeys
Serve LibreChat over HTTPS. Browsers only allow WebAuthn in a secure context. http://localhost is exempt, so local testing works without TLS.
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.
ALLOW_PASSKEY_LOGIN=truePin 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.
PASSKEY_RP_ID=chat.example.comRestart LibreChat. The login page shows Sign in with a passkey, and Settings > Account shows a Passkeys section.
Configuration reference
| Key | Type | Description | Example |
|---|---|---|---|
| ALLOW_PASSKEY_LOGIN | boolean | Enables passkey sign-in and the Passkeys section in account settings. Default: false. | ALLOW_PASSKEY_LOGIN=true |
| PASSKEY_RP_ID | string | 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. | # PASSKEY_RP_ID=chat.example.com |
| PASSKEY_RP_NAME | string | Name the authenticator shows when creating or using a passkey. Defaults to APP_TITLE, then LibreChat. | # PASSKEY_RP_NAME=LibreChat |
| PASSKEY_ORIGINS | string | Comma-separated list of origins allowed to run passkey ceremonies. Defaults to DOMAIN_CLIENT and DOMAIN_SERVER. | # PASSKEY_ORIGINS=https://chat.example.com |
| MAX_PASSKEYS_PER_USER | integer | Passkeys each account may enroll, from 1 to 100. Overridden by passkeys.perUserMax in librechat.yaml. Default: 20. | # MAX_PASSKEYS_PER_USER=20 |
| PASSKEY_STEPUP_MAX | integer | Password-confirmed passkey add or remove attempts allowed per user in PASSKEY_STEPUP_WINDOW. Default: 20. | PASSKEY_STEPUP_MAX=20 |
| PASSKEY_STEPUP_WINDOW | integer | Window in minutes for PASSKEY_STEPUP_MAX. Default: 15. | PASSKEY_STEPUP_WINDOW=15 |
| PASSKEY_MAX | integer | 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. | # PASSKEY_MAX=20 |
| PASSKEY_WINDOW | integer | Window in minutes for PASSKEY_MAX. Default: 5. | # PASSKEY_WINDOW=5 |
Per-user limit in librechat.yaml
You can also set the enrollment cap in librechat.yaml:
passkeys:
perUserMax: 10The 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 in the config reference.
What users see
Adding a passkey
- Open Settings > Account, find Passkeys, and select Manage.
- Select Add passkey.
- 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.
- 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.
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.
Signing in
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.
Behavior and caveats
- 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.
- Works with email login disabled. The Sign in with a passkey button and its routes depend only on
ALLOW_PASSKEY_LOGIN. WithALLOW_EMAIL_LOGIN=false, existing local users can still sign in with passkeys they enrolled earlier. - Two-factor authentication. Passkey sign-in goes through the same 2FA gate as password sign-in. With
ENFORCE_TWO_FACTOR_AUTHENTICATION=true, a user who has not enrolled in 2FA is sent to the setup flow after signing in with a passkey. - Changing the RP ID orphans passkeys. Passkeys created under one RP ID never work under another. Changing
PASSKEY_RP_ID, or changingDOMAIN_CLIENTwhilePASSKEY_RP_IDis unset, leaves every existing passkey unusable; users must sign in another way and enroll again. - 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 toPASSKEY_ORIGINSwhen you serve LibreChat on more than one. - 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.
How is this guide?