Skip to content

Conversation

@OsmanMElsayed
Copy link
Contributor

@OsmanMElsayed OsmanMElsayed commented Oct 30, 2025

Description

What problem is being solved?

openfga/sdk-generator#238

How is it being solved?

Allow the consume to provide a URL with a path component when setting the ApiTokenIssuer value, otherwise default to /oauth/token.

The behavior of the ApiTokenIssuer matches the expectations defined in the following table:

ApiTokenIssuer Endpoint SDK will hit
issuer.fga.example https://issuer.fga.example/oauth/token
https://issuer.fga.example https://issuer.fga.example/oauth/token
https://issuer.fga.example:8080 https://issuer.fga.example:8080/oauth/token
issuer.fga.example/some_endpoint https://issuer.fga.example/some_endpoint
https://issuer.fga.example/some_endpoint https://issuer.fga.example/some_endpoint
https://issuer.fga.example:8080/some_endpoint https://issuer.fga.example:8080/some_endpoint

What changes are made to solve it?

References

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

  • Bug Fixes

    • Improved API token issuer handling with automatic URL scheme normalization and consistent token endpoint path resolution.
  • Tests

    • Added comprehensive test coverage for token issuer normalization and API token endpoint path handling.

@OsmanMElsayed OsmanMElsayed requested a review from a team as a code owner October 30, 2025 22:33
Copilot AI review requested due to automatic review settings October 30, 2025 22:33
@coderabbitai
Copy link

coderabbitai bot commented Oct 30, 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.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This PR implements configurable OAuth2 token endpoint handling by normalizing the ApiTokenIssuer configuration to accept full URLs with optional schemes, ports, and custom paths. The normalization logic automatically prefixes HTTPS when no scheme is provided and constructs the complete token endpoint URI by appending a default /oauth/token path when needed.

Changes

Cohort / File(s) Summary
Type alias introduction for test consistency
src/OpenFga.Sdk.Test/Api/OpenFgaApiTests.cs, src/OpenFga.Sdk.Test/ApiClient/OAuth2ClientTests.cs
Introduced SdkConfiguration type alias for Configuration.Configuration and updated all instantiations to use the alias throughout tests for improved readability.
New token issuer normalization utility
src/OpenFga.Sdk/Configuration/ApiTokenIssuerNormalizer.cs
Added internal static class ApiTokenIssuerNormalizer with Normalize(string) method to standardize token issuer URLs by prefixing HTTPS scheme when absent and returning null for empty/whitespace input.
Updated OAuth2 client token endpoint handling
src/OpenFga.Sdk/ApiClient/OAuth2Client.cs
Modified OAuth2Client constructor to normalize ApiTokenIssuer and construct full token endpoint URI; added DEFAULT_API_TOKEN_ISSUER_PATH constant; changed ExchangeTokenAsync to use normalized issuer as BasePath with empty PathTemplate and append default path when needed.
Enhanced credentials validation
src/OpenFga.Sdk/Configuration/Credentials.cs
Updated IClientCredentialsConfig interface to remove explicit public modifiers on properties; enhanced EnsureValid() method to use ApiTokenIssuerNormalizer for validation; refined IsWellFormedUriString helper to support nullable input and integrate with normalization flow.
New test coverage for normalization
src/OpenFga.Sdk.Test/Configuration/ApiTokenIssuerNormalizerTests.cs
Added new test class ApiTokenIssuerNormalizerTests with theory-based test Normalize_ReturnsExpectedResult covering null/empty, schemes, ports, paths, and various HTTPS/HTTP combinations.
Extended OAuth2 client tests
src/OpenFga.Sdk.Test/ApiClient/OAuth2ClientTests.cs
Added new test region ApiTokenIssuer Path Handling with theory-based tests validating token issuer path normalization and constructed token request URI across multiple scenarios.

Sequence Diagram

