class Doorkeeper::AccessToken
Attributes
Public Class Methods
Returns an instance of the Doorkeeper::AccessToken
found by previous refresh token. Keep in mind that value of the previous_refresh_token isn't encrypted using secrets strategy.
@param previous_refresh_token [#to_s]
previous refresh token value (any object that responds to `#to_s`)
@return [Doorkeeper::AccessToken, nil] AccessToken
object or nil
if there is no record with such refresh token
# File lib/support/orm/rethinkdb/access_token.rb, line 99 def by_previous_refresh_token(previous_refresh_token) return nil unless previous_refresh_token.present? where(previous_refresh_token: previous_refresh_token).first end
Returns an instance of the Doorkeeper::AccessToken
with specific token value.
@param refresh_token [#to_s]
refresh token value (any object that responds to `#to_s`)
@return [Doorkeeper::AccessToken, nil] AccessToken
object or nil
if there is no record with such refresh token
# File lib/support/orm/rethinkdb/access_token.rb, line 84 def by_refresh_token(refresh_token) find_by_plaintext_token(:refresh_token, refresh_token) end
Returns an instance of the Doorkeeper::AccessToken
with specific token value.
@param token [#to_s]
token value (any object that responds to `#to_s`)
@return [Doorkeeper::AccessToken, nil] AccessToken
object or nil
if there is no record with such token
# File lib/support/orm/rethinkdb/access_token.rb, line 71 def by_token(token) find_by_plaintext_token(:token, token) end
# File lib/support/orm/rethinkdb/access_token.rb, line 213 def create_for(application:, resource_owner:, scopes:, **token_attributes) token_attributes[:application_id] = application&.id token_attributes[:scopes] = scopes.to_s resource_owner = resource_owner.try(:id) || resource_owner token_attributes[:resource_owner_id] = resource_owner || application.try(:owner_id) create!(**token_attributes) end
Determine the fallback storing strategy Unless configured, there will be no fallback
# File lib/support/orm/rethinkdb/access_token.rb, line 236 def fallback_secret_strategy ::Doorkeeper.config.token_secret_fallback_strategy end
# File lib/support/orm/rethinkdb/access_token.rb, line 57 def find_by_plaintext_token(attr, token) # We are not implementing the fallback strategy where(attr => secret_strategy.transform_secret(token.to_s)).first end
Looking for not expired AccessToken
record with a matching set of scopes that belongs to specific Application
and Resource Owner. If it doesn't exists - then creates it.
@param application [Doorkeeper::Application]
Application instance
@param resource_owner_id [ActiveRecord::Base, Integer]
Resource Owner model instance or it's ID
@param scopes [#to_s]
set of scopes (any object that responds to `#to_s`)
@param expires_in [Integer]
token lifetime in seconds
@param use_refresh_token
[Boolean]
whether to use the refresh token
@return [Doorkeeper::AccessToken] existing record or a new one
# File lib/support/orm/rethinkdb/access_token.rb, line 196 def find_or_create_for(application:, resource_owner:, scopes:, **token_attributes) resource_owner = resource_owner.try(:id) || resource_owner if Doorkeeper.config.reuse_access_token access_token = matching_token_for(application, resource_owner, scopes) return access_token if access_token&.reusable? end create!( application_id: application.try(:id), resource_owner_id: resource_owner || application.try(:owner_id), scopes: scopes.to_s, **token_attributes, ) end
Looking for not expired Access Token with a matching set of scopes that belongs to specific Application
and Resource Owner.
@param application [Doorkeeper::Application]
Application instance
@param resource_owner_or_id [ActiveRecord::Base, Integer]
Resource Owner model instance or it's ID
@param scopes [String, Doorkeeper::OAuth::Scopes]
set of scopes
@return [Doorkeeper::AccessToken, nil] Access Token instance or
nil if matching record was not found
# File lib/support/orm/rethinkdb/access_token.rb, line 149 def matching_token_for(application, resource_owner_or_id, scopes) resource_owner_id = resource_owner_or_id.try(:id) || resource_owner_or_id token = last_authorized_token_for(application.try(:id), resource_owner_id) if token && scopes_match?(token.scopes, scopes, application.try(:scopes)) token end end
# File lib/support/orm/rethinkdb/access_token.rb, line 53 def refresh_token_revoked_on_use? true end
Revokes AccessToken
records that have not been revoked and associated with the specific Application
and Resource Owner.
@param application_id [Integer]
ID of the Application
@param resource_owner [ActiveRecord::Base]
instance of the Resource Owner model
# File lib/support/orm/rethinkdb/access_token.rb, line 112 def revoke_all_for(application_id, resource_owner) where(application_id: application_id, resource_owner_id: resource_owner.id).each do |at| at.revoke end end
Checks whether the token scopes match the scopes from the parameters or Application
scopes (if present).
@param token_scopes [#to_s]
set of scopes (any object that responds to `#to_s`)
@param param_scopes [String]
scopes from params
@param app_scopes [String]
Application scopes
@return [Boolean] true if all scopes and blank or matches
and false in other cases
# File lib/support/orm/rethinkdb/access_token.rb, line 170 def scopes_match?(token_scopes, param_scopes, app_scopes) (!token_scopes.present? && !param_scopes.present?) || Doorkeeper::OAuth::Helpers::ScopeChecker.match?( token_scopes.to_s, param_scopes, app_scopes ) end
Determines the secret storing transformer Unless configured otherwise, uses the plain secret strategy
@return [Doorkeeper::SecretStoring::Base]
# File lib/support/orm/rethinkdb/access_token.rb, line 229 def secret_strategy ::Doorkeeper.config.token_secret_strategy end
Public Instance Methods
Indicates if token is acceptable for specific scopes.
@param scopes [Array<String>] scopes
@return [Boolean] true if record is accessible and includes scopes or
false in other cases
# File lib/support/orm/rethinkdb/access_token.rb, line 286 def acceptable?(scopes) accessible? && includes_scope?(*scopes) end
# File lib/support/orm/rethinkdb/access_token.rb, line 39 def application_id? !!self.application_id end
JSON representation of the Access Token instance.
@return [Hash] hash with token data
# File lib/support/orm/rethinkdb/access_token.rb, line 257 def as_json(_options = {}) { resource_owner_id: resource_owner_id, scopes: scopes, expires_in_seconds: expires_in_seconds, application: { uid: application.try(:uid) }, created_at: created_at.to_i } end
# File lib/support/orm/rethinkdb/access_token.rb, line 329 def lock!; end
We keep a volatile copy of the raw refresh token for initial communication The stored refresh_token may be mapped and not available in cleartext.
# File lib/support/orm/rethinkdb/access_token.rb, line 292 def plaintext_refresh_token if secret_strategy.allows_restoring_secrets? secret_strategy.restore_secret(self, :refresh_token) else @raw_refresh_token end end
We keep a volatile copy of the raw token for initial communication The stored refresh_token may be mapped and not available in cleartext.
Some strategies allow restoring stored secrets (e.g. symmetric encryption) while hashing strategies do not, so you cannot rely on this value returning a present value for persisted tokens.
# File lib/support/orm/rethinkdb/access_token.rb, line 306 def plaintext_token if secret_strategy.allows_restoring_secrets? secret_strategy.restore_secret(self, :token) else @raw_token end end
# File lib/support/orm/rethinkdb/access_token.rb, line 323 def revoke(clock = Time) self.revoked_at = clock.now.utc self.save! end
Revokes token with `:refresh_token` equal to `:previous_refresh_token` and clears `:previous_refresh_token` attribute.
# File lib/support/orm/rethinkdb/access_token.rb, line 317 def revoke_previous_refresh_token! return unless self.class.refresh_token_revoked_on_use? self.previous_refresh_token = '' self.save! end
# File lib/support/orm/rethinkdb/access_token.rb, line 43 def revoked_at time = self.revoked_time Time.at(time) if time end
# File lib/support/orm/rethinkdb/access_token.rb, line 48 def revoked_at=(time) self.revoked_time = time ? time.to_i : nil end
Indicates whether the token instance have the same credential as the other Access Token.
@param access_token [Doorkeeper::AccessToken] other token
@return [Boolean] true if credentials are same of false in other cases
# File lib/support/orm/rethinkdb/access_token.rb, line 274 def same_credential?(access_token) application_id == access_token.application_id && resource_owner_id == access_token.resource_owner_id end
Access Token type: Bearer. @see tools.ietf.org/html/rfc6750
The OAuth 2.0 Authorization Framework: Bearer Token Usage
# File lib/support/orm/rethinkdb/access_token.rb, line 245 def token_type 'bearer' end
# File lib/support/orm/rethinkdb/access_token.rb, line 328 def transaction; yield; end
# File lib/support/orm/rethinkdb/access_token.rb, line 249 def use_refresh_token? @use_refresh_token ||= false !!@use_refresh_token end
Private Instance Methods
Generates refresh token with UniqueToken generator.
@return [String] refresh token value
# File lib/support/orm/rethinkdb/access_token.rb, line 348 def generate_refresh_token if self.refresh_token.blank? @raw_refresh_token = UniqueToken.generate secret_strategy.store_secret(self, :refresh_token, @raw_refresh_token) end end
# File lib/support/orm/rethinkdb/access_token.rb, line 355 def generate_token return if self.token.present? self.created_at ||= Time.now.utc if use_refresh_token? self.ttl = (self.created_at + 1.months).to_i else self.ttl = (self.created_at + self.expires_in + 30).to_i end generator = Doorkeeper.configuration.access_token_generator.constantize @raw_token = generator.generate( resource_owner_id: resource_owner_id, scopes: scopes, application: application, expires_in: expires_in, created_at: created_at ) secret_strategy.store_secret(self, :token, @raw_token) @raw_token rescue NoMethodError raise Errors::UnableToGenerateToken, "#{generator} does not respond to `.generate`." rescue NameError raise Errors::TokenGeneratorNotFound, "#{generator} not found" end
# File lib/support/orm/rethinkdb/access_token.rb, line 338 def refresh_token_unique if refresh_token_changed? && refresh_token.present? && ::Doorkeeper::AccessToken.where(refresh_token: refresh_token).count > 0 errors.add(:refresh_token, "must be unique") end end