feat: support custom OIDC token endpoint URL
Description
This PR addresses the inconsistency in how the JS SDK constructs the OIDC token endpoint URL (see https://github.com/openfga/sdk-generator/issues/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
apiTokenIssuernow accepts a full URL that can optionally include the scheme. If a scheme is not specified, it defaults tohttps://. - Added and updated unit tests to ensure backwards compatibility.
References
- closes https://github.com/openfga/js-sdk/issues/141
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
- [x] 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]
- [X] The correct base branch is being used, if not main
- [X] 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.
The committers listed above are authorized under a signed CLA.
- :white_check_mark: login: mikesouza / name: Mike Souza (ff53e647ac0bf4045b044f9fd66a6d8cf8ed3fa2, c218edbe4a2ed3b276a55e9eb623698b15037570)
[!IMPORTANT]
Review skipped
Auto incremental reviews are disabled on this repository.
Please check the settings in the CodeRabbit UI or the
.coderabbit.yamlfile in this repository. To trigger a single review, invoke the@coderabbitai reviewcommand.You can disable this status message by setting the
reviews.review_statustofalsein 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
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.tsfor all URL formats and issuer patterns mentioned in the issue - Scheme validation in
index.test.tsto confirm invalid schemes are properly rejected
- Logic in
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.
Comment @coderabbitai help to get the list of available commands and usage tips.
@mikesouza Thanks for the PR! We will get someone on the team to review.
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 https://github.com/openfga/js-sdk/pull/271
@ttrzeng Thanks for the feedback. I updated to follow a similar pattern using the this.normalizeApiTokenIssuer() as #271
@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!
@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. 🤞