Skip to content

Conversation

@mikesouza
Copy link

@mikesouza mikesouza commented Nov 12, 2025

Description

This PR addresses the inconsistency in how the JS SDK constructs the OIDC token endpoint URL (see openfga/sdk-generator#238), so that it is inline with how the Go and other SDKs work.

  • Supports custom token endpoint paths specified by the apiTokenIssuer.
  • Configuration of the apiTokenIssuer now accepts a full URL that can optionally include the scheme. If a scheme is not specified, it defaults to https://.
  • Added and updated unit tests to ensure backwards compatibility.

References

NOTE: This PR #271 seems to be outdated and the author doesn't seem to be working on it, so I decided to submit my own PR.

Review Checklist

  • I have clicked on "allow edits by maintainers".
  • I have added documentation for new/changed functionality in this PR or in a PR to openfga.dev [Provide a link to any relevant PRs in the references section above]
  • The correct base branch is being used, if not main
  • I have added tests to validate that the change in functionality is working as expected

Summary by CodeRabbit

  • Improvements

    • Enhanced credential handling to support flexible API token issuer formats, including automatic endpoint path normalization and improved validation for various URL schemes.
  • Tests

    • Added comprehensive test coverage for token endpoint resolution, validating multiple issuer formats, URL schemes, and endpoint path handling.

@mikesouza mikesouza requested a review from a team as a code owner November 12, 2025 17:56
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Nov 12, 2025

CLA Signed

The committers listed above are authorized under a signed CLA.

@coderabbitai
Copy link

coderabbitai bot commented Nov 12, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

The changes implement intelligent OIDC token endpoint URL construction by introducing a helper method that parses and normalizes apiTokenIssuer inputs, defaulting the path to oauth/token when missing. This replaces hard-coded URL construction in validation and token refresh logic. Tests validate multiple URL formats, schemes, and path resolution scenarios.

Changes

Cohort / File(s) Summary
URL endpoint construction
credentials/credentials.ts
Added DEFAULT_TOKEN_ENDPOINT_PATH constant and new private buildApiTokenUrl() method to intelligently parse and normalize token endpoint URLs; updated validation and refresh token logic to use the new builder.
Token refresh tests
tests/credentials.test.ts
Added comprehensive test suite for access token refresh covering multiple API token issuer formats, base URL resolution, endpoint path handling, query parameters, and port numbers.
Validation tests
tests/index.test.ts
Converted single boolean assertion for apiTokenIssuer to parametric tests validating valid schemes (https://, http://, empty) and invalid schemes (tcp://, grpc://, file://).

Sequence Diagram

sequenceDiagram
    participant Caller
    participant Credentials
    participant buildApiTokenUrl
    participant TokenEndpoint

    Caller->>Credentials: getAccessTokenHeader() or isValid()
    Credentials->>buildApiTokenUrl: buildApiTokenUrl(apiTokenIssuer)
    
    alt Valid URL with scheme
        buildApiTokenUrl->>buildApiTokenUrl: Parse URL
        buildApiTokenUrl->>buildApiTokenUrl: Check if path exists
        alt Path missing or empty
            buildApiTokenUrl->>buildApiTokenUrl: Append /oauth/token
        end
        buildApiTokenUrl-->>Credentials: Return normalized URL
    else Invalid URL
        buildApiTokenUrl-->>Credentials: Return empty string
    end
    
    Credentials->>TokenEndpoint: POST normalized endpoint URL
    TokenEndpoint-->>Credentials: Access token response
    Credentials-->>Caller: Token or validation result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20–25 minutes

  • Focus areas for review:
    • Logic in buildApiTokenUrl() for URL parsing, scheme handling, and path normalization—verify it correctly handles edge cases (missing schemes, empty paths, malformed URLs)
    • Validation changes in isValid() and token refresh flow to ensure the new helper is applied consistently
    • Test coverage in credentials.test.ts for all URL formats and issuer patterns mentioned in the issue
    • Scheme validation in index.test.ts to confirm invalid schemes are properly rejected

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: support custom OIDC token endpoint URL' accurately describes the main change: adding support for custom token endpoint paths in OIDC authentication.
Linked Issues check ✅ Passed The PR implements all key objectives from #141: defaulting https:// scheme when missing, accepting custom token endpoint paths, avoiding unconditional path appending, and maintaining backwards compatibility via updated tests.
Out of Scope Changes check ✅ Passed All changes (buildApiTokenUrl method, DEFAULT_TOKEN_ENDPOINT_PATH constant, validation updates, and test expansions) are directly scoped to support custom OIDC token endpoint URLs as specified in #141.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
credentials/credentials.ts (1)

234-251: Fix JWT audience construction to respect the scheme in apiTokenIssuer.

Line 249 hardcodes the JWT audience as https://${config.apiTokenIssuer}/, which always forces the https:// scheme. This contradicts the new flexible URL handling in buildApiTokenUrl (lines 150-151), which respects the actual scheme—adding https:// only when no scheme is present.

The test suite confirms multiple schemes are intentionally supported (tests/index.test.ts:64). If apiTokenIssuer is set to http://issuer.example.com, the token endpoint respects this, but the JWT audience incorrectly forces it to https://issuer.example.com/, creating a mismatch that violates OAuth 2.0 spec requirements for the audience claim.

Fix: Extract or derive the issuer base URL using the same scheme-handling logic as buildApiTokenUrl, rather than hardcoding https://.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 847b9ff and 25729ee.

📒 Files selected for processing (3)
  • credentials/credentials.ts (3 hunks)
  • tests/credentials.test.ts (1 hunks)
  • tests/index.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (3)
tests/credentials.test.ts (4)
telemetry/configuration.ts (1)
  • TelemetryConfiguration (44-156)
credentials/credentials.ts (2)
  • DEFAULT_TOKEN_ENDPOINT_PATH (40-40)
  • Credentials (42-272)
tests/helpers/default-config.ts (3)
  • OPENFGA_API_AUDIENCE (8-8)
  • OPENFGA_CLIENT_ID (9-9)
  • OPENFGA_CLIENT_SECRET (10-10)
credentials/types.ts (1)
  • AuthCredentialsConfig (98-107)
credentials/credentials.ts (2)
validation.ts (1)
  • isWellFormedUriString (18-26)
credentials/types.ts (1)
  • ClientCredentialsConfig (75-75)
tests/index.test.ts (2)
tests/helpers/default-config.ts (1)
  • baseConfig (41-54)
configuration.ts (1)
  • Configuration (58-202)
🔇 Additional comments (7)
credentials/credentials.ts (2)

40-41: LGTM!

The constant is well-defined and provides a clear default for the token endpoint path.


169-171: LGTM!

The token refresh flow now correctly uses the new URL builder helper.

tests/credentials.test.ts (3)

1-15: LGTM!

Test setup is well-structured with proper imports and network isolation using nock.


16-81: LGTM!

Comprehensive test cases covering various URL formats, schemes, paths, query parameters, and port numbers. The test descriptions are clear and align well with the PR objectives.


83-118: LGTM!

The parameterized test implementation is clean and properly verifies that the token endpoint is called with the correct base URL and path. Good use of nock for mocking and proper cleanup.

tests/index.test.ts (2)

64-77: LGTM!

Parameterized test properly validates that valid schemes (https://, http://, and empty/default) are accepted during construction. Good coverage of the intended behavior.


79-92: Good test coverage for invalid schemes.

The test properly validates that invalid schemes are rejected. Note that this test's effectiveness depends on buildApiTokenUrl properly validating schemes (see my comment on credentials/credentials.ts lines 148-163 about adding scheme validation).

@mikesouza mikesouza force-pushed the feat/custom-token-endpoint-url branch from 25729ee to 38392a1 Compare November 12, 2025 18:57
@mikesouza mikesouza force-pushed the feat/custom-token-endpoint-url branch from 38392a1 to 414e4d2 Compare November 12, 2025 19:06
@dyeam0
Copy link
Member

dyeam0 commented Nov 12, 2025

@mikesouza Thanks for the PR! We will get someone on the team to review.

@ttrzeng
Copy link

ttrzeng commented Nov 13, 2025

With this PR we now normalize the token endpoint URL via buildApiTokenUrl(apiTokenIssuer), including handling full URLs and custom paths, but the PrivateKeyJWT aud is still built as https://${apiTokenIssuer}/.

That means:

For domain-only issuers (issuer.fga.example) the token endpoint might be https://issuer.fga.example/oauth/token, but the JWT aud stays https://issuer.fga.example/.

For full URLs like https://issuer.fga.example/custom/path, token URL is normalized correctly, but the audience is still effectively “host only” (https://issuer.fga.example/), which may or may not match what non-Auth0 providers expect.

In #271 the normalization helper was reused for the audience as well (so audience matches the same normalization rules as the token URL).

Either:

Reuse the same normalization helper here for aud, or

Explicitly document in README that apiTokenIssuer must resolve to a bare host when using PrivateKeyJWT, and that only the token endpoint URL is customizable.

Right now it feels like we’re only halfway towards “fully support non-standard OIDC providers.”

Reference from #271
Screenshot 2025-11-13 at 10 54 38 AM

@mikesouza
Copy link
Author

@ttrzeng Thanks for the feedback. I updated to follow a similar pattern using the this.normalizeApiTokenIssuer() as #271

@mikesouza mikesouza requested a review from ttrzeng November 14, 2025 21:29
@daniel-jonathan
Copy link

@mikesouza I reviewed the updates you made from the feedback. There is an error in one of the test runs. Please review and update it with a fix. I have approved the PR in general.

Thank you, and solid work!

auto-merge was automatically disabled November 21, 2025 17:38

Head branch was pushed to by a user without write access

@mikesouza
Copy link
Author

mikesouza commented Nov 21, 2025

@daniel-jonathan Thanks for the re-review!

Hmmm strange, the unit tests all pass on my local machine, but it looks like the test failures in CI are related to the 15 tests that use nock 🤔 .... I pushed a change to use afterEach() and mirror how the other test suites use nock as closely as possible, so hopefully that fixes it. 🤞

image

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.

Inconsistency in OIDC token path construction between SDKs (and incompaibility with custom token paths)

5 participants