Revoke full token chain on OIDC authorization-code replay

The replay handler previously used a created_at time-range filter to
target access tokens and called update_all(expires_at:), which left
revoked_at nil, skipped refresh tokens entirely, and could miss or
falsely catch tokens from concurrent flows. Add an oidc_authorization_code
FK on both token tables, carry it through refresh-token rotation, and
use the association to revoke every descendant via revoke! (which sets
revoked_at and cascades access -> refresh).

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
This commit is contained in:
Dan Milne
2026-04-20 17:39:08 +10:00
parent b7dd3c02e7
commit b7fa49953c
7 changed files with 89 additions and 9 deletions

View File

@@ -1,6 +1,7 @@
class OidcAccessToken < ApplicationRecord
belongs_to :application
belongs_to :user
belongs_to :oidc_authorization_code, optional: true
has_many :oidc_refresh_tokens, dependent: :destroy
before_validation :generate_token, on: :create

View File

@@ -1,6 +1,8 @@
class OidcAuthorizationCode < ApplicationRecord
belongs_to :application
belongs_to :user
has_many :oidc_access_tokens
has_many :oidc_refresh_tokens
attr_accessor :plaintext_code

View File

@@ -2,6 +2,7 @@ class OidcRefreshToken < ApplicationRecord
belongs_to :application
belongs_to :user
belongs_to :oidc_access_token
belongs_to :oidc_authorization_code, optional: true
before_validation :generate_token, on: :create
before_validation :set_expiry, on: :create