Skip to content

fix(oauth2): the authorization_code grant authenticates the client (0.5.0-rc69) - #323

Merged
ciresnave-bot merged 1 commit into
release/0.5.xfrom
fix/code-grant-client-auth-0.5.x
Oct 27, 2026
Merged

ciresnave-bot merged 1 commit into
release/0.5.xfrom
fix/code-grant-client-auth-0.5.x

Conversation

@ciresnave-bot

@ciresnave-bot ciresnave-bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

Backport of main's 04a4f48 (#140) to release/0.5.x, which never had it. On this line POST /oauth/token accepted a code exchange for a confidential client as long as the request carried some client_secret (only req.client_secret.is_none() was checked), so anyone holding an authorization code and the client_id could redeem it. The client is now authenticated before the code is read; a failed authentication neither reveals nor consumes the code; a code issued to another client is refused and left intact; public clients are decided by their registration and must use PKCE.

Re-applied by hand (the 0.5.x file lacks the helpers main already had: load_client_record, refusal, client_secret_of are added with ClientKind and authenticate_token_client). Compares the stored plain secret in constant time; the #90 hashing backport follows separately.

Red first, in Docker (rust:latest, --features api-server, jobs=2): with only the ported test file added, 5 of its 7 tests fail on the current 0.5.x code; with the fix all 7 pass. Regression, same feature set plus axum-integration: auth_flow_tests 12, oauth2_integration_test 11, oauth_advanced_tests 19 pass. cargo fmt --all -- --check clean. Not ported: the three tests of the atomic code/refresh claims (a separate change not on this line). Not run: the rest of the suite.

Version 0.5.0-rc69 (PM-allocated); base is release/0.5.x, so the PM merges by hand. GHSA and RustSec follow once the fix is live.

🤖 Generated with Claude Code

https://claude.ai/code/session_013YEhSGGFctL3d4hGevi7tC

Summary by Sourcery

Secure authorization-code exchanges by authenticating the registered client before redeeming authorization codes.

Bug Fixes:

  • Require authorization-code token exchanges to authenticate registered confidential clients with their matching secret before accessing the code.
  • Prevent client-mismatched codes and failed authentication attempts from consuming authorization codes, while preserving PKCE requirements for registered public clients.

Build:

  • Bump the package version to 0.5.0-rc69.

Documentation:

  • Document the authorization-code client-authentication fix in the changelog.

Tests:

  • Add coverage for confidential-client authentication, code ownership, code preservation after failed exchanges, public-client PKCE enforcement, and unregistered clients.

) (0.5.0-rc69)

Backport of 04a4f48 from main.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013YEhSGGFctL3d4hGevi7tC
@sourcery-ai

sourcery-ai Bot commented Oct 26, 2026

Copy link
Copy Markdown

Sorry @ciresnave-bot, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 2 days and 13 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Oct 26, 2026

Copy link
Copy Markdown

Reviewer's Guide

Backports the authorization-code client-authentication fix to 0.5.x by authenticating registered clients before code access, enforcing confidential secrets and public-client PKCE correctly, preserving codes on failed validation or client mismatch, and adding focused regression tests for the security-sensitive flows.

Sequence diagram for authorization-code client authentication

sequenceDiagram
    participant Client
    participant TokenEndpoint
    participant ClientStore
    participant CodeStore

    Client->>TokenEndpoint: handle_authorization_code_grant()
    TokenEndpoint->>ClientStore: authenticate_token_client()
    ClientStore-->>TokenEndpoint: ClientKind or invalid_client
    alt invalid_client
        TokenEndpoint-->>Client: invalid_client
    else authenticated client
        TokenEndpoint->>CodeStore: Read authorization code
        alt client_id mismatch
            TokenEndpoint->>CodeStore: Release consumed marker
            TokenEndpoint-->>Client: invalid_grant
        else matching client_id
            TokenEndpoint->>CodeStore: Delete authorization code
            TokenEndpoint-->>Client: Token response
        end
    end
Loading

File-Level Changes

Change Details Files
Authenticate the token client before reading or consuming an authorization code.
  • Load the registered client record and classify it as public or confidential.
  • Require a confidential client’s registered secret using constant-time comparison; return invalid_client for missing or incorrect credentials.
  • Reject unregistered clients without exposing or consuming the code.
  • Base public-client PKCE enforcement on registration rather than request-provided secrets.
src/api/oauth2.rs
Preserve authorization-code ownership and single-use behavior during client validation.
  • Check that the code belongs to the authenticated client before deleting it.
  • Release the consumed marker and return invalid_grant on client mismatch so the rightful client can redeem the code.
  • Add regression coverage for authentication failures, client mismatch, public-client PKCE, and successful confidential exchanges.
src/api/oauth2.rs
tests/oauth2_code_grant_client_auth_tests.rs
Prepare the 0.5.x release with the security fix.
  • Document the authorization-code client-authentication correction and its security behavior.
  • Bump the package version to 0.5.0-rc69 and update the lockfile.
CHANGELOG.md
Cargo.toml
Cargo.lock

Possibly linked issues

  • #unknown: The PR directly fixes the reported flaw by verifying confidential-client secrets before reading or consuming authorization codes.

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@ciresnave-bot
ciresnave-bot merged commit 96776c9 into release/0.5.x Oct 27, 2026
36 of 41 checks passed
@ciresnave-bot
ciresnave-bot deleted the fix/code-grant-client-auth-0.5.x branch October 27, 2026 00:58
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.

2 participants