49 lines
1.2 KiB
Ruby
49 lines
1.2 KiB
Ruby
class OidcAuthorizationCode < ApplicationRecord
|
|
belongs_to :application
|
|
belongs_to :user
|
|
|
|
before_validation :generate_code, on: :create
|
|
before_validation :set_expiry, on: :create
|
|
|
|
validates :code, presence: true, uniqueness: true
|
|
validates :redirect_uri, presence: true
|
|
validates :code_challenge_method, inclusion: { in: %w[plain S256], allow_nil: true }
|
|
validate :validate_code_challenge_format, if: -> { code_challenge.present? }
|
|
|
|
scope :valid, -> { where(used: false).where("expires_at > ?", Time.current) }
|
|
scope :expired, -> { where("expires_at <= ?", Time.current) }
|
|
|
|
def expired?
|
|
expires_at <= Time.current
|
|
end
|
|
|
|
def usable?
|
|
!used? && !expired?
|
|
end
|
|
|
|
def consume!
|
|
update!(used: true)
|
|
end
|
|
|
|
def uses_pkce?
|
|
code_challenge.present?
|
|
end
|
|
|
|
private
|
|
|
|
def generate_code
|
|
self.code ||= SecureRandom.urlsafe_base64(32)
|
|
end
|
|
|
|
def set_expiry
|
|
self.expires_at ||= 10.minutes.from_now
|
|
end
|
|
|
|
def validate_code_challenge_format
|
|
# PKCE code challenge should be base64url-encoded, 43-128 characters
|
|
unless code_challenge.match?(/\A[A-Za-z0-9\-_]{43,128}\z/)
|
|
errors.add(:code_challenge, "must be 43-128 characters of base64url encoding")
|
|
end
|
|
end
|
|
end
|