Class: Toolchest::OauthAccessToken

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/toolchest/oauth_access_token.rb

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.create_for(application:, resource_owner_id:, scopes:, mount_key: "default", expires_in: 7200) ⇒ Object



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'app/models/toolchest/oauth_access_token.rb', line 31

def create_for(application:, resource_owner_id:, scopes:, mount_key: "default", expires_in: 7200)
  raw_token = SecureRandom.urlsafe_base64(32)
  raw_refresh = SecureRandom.urlsafe_base64(32)

  token = create!(
    application: application,
    resource_owner_id: resource_owner_id,
    token: Digest::SHA256.hexdigest(raw_token),
    refresh_token: Digest::SHA256.hexdigest(raw_refresh),
    scopes: scopes,
    mount_key: mount_key,
    expires_at: expires_in ? Time.current + expires_in.seconds : nil
  )

  token.instance_variable_set(:@raw_token, raw_token)
  token.instance_variable_set(:@raw_refresh_token, raw_refresh)
  token
end

.find_by_refresh_token(raw_refresh, mount_key: nil) ⇒ Object

See find_by_token for timing safety rationale.



60
61
62
63
64
# File 'app/models/toolchest/oauth_access_token.rb', line 60

def find_by_refresh_token(raw_refresh, mount_key: nil)
  scope = active.where(refresh_token: Digest::SHA256.hexdigest(raw_refresh))
  scope = scope.where(mount_key: mount_key) if mount_key
  scope.first
end

.find_by_token(raw_token, mount_key: nil) ⇒ Object

Timing-safe by design: we hash the raw token before lookup, so the database comparison runs against the hash (which the attacker doesn’t know). No constant-time comparison needed here.



53
54
55
56
57
# File 'app/models/toolchest/oauth_access_token.rb', line 53

def find_by_token(raw_token, mount_key: nil)
  scope = active.where(token: Digest::SHA256.hexdigest(raw_token))
  scope = scope.where(mount_key: mount_key) if mount_key
  scope.first
end

.revoke_all_for(application, resource_owner_id) ⇒ Object



26
27
28
29
# File 'app/models/toolchest/oauth_access_token.rb', line 26

def 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

#accessible?Boolean

Returns:

  • (Boolean)


21
# File 'app/models/toolchest/oauth_access_token.rb', line 21

def accessible? = !revoked? && !expired?

#expired?Boolean

Returns:

  • (Boolean)


15
# File 'app/models/toolchest/oauth_access_token.rb', line 15

def expired? = expires_at.present? && expires_at < Time.current

#raw_refresh_tokenObject



69
# File 'app/models/toolchest/oauth_access_token.rb', line 69

def raw_refresh_token = @raw_refresh_token

#raw_tokenObject



67
# File 'app/models/toolchest/oauth_access_token.rb', line 67

def raw_token = @raw_token

#revoke!Object



19
# File 'app/models/toolchest/oauth_access_token.rb', line 19

def revoke! = update!(revoked_at: Time.current)

#revoked?Boolean

Returns:

  • (Boolean)


17
# File 'app/models/toolchest/oauth_access_token.rb', line 17

def revoked? = revoked_at.present?

#scopes_arrayObject



23
# File 'app/models/toolchest/oauth_access_token.rb', line 23

def scopes_array = (scopes || "").split(" ").reject(&:empty?)