Use SolidQueue in production. Use the find_by_token method, rather than iterating over refresh tokens, as we already fixed for tokens

This commit is contained in:
Dan Milne
2025-12-31 14:32:34 +11:00
parent a17c08c890
commit 40815d3576
3 changed files with 9 additions and 15 deletions

View File

@@ -482,14 +482,11 @@ class OidcController < ApplicationController
return return
end end
# Find the refresh token record # Find the refresh token record using indexed token prefix lookup
# Note: This is inefficient with BCrypt hashing, but necessary for security refresh_token_record = OidcRefreshToken.find_by_token(refresh_token)
# In production, consider adding a token prefix for faster lookup
refresh_token_record = OidcRefreshToken.where(application: application).find do |rt|
rt.token_matches?(refresh_token)
end
unless refresh_token_record # Verify the token belongs to the correct application
unless refresh_token_record && refresh_token_record.application == application
render json: { error: "invalid_grant", error_description: "Invalid refresh token" }, status: :bad_request render json: { error: "invalid_grant", error_description: "Invalid refresh token" }, status: :bad_request
return return
end end
@@ -668,9 +665,7 @@ class OidcController < ApplicationController
if token_type_hint == "refresh_token" || token_type_hint.nil? if token_type_hint == "refresh_token" || token_type_hint.nil?
# Try to find as refresh token # Try to find as refresh token
refresh_token_record = OidcRefreshToken.where(application: application).find do |rt| refresh_token_record = OidcRefreshToken.find_by_token(token)
rt.token_matches?(token)
end
if refresh_token_record if refresh_token_record
refresh_token_record.revoke! refresh_token_record.revoke!
@@ -681,9 +676,7 @@ class OidcController < ApplicationController
if !revoked && (token_type_hint == "access_token" || token_type_hint.nil?) if !revoked && (token_type_hint == "access_token" || token_type_hint.nil?)
# Try to find as access token # Try to find as access token
access_token_record = OidcAccessToken.where(application: application).find do |at| access_token_record = OidcAccessToken.find_by_token(token)
at.token_matches?(token)
end
if access_token_record if access_token_record
access_token_record.revoke! access_token_record.revoke!

View File

@@ -10,6 +10,7 @@ class OidcRefreshToken < ApplicationRecord
before_validation :set_token_family_id, on: :create before_validation :set_token_family_id, on: :create
validates :token_digest, presence: true, uniqueness: true validates :token_digest, presence: true, uniqueness: true
validates :token_prefix, presence: true
scope :valid, -> { where("expires_at > ?", Time.current).where(revoked_at: nil) } scope :valid, -> { where("expires_at > ?", Time.current).where(revoked_at: nil) }
scope :expired, -> { where("expires_at <= ?", Time.current) } scope :expired, -> { where("expires_at <= ?", Time.current) }

View File

@@ -57,8 +57,8 @@ Rails.application.configure do
# Replace the default in-process memory cache store with a durable alternative. # Replace the default in-process memory cache store with a durable alternative.
config.cache_store = :solid_cache_store config.cache_store = :solid_cache_store
# Use async processor for background jobs (modify as needed for production) # Use Solid Queue for background jobs
config.active_job.queue_adapter = :async config.active_job.queue_adapter = :solid_queue
# Ignore bad email addresses and do not raise email delivery errors. # Ignore bad email addresses and do not raise email delivery errors.
# Set this to true and configure the email server for immediate delivery to raise delivery errors. # Set this to true and configure the email server for immediate delivery to raise delivery errors.