1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
# frozen_string_literal: true
class Token < ApplicationRecord
audited associated_with: :subject
enum token_type: { access: 0, refresh: 1 }
belongs_to :authorization, optional: true
belongs_to :subject, polymorphic: true
belongs_to :audience, polymorphic: true
scope :active, -> { where.not(id: revoked.or(where(id: expired))) }
scope :expired, -> { where('expired_at < ?', Time.current) }
scope :revoked, -> { where('revoked_at < ?', Time.current) }
after_initialize do |x|
if x.expired_at.nil?
x.expired_at = access? ? 1.hour.from_now : 1.day.from_now
end
end
def issued_to?(audience)
self.audience == audience
end
def revoke!
update!(revoked_at: Time.current)
authorization&.revoke!
end
def revoked?
revoked_at.present?
end
def claims(custom_claims = {})
{
aud: audience.to_param,
exp: expired_at.to_i,
iat: created_at.to_i,
iss: Saml::Kit.configuration.entity_id,
jti: id,
nbf: created_at.to_i,
sub: subject.to_param,
token_type: token_type,
}.merge(custom_claims)
end
def to_jwt(custom_claims = {})
@to_jwt ||= BearerToken.new.encode(claims(custom_claims))
end
def issue_tokens_to(client, token_types: [:access, :refresh])
transaction do
revoke!
token_types.map do |x|
Token.create!(subject: subject, audience: client, token_type: x)
end
end
end
class << self
def revoked?(jti)
revoked = Rails.cache.fetch("revoked-tokens", expires_in: 10.minutes) do
Hash[Token.revoked.pluck(:id).map { |x| [x, true] }]
end
revoked[jti]
end
def claims_for(token, token_type: :access)
if token_type == :any
claims = claims_for(token, token_type: :access)
claims = claims_for(token, token_type: :refresh) if claims.empty?
return claims
end
BearerToken.new.decode(token)
end
def authenticate(jwt)
claims = claims_for(jwt, token_type: :access)
return if claims.empty?
token = Token.find(claims[:jti])
return if token.refresh? || token.revoked?
token
end
end
end
|