fix: Add federated token propagation to OIDC authentication strategies

Adds federatedTokens object to user during authentication to enable
federated provider token template variables in LibreChat configuration.

Changes:
- OpenID JWT Strategy: Extract raw JWT from Authorization header and
  attach as federatedTokens.access_token to enable {{LIBRECHAT_OPENID_TOKEN}}
  placeholder resolution
- OpenID Strategy: Attach tokenset tokens as federatedTokens object to
  standardize token access across both authentication strategies

This enables proper token propagation for custom endpoints and MCP
servers that require federated provider tokens for authorization.

Resolves missing token issue reported by @ramden in PR #9931

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Denis Ramic <denis.ramic@nfon.com>
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jón Levy 2025-10-16 11:46:59 +00:00
parent aca4bba02d
commit 5874ba29ff
No known key found for this signature in database
2 changed files with 24 additions and 2 deletions

View file

@ -40,13 +40,19 @@ const openIdJwtLogin = (openIdConfig) => {
{ {
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
secretOrKeyProvider: jwksRsa.passportJwtSecret(jwksRsaOptions), secretOrKeyProvider: jwksRsa.passportJwtSecret(jwksRsaOptions),
passReqToCallback: true, // Pass request to callback to access raw token
}, },
/** /**
* @param {Express.Request} req
* @param {import('openid-client').IDToken} payload * @param {import('openid-client').IDToken} payload
* @param {import('passport-jwt').VerifyCallback} done * @param {import('passport-jwt').VerifyCallback} done
*/ */
async (payload, done) => { async (req, payload, done) => {
try { try {
// Extract the raw JWT token from the Authorization header
const authHeader = req.headers.authorization;
const rawToken = authHeader?.replace('Bearer ', '');
const { user, error, migration } = await findOpenIDUser({ const { user, error, migration } = await findOpenIDUser({
findUser, findUser,
email: payload?.email, email: payload?.email,
@ -77,6 +83,14 @@ const openIdJwtLogin = (openIdConfig) => {
await updateUser(user.id, updateData); await updateUser(user.id, updateData);
} }
// Add federated tokens for OIDC placeholder processing
// Use the raw JWT token as the access token
user.federatedTokens = {
access_token: rawToken,
refresh_token: payload.refresh_token,
expires_at: payload.exp,
};
done(null, user); done(null, user);
} else { } else {
logger.warn( logger.warn(

View file

@ -491,7 +491,15 @@ async function setupOpenId() {
}, },
); );
done(null, { ...user, tokenset }); done(null, {
...user,
tokenset,
federatedTokens: {
access_token: tokenset.access_token,
refresh_token: tokenset.refresh_token,
expires_at: tokenset.expires_at,
},
});
} catch (err) { } catch (err) {
logger.error('[openidStrategy] login failed', err); logger.error('[openidStrategy] login failed', err);
done(err); done(err);