Repository navigation
π feat: allow the session JWT to be read from a configurable header #14753
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
base: dev
Are you sure you want to change the base?
Changes from 1 commit
1617e19
4bf960f
9adbe5c
11a25c6
898cdeb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,11 +3,26 @@ const { SystemRoles } = require('librechat-data-provider'); | |
| const { Strategy: JwtStrategy, ExtractJwt } = require('passport-jwt'); | ||
| const { getUserById, updateUser } = require('~/models'); | ||
|
|
||
| /** | ||
| * A proxy in front of LibreChat may write the Authorization header itself (oauth2-proxy | ||
| * with --set-authorization-header, meshes and gateways doing credential injection), in | ||
| * which case the session token never arrives. JWT_AUTH_HEADER names a header to try | ||
| * first, holding the raw token with no scheme prefix. Unset, nothing changes. | ||
| */ | ||
| const jwtExtractor = () => { | ||
| const extractors = []; | ||
| if (process.env.JWT_AUTH_HEADER) { | ||
| extractors.push(ExtractJwt.fromHeader(process.env.JWT_AUTH_HEADER)); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When an operator configures a conventionally capitalized name such as Useful? React with πΒ / π.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch. |
||
| } | ||
| extractors.push(ExtractJwt.fromAuthHeaderAsBearerToken()); | ||
| return extractors.length > 1 ? ExtractJwt.fromExtractors(extractors) : extractors[0]; | ||
| }; | ||
|
|
||
| // JWT strategy | ||
| const jwtLogin = () => | ||
| new JwtStrategy( | ||
| { | ||
| jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), | ||
| jwtFromRequest: jwtExtractor(), | ||
| secretOrKey: process.env.JWT_SECRET, | ||
| }, | ||
| async (payload, done) => { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a proxy copies LibreChat's original
Authorizationvalue verbatim into the suggestedx-original-authorizationheader, the value isBearer <jwt>because LibreChat emits session credentials in that form (for example,packages/data-provider/src/headers-helpers.ts:11).ExtractJwt.fromHeaderdoes not remove the scheme, so authentication rejects the copied value, but this operator-facing documentation never says that the proxy must stripBearer. State that requirement here or make the alternate extractor accept both forms.Useful? React with πΒ / π.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved by accepting both forms: the extractor strips an optional
Bearerscheme (case-insensitive) before returning the token, so a proxy can copyAuthorizationverbatim..env.exampleandlibrechat.example.yamldocument it, andjwt.spec.tscovers raw,Bearerandbearervalues (898cdeb).