sequenceDiagram
    participant Config as OAuth2 Configuration
    participant Client as OAuth2Client
    participant Normalizer as ApiTokenIssuerNormalizer
    participant Validator as Credentials.EnsureValid()

    Config->>Normalizer: ApiTokenIssuer (raw input)
    Note over Normalizer: Normalize: add https:// if no scheme
    Normalizer-->>Client: normalized issuer URL
    
    Client->>Client: Parse URL (extract host/port/path)
    alt Path is empty or "/"
        Client->>Client: Append "/oauth/token"
    end
    Client->>Client: Store as _apiTokenIssuer
    
    Config->>Validator: Validate ApiTokenIssuer
    Validator->>Normalizer: Normalize for validation
    Normalizer-->>Validator: normalized URL
    Validator->>Validator: Validate with IsWellFormedUriString
    alt Invalid
        Validator-->>Config: FgaValidationError
    else Valid
        Validator-->>Config: ✓
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • OAuth2Client.cs: New normalization and URL construction logic requires careful review of URI parsing and path appending behavior to ensure all configuration formats are handled correctly
  • ApiTokenIssuerNormalizer.cs: Verify scheme prefixing logic and edge cases (null, whitespace, URLs with paths)
  • Credentials.cs: Interface signature changes and integration of normalization into validation flow needs verification for backward compatibility
  • Test files: New test regions should cover the full matrix of token issuer configurations from the linked issue

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • evansims
  • ewanharris

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The PR includes minor type alias refactoring in test files (src/OpenFga.Sdk.Test/Api/OpenFgaApiTests.cs and src/OpenFga.Sdk.Test/ApiClient/OAuth2ClientTests.cs) where Configuration.Configuration is aliased to SdkConfiguration. While this improves code readability in test code, these changes are not directly related to the ApiTokenIssuer feature requirements specified in the linked issues and represent collateral refactoring that falls outside the stated objectives. The core feature implementation in OAuth2Client, Credentials, and the new ApiTokenIssuerNormalizer remains properly scoped to the feature requirements. Consider removing the type alias refactoring (the SdkConfiguration alias introductions in OpenFgaApiTests.cs and the broader usage changes) or moving these changes to a separate, dedicated code quality improvement PR. The type alias changes are not required to implement the ApiTokenIssuer feature and should be decoupled from this feature work to maintain scope clarity. The core feature implementation itself is complete and solid.
Docstring Coverage ⚠️ Warning Docstring coverage is 69.23% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "feat: Allow the api token issuer to be a fully qualified url with a path component" accurately and concisely describes the primary objective of this changeset. The implementation demonstrates that the SDK now supports ApiTokenIssuer as a full URL with optional path components, defaulting to /oauth/token when no path is provided, which is exactly what the title conveys. The title is specific enough to clearly communicate the main change without being overly verbose or generic.
Linked Issues Check ✅ Passed
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

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR allows the API token issuer to accept a fully qualified URL with a path component. Previously, the SDK only supported domain-based issuer values and automatically appended /oauth/token. Now consumers can provide custom paths in the issuer URL while maintaining backward compatibility with domain-only configurations.

  • Normalizes API token issuer URLs by adding https:// scheme when missing and preserving custom paths
  • Updates OAuth2Client to handle full URLs instead of constructing them from domain fragments
  • Adds comprehensive test coverage for various issuer URL formats

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/OpenFga.Sdk/Configuration/Credentials.cs Updates interface properties and validation logic to use new URL normalizer
src/OpenFga.Sdk/Configuration/ApiTokenIssuerNormalizer.cs New utility class that normalizes issuer URLs by adding scheme when missing
src/OpenFga.Sdk/ApiClient/OAuth2Client.cs Modifies token exchange logic to use normalized URLs with path handling
src/OpenFga.Sdk.Test/Configuration/ApiTokenIssuerNormalizerTests.cs Test coverage for URL normalization functionality
src/OpenFga.Sdk.Test/ApiClient/OAuth2ClientTests.cs Test coverage for OAuth2Client path handling and alias fix for Configuration
src/OpenFga.Sdk.Test/Api/OpenFgaApiTests.cs Updates Configuration class usage to use alias for consistency

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

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: 2

🧹 Nitpick comments (1)
src/OpenFga.Sdk/ApiClient/OAuth2Client.cs (1)

101-112: Consider simplifying the AbsolutePath check.

The check string.IsNullOrWhiteSpace(normalizedApiTokenIssuerUri.AbsolutePath) on line 109 may be redundant. For absolute URIs, the AbsolutePath property always returns at least "/" and never null or whitespace according to .NET documentation. You could simplify this to just check normalizedApiTokenIssuerUri.AbsolutePath.Equals("/").

Apply this diff to simplify the condition:

