Skip to content

fix: added fix for https://github.com/highflame-ai/zeroid/issues/15#76

Merged
rsharath merged 5 commits intomainfrom
issue15
Apr 16, 2026
Merged

fix: added fix for https://github.com/highflame-ai/zeroid/issues/15#76
rsharath merged 5 commits intomainfrom
issue15

Conversation

@rsharath
Copy link
Copy Markdown
Contributor

Summary

fix: enforce single-use authorization codes (RFC 6749 §4.1.2)

Problem

Authorization codes were stateless HS256 JWTs with no consumption tracking. The same valid code could be exchanged multiple times before its 5-minute TTL expired, allowing an attacker who intercepts it to obtain multiple valid sessions.

Fix

Track consumed auth codes in a new auth_codes table. On exchange, an atomic INSERT ON CONFLICT determines whether the code has been used before. Replays are rejected with invalid_grant and all tokens from the original exchange are revoked.

Key design decisions:

  • Consume after validation: the single-use check runs after client lookup, redirect_uri, and PKCE verification so an attacker who intercepts a code but doesn't know the verifier cannot burn it
  • Revocation on replay: per RFC 6749 section 4.1.2 SHOULD, replaying a code revokes the access token (cascade) and refresh token family from the first exchange
  • Backward-compatible JTI: if the auth code JWT has a jti claim, it's used; otherwise, a deterministic SHA-256 hash of the raw JWT string is derived, so existing codes without jti are protected

Changes

New files:

  • migrations/008_auth_codes.up.sql : consumed auth codes table (PK on jti, index on expires_at)
  • domain/auth_code.go : Bun model
  • internal/store/postgres/auth_code.go : repo with Consume, GetByJTI, UpdateTokenInfo

Modified:

  • internal/service/oauth.go: single-use enforcement in authorizationCode(), revokeAuthCodeTokens() for replay revocation
  • internal/service/authcode.go: extract JTI and ExpiresAt from auth code JWT
  • internal/service/refresh_token.go: expose RevokeFamily() for replay revocation
  • internal/worker/cleanup.go: clean up expired auth code records
  • server.go: wire AuthCodeRepository

Lint cleanup (pre-existing):

  • Added _ = to unchecked .Close() / os.Remove() calls across test files
  • Removed unused respondNotImplemented in internal/handler/helper.go
  • Wrapped defer db.Close() in migrate.go

Test plan

  • TestAuthorizationCodeReplayRejected: second exchange returns invalid_grant
  • TestAuthorizationCodeReplayRevokesTokens: access token + refresh token from first exchange are revoked on
    replay
  • All 67 existing integration tests pass (no regressions)
  • golangci-lint run ./...: 0 issues

@rsharath
Copy link
Copy Markdown
Contributor Author

/gemini review

@rsharath rsharath self-assigned this Apr 16, 2026
@rsharath rsharath added the enhancement New feature or request label Apr 16, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request implements single-use enforcement for authorization codes as per RFC 6749 §4.1.2. It introduces a new AuthCode domain model, a PostgreSQL repository for tracking consumed codes, and logic within the OAuthService to detect replays and revoke associated tokens. Feedback focuses on addressing a potential race condition during replay detection, handling persistence errors more robustly when storing token metadata, ensuring errors are not ignored during token introspection for revocation, and improving performance by executing token revocation asynchronously.

Comment thread internal/service/oauth.go
Comment thread internal/service/oauth.go
Comment thread internal/service/oauth.go Outdated
Comment thread internal/service/oauth.go
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request implements single-use enforcement for authorization codes per RFC 6749 §4.1.2. It introduces a new AuthCode domain model and repository to track consumed codes, adds logic to the OAuthService to detect and reject replays, and ensures that tokens issued from a replayed code are revoked. The changes also include database migrations, cleanup tasks for expired records, and updates to integration tests to handle response body closing more robustly. Feedback was provided regarding the handling of errors during token introspection in the revocation logic.

Comment thread internal/service/oauth.go Outdated
@rsharath rsharath merged commit 21e901c into main Apr 16, 2026
8 checks passed
@rsharath rsharath deleted the issue15 branch April 16, 2026 18:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants