Skip to content

fix: resolve ApiToken reserved header exception (#146)#152

Merged
daniel-jonathan merged 2 commits intomainfrom
fix/creds-api-token
Nov 3, 2025
Merged

fix: resolve ApiToken reserved header exception (#146)#152
daniel-jonathan merged 2 commits intomainfrom
fix/creds-api-token

Conversation

@daniel-jonathan
Copy link
Contributor

@daniel-jonathan daniel-jonathan commented Oct 31, 2025

Fix ApiToken reserved header exception

Fixes #146

Problem

Using CredentialsMethod.ApiToken caused the application to crash with: Header 'Authorization' is a reserved HTTP header and should not be set via custom headers.

The issue: ApiToken was setting Authorization in DefaultHeaders, which then failed validation as a reserved header.

Solution

  • Handle ApiToken authorization via BuildHeaders() method instead of DefaultHeaders
  • Extract auth token retrieval to new GetAuthenticationTokenAsync() helper
  • Follows same pattern as OAuth credentials

Testing

Impact

  • No breaking changes - internal refactoring only
  • Users can now use ApiToken credentials without crashes
  • Code is cleaner and more maintainable

Summary by CodeRabbit

  • Bug Fixes
    • ApiToken credentials no longer trigger reserved header exceptions during configuration validation.
    • Improved authentication token handling to ensure consistent and reliable behavior for both ApiToken and OAuth credential configurations.

@daniel-jonathan daniel-jonathan requested a review from a team as a code owner October 31, 2025 17:35
@coderabbitai
Copy link

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

Refactors ApiToken and OAuth token handling in ApiClient to resolve a conflict where ApiToken credentials were incorrectly set in DefaultHeaders and rejected by validation. Introduces centralized token retrieval via GetAuthenticationTokenAsync and updates header construction logic to apply authorization tokens at request time rather than modifying DefaultHeaders, with comprehensive test coverage for ApiToken, OAuth, and no-credential scenarios.

Changes

Cohort / File(s) Summary
Changelog
CHANGELOG.md
Adds "Fixed" subsection documenting the resolution of issue #146 regarding ApiToken reserved header exception.
API Tests
src/OpenFga.Sdk.Test/Api/OpenFgaApiTests.cs
Adds unit test validating that ApiToken credentials do not trigger reserved header exceptions and do not set Authorization in DefaultHeaders after EnsureValid.
New ApiClient Test Suite
src/OpenFga.Sdk.Test/ApiClient/ApiClientTests.cs
New comprehensive test file with test helpers and scenarios covering ApiToken (Authorization header injection, DefaultHeaders preservation, custom header handling), OAuth (token exchange and Bearer token injection), and no-credential flows. Includes Configuration validation tests.
Core Implementation
src/OpenFga.Sdk/ApiClient/ApiClient.cs
Introduces GetAuthenticationTokenAsync to consolidate token retrieval for both OAuth and ApiToken. Removes direct DefaultHeaders modification for ApiToken in constructor. Refactors BuildHeaders to use case-insensitive dictionary and merge headers with defined precedence (DefaultHeaders → Auth token → Per-request headers). Updates SendRequestAsync to delegate token retrieval to centralized method.

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant Config as Configuration
    participant Client as ApiClient
    participant Auth as GetAuthenticationToken
    participant Build as BuildHeaders
    participant HTTP as HTTP Request

    Note over Client,HTTP: Before: Token in DefaultHeaders (FAILED)
    User->>Config: Create with ApiToken
    activate Config
    Config->>Client: new ApiClient(config)
    activate Client
    Client->>Client: DefaultHeaders.Add("Authorization", ...)
    Client->>Config: Validate
    activate Config
    Config-->>Config: ❌ Reserved header in DefaultHeaders
    Config-->>Client: Exception
    deactivate Config
    Client-->>User: Crash
    deactivate Client
    deactivate Config

    Note over Client,HTTP: After: Token applied at request time (FIXED)
    User->>Config: Create with ApiToken
    activate Config
    Config->>Client: new ApiClient(config)
    activate Client
    Client->>Config: Validate
    activate Config
    Config-->>Client: ✓ Valid (DefaultHeaders clean)
    deactivate Config
    Client-->>User: Success
    deactivate Client
    
    User->>Client: SendRequest
    activate Client
    Client->>Auth: GetAuthenticationTokenAsync
    activate Auth
    Auth-->>Client: Bearer token
    deactivate Auth
    Client->>Build: BuildHeaders(authToken)
    activate Build
    Build-->>Client: Merged headers<br/>(DefaultHeaders + Auth + Custom)
    deactivate Build
    Client->>HTTP: POST with Authorization header
    HTTP-->>Client: Response
    deactivate Client
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Focus areas requiring attention:
    • src/OpenFga.Sdk/ApiClient/ApiClient.cs: Verify the precedence logic in BuildHeaders (DefaultHeaders → Auth token → Per-request headers) correctly handles all credential scenarios and doesn't inadvertently override user headers.
    • Token retrieval flow in GetAuthenticationTokenAsync: Ensure OAuth error handling properly raises FgaApiAuthenticationError and doesn't break existing retry logic.
    • Constructor removal of DefaultHeaders modification for ApiToken: Confirm this change doesn't affect backward compatibility or break dependent code paths.
    • Case-insensitive dictionary usage in BuildHeaders: Verify HTTP header name handling is compliant across platforms.
    • Test file src/OpenFga.Sdk.Test/ApiClient/ApiClientTests.cs: Review mock HTTP handler setup and assertion counts to ensure tests exercise all code paths and edge cases (e.g., OAuth token refresh, concurrent requests).

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "fix: resolve ApiToken reserved header exception (#146)" accurately describes the primary change in the changeset. The core modification across all files involves moving ApiToken authorization handling from DefaultHeaders to BuildHeaders to prevent the reserved header validation error described in issue #146. The title is specific, clear, and directly related to the main objective of the changeset, making it immediately understandable to a developer reviewing the change history.
Linked Issues Check ✅ Passed The code changes comprehensively address the objectives of issue #146. The ApiToken authorization handling has been moved from DefaultHeaders to BuildHeaders, eliminating the reserved header validation error [#146]. A new GetAuthenticationTokenAsync() helper was introduced to consolidate token retrieval for both OAuth and ApiToken credentials, and the header construction logic now uses a consistent pattern that merges DefaultHeaders, authorization tokens, and per-request headers with proper precedence [#146]. The test additions include both a regression test validating that ApiToken no longer sets Authorization in DefaultHeaders and comprehensive ApiClient authentication tests covering ApiToken, OAuth, and no-credentials scenarios [#146]. All 234 existing tests pass and seven new authentication tests were added as documented in the PR objectives [#146].
Out of Scope Changes Check ✅ Passed All modifications in the pull request are directly related to fixing issue #146 and implementing comprehensive test coverage for the fix. The CHANGELOG.md entry documents the resolved issue, the ApiClient.cs refactoring addresses the core problem by moving ApiToken authorization from DefaultHeaders to BuildHeaders, and all test additions validate the fix across multiple authentication scenarios including ApiToken, OAuth, and no-credentials configurations. No unrelated feature additions, refactoring of unrelated code, or extraneous modifications are evident.
Docstring Coverage ✅ Passed Docstring coverage is 95.00% which is sufficient. The required threshold is 80.00%.

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.

ApiToken credentials no longer modify DefaultHeaders, avoiding
reserved header validation error.
@ewanharris ewanharris added this pull request to the merge queue Nov 3, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Nov 3, 2025
@daniel-jonathan daniel-jonathan added this pull request to the merge queue Nov 3, 2025
Merged via the queue into main with commit f1bc1e0 Nov 3, 2025
23 checks passed
@daniel-jonathan daniel-jonathan deleted the fix/creds-api-token branch November 3, 2025 19:50
daniel-jonathan added a commit that referenced this pull request Nov 10, 2025
* fix: resolve ApiToken reserved header exception (#146)

ApiToken credentials no longer modify DefaultHeaders, avoiding
reserved header validation error.

* fix/creds-api-token: CHANGELOG cleanup. Removed extraneous header.
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.

Using CredentialsMethod.ApiToken adds Authorization header which is not allowed according to Configuration

3 participants

Comments