-        var normalizedApiTokenIssuerUriWithPath = string.IsNullOrWhiteSpace(normalizedApiTokenIssuerUri.AbsolutePath) || normalizedApiTokenIssuerUri.AbsolutePath.Equals("/")
+        var normalizedApiTokenIssuerUriWithPath = normalizedApiTokenIssuerUri.AbsolutePath.Equals("/")
             ? new Uri(normalizedApiTokenIssuerUri, DEFAULT_API_TOKEN_ISSUER_PATH)
             : normalizedApiTokenIssuerUri;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d596eeb and e965563.

📒 Files selected for processing (6)
  • src/OpenFga.Sdk.Test/Api/OpenFgaApiTests.cs (27 hunks)
  • src/OpenFga.Sdk.Test/ApiClient/OAuth2ClientTests.cs (8 hunks)
  • src/OpenFga.Sdk.Test/Configuration/ApiTokenIssuerNormalizerTests.cs (1 hunks)
  • src/OpenFga.Sdk/ApiClient/OAuth2Client.cs (3 hunks)
  • src/OpenFga.Sdk/Configuration/ApiTokenIssuerNormalizer.cs (1 hunks)
  • src/OpenFga.Sdk/Configuration/Credentials.cs (5 hunks)
🧰 Additional context used
🧬 Code graph analysis (5)
src/OpenFga.Sdk/ApiClient/OAuth2Client.cs (2)
src/OpenFga.Sdk/Configuration/ApiTokenIssuerNormalizer.cs (2)
  • ApiTokenIssuerNormalizer (5-29)
  • Normalize (14-28)
src/OpenFga.Sdk/ApiClient/RequestBuilder.cs (1)
  • Uri (87-98)
src/OpenFga.Sdk.Test/Configuration/ApiTokenIssuerNormalizerTests.cs (2)
src/OpenFga.Sdk.Test/ApiClient/OAuth2ClientTests.cs (1)
  • Theory (310-357)
src/OpenFga.Sdk/Configuration/ApiTokenIssuerNormalizer.cs (2)
  • ApiTokenIssuerNormalizer (5-29)
  • Normalize (14-28)
src/OpenFga.Sdk.Test/Api/OpenFgaApiTests.cs (1)
src/OpenFga.Sdk/Configuration/Configuration.cs (2)
  • Configuration (11-216)
  • Configuration (18-24)
src/OpenFga.Sdk.Test/ApiClient/OAuth2ClientTests.cs (3)
src/OpenFga.Sdk/Configuration/Configuration.cs (2)
  • Configuration (11-216)
  • Configuration (18-24)
src/OpenFga.Sdk.Test/Configuration/ApiTokenIssuerNormalizerTests.cs (1)
  • Theory (7-26)
src/OpenFga.Sdk/ApiClient/OAuth2Client.cs (5)
  • Task (133-161)
  • Task (163-197)
  • Task (204-213)
  • OAuth2Client (20-216)
  • OAuth2Client (87-126)
src/OpenFga.Sdk/Configuration/Credentials.cs (2)
src/OpenFga.Sdk.Test/ApiClient/OAuth2ClientTests.cs (1)
  • Credentials (32-46)
src/OpenFga.Sdk/Configuration/ApiTokenIssuerNormalizer.cs (2)
  • ApiTokenIssuerNormalizer (5-29)
  • Normalize (14-28)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: Test net8.0 on ubuntu-latest
  • GitHub Check: Test netcoreapp3.1 on windows-latest
  • GitHub Check: Test net8.0 on windows-latest
  • GitHub Check: Test net48 on windows-latest
  • GitHub Check: Test net8.0 on macos-latest
  • GitHub Check: Test net9.0 on ubuntu-latest
  • GitHub Check: Analyze (csharp)
🔇 Additional comments (10)
src/OpenFga.Sdk.Test/Api/OpenFgaApiTests.cs (1)

19-19: LGTM! Type alias improves code readability.

The introduction of the SdkConfiguration alias and its consistent use throughout the test file improves readability without changing functionality.

src/OpenFga.Sdk/Configuration/ApiTokenIssuerNormalizer.cs (1)

14-28: LGTM! The normalization logic is correct.

The implementation correctly handles null/whitespace input and prepends https:// when no scheme is present.

src/OpenFga.Sdk/ApiClient/OAuth2Client.cs (1)

134-140: LGTM! Token endpoint construction is correct.

Using the pre-constructed _apiTokenIssuer as BasePath with an empty PathTemplate correctly implements the configurable token endpoint feature.

src/OpenFga.Sdk.Test/ApiClient/OAuth2ClientTests.cs (2)

15-15: LGTM! Type alias improves consistency.

