class Doorkeeper::AccessToken

Attributes

use_refresh_token[W]

Public Class Methods

by_previous_refresh_token(previous_refresh_token) click to toggle source

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
by_refresh_token(refresh_token) click to toggle source

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
by_token(token) click to toggle source

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
create_for(application:, resource_owner:, scopes:, **token_attributes) click to toggle source
# 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
fallback_secret_strategy() click to toggle source

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
find_by_plaintext_token(attr, token) click to toggle source
# 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
find_or_create_for(application:, resource_owner:, scopes:, **token_attributes) click to toggle source

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
last_authorized_token_for(application_id, resource_owner_id) click to toggle source

Looking for not revoked Access Token record that belongs to specific Application and Resource Owner.

@param application_id [Integer]

ID of the Application model instance

@param resource_owner_id [Integer]

ID of the Resource Owner model instance

@return [Doorkeeper::AccessToken, nil] matching AccessToken object or

nil if nothing was found
# File lib/support/orm/rethinkdb/access_token.rb, line 129
def last_authorized_token_for(application_id, resource_owner_id)
  resource_owner_id = resource_owner_id.try(:id) || resource_owner_id
  result = where(application_id: application_id, resource_owner_id: resource_owner_id).last
  return nil unless result
  result[:revoked_at] ? nil : result
end
matching_token_for(application, resource_owner_or_id, scopes) click to toggle source

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
refresh_token_revoked_on_use?() click to toggle source
# File lib/support/orm/rethinkdb/access_token.rb, line 53
def refresh_token_revoked_on_use?
  true
end
revoke_all_for(application_id, resource_owner) click to toggle source

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
scopes_match?(token_scopes, param_scopes, app_scopes) click to toggle source

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
secret_strategy() click to toggle source

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

acceptable?(scopes) click to toggle source

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
application_id?() click to toggle source
# File lib/support/orm/rethinkdb/access_token.rb, line 39
def application_id?
  !!self.application_id
end
as_json(_options = {}) click to toggle source

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
lock!() click to toggle source
# File lib/support/orm/rethinkdb/access_token.rb, line 329
def lock!; end
plaintext_refresh_token() click to toggle source

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
plaintext_token() click to toggle source

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
revoke(clock = Time) click to toggle source
# File lib/support/orm/rethinkdb/access_token.rb, line 323
def revoke(clock = Time)
  self.revoked_at = clock.now.utc
  self.save!
end
revoke_previous_refresh_token!() click to toggle source

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
revoked_at() click to toggle source
# File lib/support/orm/rethinkdb/access_token.rb, line 43
def revoked_at
  time = self.revoked_time
  Time.at(time) if time
end
revoked_at=(time) click to toggle source
# File lib/support/orm/rethinkdb/access_token.rb, line 48
def revoked_at=(time)
  self.revoked_time = time ? time.to_i : nil
end
same_credential?(access_token) click to toggle source

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
token_type() click to toggle source

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
transaction() { || ... } click to toggle source
# File lib/support/orm/rethinkdb/access_token.rb, line 328
def transaction; yield; end
use_refresh_token?() click to toggle source
# 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

generate_refresh_token() click to toggle source

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
generate_token() click to toggle source
# 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
refresh_token_unique() click to toggle source
# 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