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.

Parameters:

  • application_id (Integer)

    ID of the Application model instance

  • resource_owner (ActiveRecord::Base, Integer)

    Resource Owner model instance or it's ID

Returns:

  • (ActiveRecord::Relation)

    collection of matching AccessToken objects


239
240
241
242
243
244
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 239

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.

Parameters:

  • previous_refresh_token (#to_s)

    previous refresh token value (any object that responds to `#to_s`)

Returns:


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

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.

Parameters:

  • refresh_token (#to_s)

    refresh token value (any object that responds to `#to_s`)

Returns:


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

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.

Parameters:

  • token (#to_s)

    Plain text token value (any object that responds to `#to_s`)

Returns:


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

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.

Parameters:

  • application (Doorkeeper::Application)

    Application instance

  • resource_owner (ActiveRecord::Base, Integer)

    Resource Owner model instance or it's ID

  • scopes (#to_s)

    set of scopes (any object that responds to `#to_s`)

  • token_attributes (Hash)

    Additional attributes to use when creating a token

Options Hash (**token_attributes):

  • :expires_in (Integer)

    token lifetime in seconds

  • :use_refresh_token (Boolean)

    whether to use the refresh token

Returns:


215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 215

def create_for(application:, resource_owner:, scopes:, **token_attributes)
  token_attributes[:application_id] = application&.id
  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

#fallback_secret_strategyObject

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


276
277
278
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 276

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.


97
98
99
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 97

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

#find_matching_token(relation, application, 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. Probably it would be better to rewrite this query using Time math if possible, but we n eed to consider ORM and different databases support.

Parameters:

Returns:


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 121

def find_matching_token(relation, application, 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)
    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.

Parameters:

  • application (Doorkeeper::Application)

    Application instance

  • resource_owner (ActiveRecord::Base, Integer)

    Resource Owner model instance or it's ID

  • scopes (#to_s)

    set of scopes (any object that responds to `#to_s`)

  • token_attributes (Hash)

    Additional attributes to use when creating a token

Options Hash (**token_attributes):

  • :expires_in (Integer)

    token lifetime in seconds

  • :use_refresh_token (Boolean)

    whether to use the refresh token

Returns:


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

def find_or_create_for(application:, resource_owner:, scopes:, **token_attributes)
  if Doorkeeper.config.reuse_access_token
    access_token = matching_token_for(application, resource_owner, scopes)

    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.

Parameters:

  • application_id (Integer)

    ID of the Application model instance

  • resource_owner (ActiveRecord::Base, Integer)

    ID of the Resource Owner model instance

Returns:


257
258
259
260
261
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 257

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) ⇒ Doorkeeper::AccessToken?

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

Parameters:

Returns:


89
90
91
92
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 89

def matching_token_for(application, resource_owner, scopes)
  tokens = authorized_tokens_for(application&.id, resource_owner)
  find_matching_token(tokens, application, 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.

Parameters:

  • application_id (Integer)

    ID of the Application

  • resource_owner (ActiveRecord::Base, Integer)

    instance of the Resource Owner model or it's ID


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

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

Parameters:

Returns:

  • (Boolean)

    true if the param scopes match the token scopes, and all the param scopes are defined in the application (or in the server configuration if the application doesn't define any scopes), and false in other cases


152
153
154
155
156
157
158
159
160
161
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 152

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


269
270
271
# File 'lib/doorkeeper/models/access_token_mixin.rb', line 269

def secret_strategy
  ::Doorkeeper.config.token_secret_strategy
end