Nullify token to auth-code FK on delete so cleanup job can purge codes

The FK added in b7fa499 defaulted to ON DELETE RESTRICT, which means
OidcTokenCleanupJob#perform would fail when deleting auth codes older
than 7 days if any refresh token (whose expiry is days-to-weeks) still
referenced them. Switch both token FKs to ON DELETE SET NULL so token
rows survive the code deletion with a NULL FK, preserving the audit
trail the cleanup job deliberately keeps.

Add a regression test covering the exact scenario: a 10-day-old auth
code with a token still pointing at it -> cleanup deletes the code,
token survives, token FK is nulled.

Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
This commit is contained in:
Dan Milne
2026-04-20 18:12:03 +10:00
parent 2068675173
commit 93d8381214
3 changed files with 70 additions and 6 deletions

View File

@@ -0,0 +1,20 @@
class NullifyAuthCodeFkOnDelete < ActiveRecord::Migration[8.1]
# When an OidcAuthorizationCode is deleted (e.g. by OidcTokenCleanupJob),
# null out the FK on any descendant tokens instead of blocking the delete
# on the default RESTRICT. Token rows survive for the audit trail.
def up
remove_foreign_key :oidc_access_tokens, :oidc_authorization_codes
add_foreign_key :oidc_access_tokens, :oidc_authorization_codes, on_delete: :nullify
remove_foreign_key :oidc_refresh_tokens, :oidc_authorization_codes
add_foreign_key :oidc_refresh_tokens, :oidc_authorization_codes, on_delete: :nullify
end
def down
remove_foreign_key :oidc_access_tokens, :oidc_authorization_codes
add_foreign_key :oidc_access_tokens, :oidc_authorization_codes
remove_foreign_key :oidc_refresh_tokens, :oidc_authorization_codes
add_foreign_key :oidc_refresh_tokens, :oidc_authorization_codes
end
end

6
db/schema.rb generated
View File

@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.1].define(version: 2026_04_20_073319) do
ActiveRecord::Schema[8.1].define(version: 2026_04_20_080000) do
create_table "active_storage_attachments", force: :cascade do |t|
t.bigint "blob_id", null: false
t.datetime "created_at", null: false
@@ -278,13 +278,13 @@ ActiveRecord::Schema[8.1].define(version: 2026_04_20_073319) do
add_foreign_key "application_user_claims", "applications", on_delete: :cascade
add_foreign_key "application_user_claims", "users", on_delete: :cascade
add_foreign_key "oidc_access_tokens", "applications"
add_foreign_key "oidc_access_tokens", "oidc_authorization_codes"
add_foreign_key "oidc_access_tokens", "oidc_authorization_codes", on_delete: :nullify
add_foreign_key "oidc_access_tokens", "users"
add_foreign_key "oidc_authorization_codes", "applications"
add_foreign_key "oidc_authorization_codes", "users"
add_foreign_key "oidc_refresh_tokens", "applications"
add_foreign_key "oidc_refresh_tokens", "oidc_access_tokens"
add_foreign_key "oidc_refresh_tokens", "oidc_authorization_codes"
add_foreign_key "oidc_refresh_tokens", "oidc_authorization_codes", on_delete: :nullify
add_foreign_key "oidc_refresh_tokens", "users"
add_foreign_key "oidc_user_consents", "applications"
add_foreign_key "oidc_user_consents", "users"