The SdkConfiguration alias aligns with the same change in OpenFgaApiTests.cs and improves code readability.


308-357: LGTM! Comprehensive test coverage for token issuer path handling.

The test thoroughly validates the ApiTokenIssuer normalization behavior across various scenarios:

  • URLs with/without schemes
  • URLs with/without ports
  • URLs with/without custom paths
  • URLs with trailing slashes

The test correctly captures the actual request URI and asserts it against expected values.

src/OpenFga.Sdk.Test/Configuration/ApiTokenIssuerNormalizerTests.cs (1)

7-26: Good test coverage for normalization behavior.

The test cases comprehensively cover the expected normalization scenarios including edge cases like null/empty input, domains without schemes, domains with ports and paths.

src/OpenFga.Sdk/Configuration/Credentials.cs (4)

53-67: LGTM! Excellent documentation improvements.

The enhanced documentation clearly explains the normalization behavior with helpful examples. This aligns well with the PR objectives and will help users understand how to configure the ApiTokenIssuer.


104-106: Verify constructor exception behavior is acceptable.

The public parameterless constructor now calls EnsureValid(), which can throw FgaRequiredParamError or FgaValidationError during object construction. Ensure this aligns with your error handling strategy, as some developers prefer constructors not to throw (preferring lazy validation instead).

If this is intentional and documented, this is acceptable. Otherwise, consider moving validation to when the credentials are actually used.


147-154: LGTM! Validation logic correctly normalizes before checking.

The validation properly normalizes the ApiTokenIssuer using ApiTokenIssuerNormalizer.Normalize before validating it with IsWellFormedUriString. This ensures consistent validation behavior.


163-167: LGTM! URI validation logic is correct.

The updated IsWellFormedUriString method correctly handles nullable input and validates that the URI has a valid HTTP/HTTPS scheme.

@OsmanMElsayed OsmanMElsayed force-pushed the feat/allow-api-token-issuer-with-path branch from e965563 to 6cf3ecc Compare October 30, 2025 22:51
rhamzeh
rhamzeh previously approved these changes Nov 4, 2025
Copy link
Member

@rhamzeh rhamzeh left a comment

Choose a reason for hiding this comment

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

Nice! Thanks @OsmanMElsayed!

Copy link
Member

@rhamzeh rhamzeh left a comment

Choose a reason for hiding this comment

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

Actually before merging, would you mind updating the README and adding a brief note to the unreleased section in the Changelog?

We haven't updated the READMEs of the rest of the SDKs but we should.

We can be as brief as possible, so something as simple as in the ClientCredentials example, adding a comment:

// API Token Issuer can contain:
// - a scheme, defaults to https
// - a path, defaults to /oauth/token
// - a port
ApiTokenIssuer = Environment.GetEnvironmentVariable("FGA_API_TOKEN_ISSUER"),

@rhamzeh rhamzeh dismissed their stale review November 4, 2025 14:39

Dismissing approval just till Changelog and README are updated

@OsmanMElsayed OsmanMElsayed requested review from a team as code owners November 4, 2025 15:08
@OsmanMElsayed
Copy link
Contributor Author

OsmanMElsayed commented Nov 4, 2025

Actually before merging, would you mind updating the README and adding a brief note to the unreleased section in the Changelog?

We haven't updated the READMEs of the rest of the SDKs but we should.

We can be as brief as possible, so something as simple as in the ClientCredentials example, adding a comment:

// API Token Issuer can contain:
// - a scheme, defaults to https
// - a path, defaults to /oauth/token
// - a port
ApiTokenIssuer = Environment.GetEnvironmentVariable("FGA_API_TOKEN_ISSUER"),

Done ✔️ . @rhamzeh

@rhamzeh rhamzeh enabled auto-merge November 6, 2025 11:30
@rhamzeh rhamzeh added this pull request to the merge queue Nov 6, 2025
Merged via the queue into openfga:main with commit e7a67f3 Nov 6, 2025
22 checks passed
@OsmanMElsayed OsmanMElsayed deleted the feat/allow-api-token-issuer-with-path branch November 7, 2025 20:04
daniel-jonathan pushed a commit that referenced this pull request Nov 10, 2025
…ath component (#151)

* feat: Allow the api token issuer to be a fully qualified url with a path component

* chore: Address PR comment
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.

PathTemplate auth/token hardcoded in OAuth2Client ExchangeTokenAsync method

2 participants