Module: Doorkeeper::AccessTokenMixin::ClassMethods

Defined in:
lib/doorkeeper/models/access_token_mixin.rb

Instance Method Summary collapse

Instance Method Details

#authorized_tokens_for(application_id, resource_owner) ⇒ ActiveRecord::Relation

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



277
278
279
280
281
282
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 277

def authorized_tokens_for(application_id, resource_owner)
  by_resource_owner(resource_owner).where(
    application_id: application_id,
    revoked_at: nil,
  )
end

#by_previous_refresh_token(previous_refresh_token) ⇒ Doorkeeper::AccessToken?

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.



56
57
58
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 56

def by_previous_refresh_token(previous_refresh_token)
  find_by(refresh_token: previous_refresh_token)
end

#by_refresh_token(refresh_token) ⇒ Doorkeeper::AccessToken?

Returns an instance of the Doorkeeper::AccessToken with specific token value.



41
42
43
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 41

def by_refresh_token(refresh_token)
  find_by_plaintext_token(:refresh_token, refresh_token)
end

#by_token(token) ⇒ Doorkeeper::AccessToken?

Returns an instance of the Doorkeeper::AccessToken with specific plain text token value.



28
29
30
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 28

def by_token(token)
  find_by_plaintext_token(:token, token)
end

#create_for(application:, resource_owner:, scopes:, **token_attributes) ⇒ Doorkeeper::AccessToken

Creates a not expired AccessToken record with a matching set of scopes that belongs to specific Application and Resource Owner.

Options Hash (**token_attributes):

  • :expires_in (Integer)

    token lifetime in seconds

  • :use_refresh_token (Boolean)

    whether to use the refresh token



253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 253

def create_for(application:, resource_owner:, scopes:, **token_attributes)
  token_attributes[:application] = application
  token_attributes[:scopes] = scopes.to_s

  if Doorkeeper.config.polymorphic_resource_owner?
    token_attributes[:resource_owner] = resource_owner
  else
    token_attributes[:resource_owner_id] = resource_owner_id_for(resource_owner)
  end

  create!(token_attributes)
end

#custom_attributes_match?(token, custom_attributes) ⇒ Boolean

Checks whether the token custom attribute values match the custom attributes from the parameters.



186
187
188
189
190
191
192
193
194
195
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 186

def custom_attributes_match?(token, custom_attributes)
  return true if custom_attributes.nil?

  token_attribs = token.custom_attributes
  return true if token_attribs.blank? && custom_attributes.blank?

  Doorkeeper.config.custom_access_token_attributes.all? do |attribute|
    token_attribs[attribute] == custom_attributes[attribute]
  end
end

#extract_custom_attributes(attributes) ⇒ Hash

Extracts the token’s custom attributes (defined by the custom_access_token_attributes config option) from the token’s attributes.



325
326
327
328
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 325

def extract_custom_attributes(attributes)
  attributes.with_indifferent_access.slice(
    *Doorkeeper.configuration.custom_access_token_attributes)
end

#fallback_secret_strategyObject

Determine the fallback storing strategy Unless configured, there will be no fallback



314
315
316
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 314

def fallback_secret_strategy
  ::Doorkeeper.config.token_secret_fallback_strategy
end

#find_access_token_in_batches(relation, **args, &block) ⇒ Object

Interface to enumerate access token records in batches in order not to bloat the memory. Could be overloaded in any ORM extension.



103
104
105
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 103

def find_access_token_in_batches(relation, **args, &block)
  relation.find_in_batches(**args, &block)
end

#find_matching_token(relation, application, custom_attributes, scopes) ⇒ Doorkeeper::AccessToken?

Enumerates AccessToken records in batches to find a matching token. Batching is required in order not to pollute the memory if Application has huge amount of associated records.

ActiveRecord 5.x - 6.x ignores custom ordering so we can’t perform a database sort by created_at, so we need to load all the matching records, sort them and find latest one.



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 129

def find_matching_token(relation, application, custom_attributes, scopes)
  return nil unless relation

  matching_tokens = []
  batch_size = Doorkeeper.configuration.token_lookup_batch_size

  find_access_token_in_batches(relation, batch_size: batch_size) do |batch|
    tokens = batch.select do |token|
      scopes_match?(token.scopes, scopes, application&.scopes) &&
        custom_attributes_match?(token, custom_attributes)
    end

    matching_tokens.concat(tokens)
  end

  matching_tokens.max_by(&:created_at)
end

#find_or_create_for(application:, resource_owner:, scopes:, **token_attributes) ⇒ Doorkeeper::AccessToken

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.

Options Hash (**token_attributes):

  • :expires_in (Integer)

    token lifetime in seconds

  • :use_refresh_token (Boolean)

    whether to use the refresh token



216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 216

def find_or_create_for(application:, resource_owner:, scopes:, **token_attributes)
  scopes = Doorkeeper::OAuth::Scopes.from_string(scopes) if scopes.is_a?(String)

  if Doorkeeper.config.reuse_access_token
    custom_attributes = extract_custom_attributes(token_attributes).presence
    access_token = matching_token_for(
      application, resource_owner, scopes, custom_attributes: custom_attributes, include_expired: false)

    return access_token if access_token&.reusable?
  end

  create_for(
    application: application,
    resource_owner: resource_owner,
    scopes: scopes,
    **token_attributes,
  )
end

#last_authorized_token_for(application_id, resource_owner) ⇒ Doorkeeper::AccessToken?

Convenience method for backwards-compatibility, return the last matching token for the given Application and Resource Owner.



295
296
297
298
299
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 295

def last_authorized_token_for(application_id, resource_owner)
  authorized_tokens_for(application_id, resource_owner)
    .ordered_by(:created_at, :desc)
    .first
end

#matching_token_for(application, resource_owner, scopes, custom_attributes: nil, include_expired: true) ⇒ Doorkeeper::AccessToken?

Looking for not revoked Access Token with a matching set of scopes that belongs to specific Application and Resource Owner.



94
95
96
97
98
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 94

def matching_token_for(application, resource_owner, scopes, custom_attributes: nil, include_expired: true)
  tokens = authorized_tokens_for(application&.id, resource_owner)
  tokens = tokens.not_expired unless include_expired
  find_matching_token(tokens, application, custom_attributes, scopes)
end

#revoke_all_for(application_id, resource_owner, clock = Time) ⇒ Object

Revokes AccessToken records that have not been revoked and associated with the specific Application and Resource Owner.



68
69
70
71
72
73
74
75
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 68

def revoke_all_for(application_id, resource_owner, clock = Time)
  by_resource_owner(resource_owner)
    .where(
      application_id: application_id,
      revoked_at: nil,
    )
    .update_all(revoked_at: clock.now.utc)
end

#scopes_match?(token_scopes, param_scopes, app_scopes) ⇒ Boolean

Checks whether the token scopes match the scopes from the parameters



161
162
163
164
165
166
167
168
169
170
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 161

def scopes_match?(token_scopes, param_scopes, app_scopes)
  return true if token_scopes.empty? && param_scopes.empty?

  (token_scopes.sort == param_scopes.sort) &&
    Doorkeeper::OAuth::Helpers::ScopeChecker.valid?(
      scope_str: param_scopes.to_s,
      server_scopes: Doorkeeper.config.scopes,
      app_scopes: app_scopes,
    )
end

#secret_strategyDoorkeeper::SecretStoring::Base

Determines the secret storing transformer Unless configured otherwise, uses the plain secret strategy



307
308
309
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 307

def secret_strategy
  ::Doorkeeper.config.token_secret_strategy
end