Skip to content

Authorization-code replay race (TOCTOU) in the authorization_code grant at POST /oauth/token #2613

Description

@reactima

Describe the bug

Authorization-code replay race (TOCTOU) in the authorization_code grant at POST /oauth/token.

handleAuthorizationCodeGrant reads and validates the code (expiry / client / redirect_uri / PKCE) with no row lock, and only opens a transaction later to issue tokens and Destroy the code. Two concurrent requests with the same code both pass validation before either commits, violating RFC 6749 §4.1.2.

To Reproduce

  1. Mint one approved authorization code (public client + PKCE code_verifier).
  2. Fire N concurrent POST /oauth/token exchanges of that same code behind a start barrier.
  3. Observe ≥2 responses carry access_token.

Expected behavior

Exactly one exchange succeeds (200 + access_token); the rest return 400 invalid_grant. The code is single-use.

Fix

#2612

  • Lock the row at the top of the issuing transaction via the existing FindOAuthServerAuthorizationByIDForUpdate (FOR UPDATE SKIP LOCKED, from fix(oauth-server): serialize concurrent authorize/consent with row-level lock #2512). Concurrent redemptions serialize — the loser skips the locked row and gets invalid_grant
  • Propagate *apierrors.OAuthError out of the transaction so invalid_grant reaches the client instead of a 500.
  • Adds handlers_replay_test.go: N concurrent redemptions assert single-use (success == 1). Passes with the fix; without the lock, all N succeed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions