Skip to content

📌 fix: Improve robustness for missing token and key expiry fields#65

Open
programmvilli wants to merge 1 commit into
mainfrom
fix-malformed-key
Open

📌 fix: Improve robustness for missing token and key expiry fields#65
programmvilli wants to merge 1 commit into
mainfrom
fix-malformed-key

Conversation

@programmvilli

@programmvilli programmvilli commented Jun 12, 2026

Copy link
Copy Markdown

Pull Request Template

⚠️ Before Submitting a PR, Please Review:

  • Please ensure that you have thoroughly read and understood the Contributing Docs before submitting your Pull Request.

⚠️ Documentation Updates Notice:

  • Kindly note that documentation updates are managed in this repository: librechat.ai

Summary

Please provide a brief summary of your changes and the related issue. Include any motivation and context that is relevant to your changes. If there are any dependencies necessary for your changes, please list them here.

Change Type

Please delete any irrelevant options.

  • [ x] Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update
  • Translation update

Testing

Please describe your test process and include instructions so that we can reproduce your test. If there are any important variables for your testing configuration, list them here.

Test Configuration:

We tested OIDC Bearer fallback and initialization under missing key expiration parameters utilizing the Jest test framework.

Test Process:
Scenario 1: Simulated selective cookie deletion (missing openid_id_token cookie) under an active browser session. Verified LibreChat falls back directly to the validated raw bearer token.
Scenario 2: Evaluated endpoint credentials with no expiration field in the request parameters. Verified retrieved credentials decrypted successfully without crashing.
How to Reproduce:
Run these commands from the root directory of your project:

Verify OIDC Token Strategy Fallback:

(Checks user fallback logic in openIdJwtStrategy.js)

Verify Endpoint Key Initialization:

(Checks key logic in [initialize.ts]

Variables:
NODE_ENV: test (Sets test profile context)
OPENAI_API_KEY: user_provided (Triggers user key collection)
OPENAI_REVERSE_PROXY: https://user-proxy.example.com/v1 (Provides a valid mock endpoint verification)

Checklist

Please delete any irrelevant options.

  • [x ] My code adheres to this project's style guidelines
  • I have performed a self-review of my own code
  • My changes do not introduce new warnings
  • I have written tests demonstrating that my changes are effective or that my feature works
  • Local unit tests pass with my changes

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Improved federated authentication token handling with better fallback logic when primary token sources are unavailable, ensuring more reliable user authentication flows.
    • Enhanced API key validation to properly handle user-provided API keys that lack expiration information, reducing potential configuration errors and improving overall reliability.

Ensure `id_token` is populated by falling back to the raw bearer token if explicitly missing from the IdP response. Allow user-provided API keys to be resolved even when the `expiresAt` field is absent.
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR addresses two independent concerns: OpenID JWT token handling now falls back to raw Bearer tokens when ID tokens are missing, and OpenAI initialization decouples user input presence from expiry validation, with test coverage for missing expiry fields.

Changes

OpenID JWT Token Fallback

Layer / File(s) Summary
ID token fallback implementation and test
api/strategies/openIdJwtStrategy.js, api/strategies/openIdJwtStrategy.spec.js
federatedTokens.id_token now uses idToken || rawToken fallback instead of idToken alone, ensuring consistent fallback behavior across token fields. Test updated to expect the raw Bearer token when neither session nor cookies provide an ID token.

OpenAI Initialization Expiry Validation

Layer / File(s) Summary
Expiry validation refactoring and missing expiry test
packages/api/src/endpoints/openai/initialize.ts, packages/api/src/endpoints/openai/initialize.spec.ts
Conditional logic refactored to check user-provided inputs separately from expiry presence, deferring checkUserKeyExpiry only when expiresAt is truthy. New test verifies stored user key resolution succeeds when the expiry field is absent.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

When tokens fall back to the Bearer's way,
And expiry guards the keys at play,
Validation refactored, clean and bright,
Fallbacks aligned, the logic's right! 🔐✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: improving robustness for missing token and key expiry fields, which directly corresponds to the OIDC id_token fallback and OpenAI key expiry field handling in the changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description follows the template structure and includes essential sections, though the Summary section lacks detailed explanation of the changes and their motivation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-malformed-key

Comment @coderabbitai help to get the list of available commands and usage tips.

@programmvilli programmvilli requested a review from Ivan-Apro June 12, 2026 14:01

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/api/src/endpoints/openai/initialize.spec.ts (1)

118-143: ⚡ Quick win

Assert that expiry validation is explicitly skipped in the missing-expiry path.

This test should also verify checkUserKeyExpiry is not called, so the exact guard behavior is locked down.

Suggested patch
 import type { BaseInitializeParams } from '~/types';
 
 const mockValidateEndpointURL = jest.fn();
+const mockCheckUserKeyExpiry = jest.fn();
 jest.mock('~/auth', () => ({
   validateEndpointURL: (...args: unknown[]) => mockValidateEndpointURL(...args),
 }));
@@
 jest.mock('~/utils', () => ({
   getAzureCredentials: jest.fn(),
   resolveHeaders: jest.fn(() => ({})),
   isUserProvided: (val: string) => val === 'user_provided',
-  checkUserKeyExpiry: jest.fn(),
+  checkUserKeyExpiry: (...args: unknown[]) => mockCheckUserKeyExpiry(...args),
 }));
@@
     expect(params.db.getUserKeyValues).toHaveBeenCalledWith({
       userId: 'user-1',
       name: EModelEndpoint.openAI,
     });
+    expect(mockCheckUserKeyExpiry).not.toHaveBeenCalled();
     expect(mockValidateEndpointURL).not.toHaveBeenCalled();
     expect(mockGetOpenAIConfig).toHaveBeenCalledWith(
       'sk-user-key',
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/api/src/endpoints/openai/initialize.spec.ts` around lines 118 - 143,
Add an assertion in the test "should resolve a stored user key even when the
expiry field is missing" to assert that checkUserKeyExpiry is not invoked;
locate the test in initialize.spec.ts and after the initializeOpenAI call (but
before restoring mocks) add expect(checkUserKeyExpiry).not.toHaveBeenCalled() so
the missing-expiry code path explicitly skips expiry validation; reference the
checkUserKeyExpiry symbol and the initializeOpenAI test block to place the
assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/api/src/endpoints/openai/initialize.spec.ts`:
- Around line 118-143: Add an assertion in the test "should resolve a stored
user key even when the expiry field is missing" to assert that
checkUserKeyExpiry is not invoked; locate the test in initialize.spec.ts and
after the initializeOpenAI call (but before restoring mocks) add
expect(checkUserKeyExpiry).not.toHaveBeenCalled() so the missing-expiry code
path explicitly skips expiry validation; reference the checkUserKeyExpiry symbol
and the initializeOpenAI test block to place the assertion.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 72fe85bc-2482-495f-a37c-6ff238a5e7da

📥 Commits

Reviewing files that changed from the base of the PR and between 566e20b and bdd2c69.

📒 Files selected for processing (4)
  • api/strategies/openIdJwtStrategy.js
  • api/strategies/openIdJwtStrategy.spec.js
  • packages/api/src/endpoints/openai/initialize.spec.ts
  • packages/api/src/endpoints/openai/initialize.ts

@programmvilli programmvilli removed the request for review from Ivan-Apro June 15, 2026 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant