Class: Toolchest::OauthAccessGrant
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Toolchest::OauthAccessGrant
- Defined in:
- app/models/toolchest/oauth_access_grant.rb
Class Method Summary collapse
- .create_for(application:, resource_owner_id:, redirect_uri:, scopes:, mount_key: "default", expires_in: 300, code_challenge: nil, code_challenge_method: nil) ⇒ Object
- .find_by_code(raw_code) ⇒ Object
- .revoke_all_for(application, resource_owner_id) ⇒ Object
Instance Method Summary collapse
- #expired? ⇒ Boolean
- #raw_code ⇒ Object
- #revoke! ⇒ Object
-
#revoke_atomically! ⇒ Object
Atomic revocation — returns true only if THIS call revoked the grant.
- #revoked? ⇒ Boolean
- #uses_pkce? ⇒ Boolean
- #verify_pkce(code_verifier) ⇒ Object
Class Method Details
.create_for(application:, resource_owner_id:, redirect_uri:, scopes:, mount_key: "default", expires_in: 300, code_challenge: nil, code_challenge_method: nil) ⇒ Object
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'app/models/toolchest/oauth_access_grant.rb', line 48 def create_for(application:, resource_owner_id:, redirect_uri:, scopes:, mount_key: "default", expires_in: 300, code_challenge: nil, code_challenge_method: nil) raw_code = SecureRandom.urlsafe_base64(32) grant = create!( application: application, resource_owner_id: resource_owner_id, token_digest: Digest::SHA256.hexdigest(raw_code), redirect_uri: redirect_uri, scopes: scopes, mount_key: mount_key, expires_at: Time.current + expires_in.seconds, code_challenge: code_challenge, code_challenge_method: code_challenge_method ) grant.instance_variable_set(:@raw_code, raw_code) grant end |
.find_by_code(raw_code) ⇒ Object
68 |
# File 'app/models/toolchest/oauth_access_grant.rb', line 68 def find_by_code(raw_code) = active.find_by(token_digest: Digest::SHA256.hexdigest(raw_code)) |
.revoke_all_for(application, resource_owner_id) ⇒ Object
11 12 13 14 |
# File 'app/models/toolchest/oauth_access_grant.rb', line 11 def self.revoke_all_for(application, resource_owner_id) where(application: application, resource_owner_id: resource_owner_id.to_s, revoked_at: nil) .update_all(revoked_at: Time.current) end |
Instance Method Details
#expired? ⇒ Boolean
21 |
# File 'app/models/toolchest/oauth_access_grant.rb', line 21 def expired? = expires_at < Time.current |
#raw_code ⇒ Object
71 |
# File 'app/models/toolchest/oauth_access_grant.rb', line 71 def raw_code = @raw_code |
#revoke! ⇒ Object
25 |
# File 'app/models/toolchest/oauth_access_grant.rb', line 25 def revoke! = update!(revoked_at: Time.current) |
#revoke_atomically! ⇒ Object
Atomic revocation — returns true only if THIS call revoked the grant. Prevents race conditions where two concurrent token exchanges both find the grant active and both mint tokens (RFC 6749 §4.1.2).
30 31 32 |
# File 'app/models/toolchest/oauth_access_grant.rb', line 30 def revoke_atomically! self.class.where(id: id, revoked_at: nil).update_all(revoked_at: Time.current) > 0 end |
#revoked? ⇒ Boolean
23 |
# File 'app/models/toolchest/oauth_access_grant.rb', line 23 def revoked? = revoked_at.present? |
#uses_pkce? ⇒ Boolean
34 |
# File 'app/models/toolchest/oauth_access_grant.rb', line 34 def uses_pkce? = code_challenge.present? |
#verify_pkce(code_verifier) ⇒ Object
36 37 38 39 40 41 42 43 44 45 |
# File 'app/models/toolchest/oauth_access_grant.rb', line 36 def verify_pkce(code_verifier) return true unless uses_pkce? return false if code_verifier.blank? generated = Base64.urlsafe_encode64( Digest::SHA256.digest(code_verifier), padding: false ) ActiveSupport::SecurityUtils.secure_compare(generated, code_challenge) end |