Class: Himari::RefreshToken

Inherits:
Object
  • Object
show all
Includes:
TokenString
Defined in:
lib/himari/refresh_token.rb

Instance Attribute Summary collapse

Attributes included from TokenString

#verification

Class Method Summary collapse

Instance Method Summary collapse

Methods included from TokenString

#format, hash_secret, included, #magic_header, #secret, #secret_hash, #secret_hash_prev, #verify!, #verify_expiry!, #verify_secret!

Constructor Details

#initialize(handle:, client_id:, claims:, session_handle:, expiry:, openid: false, scopes: [], secret: nil, secret_hash: nil, secret_hash_prev: nil, version: 1, updated_at: nil) ⇒ RefreshToken

Returns a new instance of RefreshToken.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/himari/refresh_token.rb', line 18

def initialize(handle:, client_id:, claims:, session_handle:, expiry:, openid: false, scopes: [], secret: nil, secret_hash: nil, secret_hash_prev: nil, version: 1, updated_at: nil)
  @handle = handle
  @client_id = client_id
  @claims = claims
  @session_handle = session_handle
  @openid = openid
  @scopes = scopes
  @expiry = expiry

  @secret = secret
  @secret_hash = secret_hash
  @secret_hash_prev = secret_hash_prev
  @version = version
  @updated_at = updated_at || Time.now.to_i
  @verification = nil
end

Instance Attribute Details

#claimsObject (readonly)

Returns the value of attribute claims.



35
36
37
# File 'lib/himari/refresh_token.rb', line 35

def claims
  @claims
end

#client_idObject (readonly)

Returns the value of attribute client_id.



35
36
37
# File 'lib/himari/refresh_token.rb', line 35

def client_id
  @client_id
end

#expiryObject (readonly)

Returns the value of attribute expiry.



35
36
37
# File 'lib/himari/refresh_token.rb', line 35

def expiry
  @expiry
end

#handleObject (readonly)

Returns the value of attribute handle.



35
36
37
# File 'lib/himari/refresh_token.rb', line 35

def handle
  @handle
end

#openidObject (readonly)

Returns the value of attribute openid.



35
36
37
# File 'lib/himari/refresh_token.rb', line 35

def openid
  @openid
end

#scopesObject (readonly)

Returns the value of attribute scopes.



35
36
37
# File 'lib/himari/refresh_token.rb', line 35

def scopes
  @scopes
end

#session_handleObject (readonly)

Returns the value of attribute session_handle.



35
36
37
# File 'lib/himari/refresh_token.rb', line 35

def session_handle
  @session_handle
end

#updated_atObject (readonly)

Returns the value of attribute updated_at.



35
36
37
# File 'lib/himari/refresh_token.rb', line 35

def updated_at
  @updated_at
end

#versionObject (readonly)

Returns the value of attribute version.



35
36
37
# File 'lib/himari/refresh_token.rb', line 35

def version
  @version
end

Class Method Details

.default_lifetimeObject

Raises:

  • (ArgumentError)


14
15
16
# File 'lib/himari/refresh_token.rb', line 14

def self.default_lifetime
  raise ArgumentError, "RefreshToken requires an explicit lifetime:"
end

.magic_headerObject



10
11
12
# File 'lib/himari/refresh_token.rb', line 10

def self.magic_header
  'hmrt'
end

Instance Method Details

#as_jsonObject



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/himari/refresh_token.rb', line 77

def as_json
  {
    handle: handle,
    secret_hash: secret_hash,
    secret_hash_prev: secret_hash_prev,
    client_id: client_id,
    claims: claims,
    session_handle: session_handle,
    openid: openid,
    scopes: scopes,
    expiry: expiry.to_i,
    version: version,
    updated_at: updated_at.to_i,
  }
end

#as_logObject



62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/himari/refresh_token.rb', line 62

def as_log
  {
    handle: handle,
    client_id: client_id,
    claims: claims,
    session_handle: session_handle,
    openid: openid,
    scopes: scopes,
    expiry: expiry,
    version: version,
    updated_at: updated_at,
    prev_secret_set: !secret_hash_prev.nil?,
  }
end

#rotate(claims:, openid:, now: Time.now) ⇒ Object

Rotate the token in place (same handle): mint a new current secret while keeping the just-presented secret valid as the previous one, so a client whose rotation response is lost can retry with the secret it still holds. The secret to keep is the hash verify! matched (TokenString#verification) — whichever slot the client used; rotate is therefore only valid after a successful verify!. version is bumped so a concurrent refresh against the version we read fails the conditional update. expiry is preserved: the initial lifetime is an absolute cap on the rotation chain, not slid forward on each refresh.



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/himari/refresh_token.rb', line 44

def rotate(claims:, openid:, now: Time.now)
  raise TokenString::SecretMissing, "rotate requires a verified secret; call verify! first" unless verification

  self.class.new(
    handle:,
    client_id:,
    session_handle:,
    claims:,
    openid:,
    scopes:,
    secret: SecureRandom.urlsafe_base64(48),
    secret_hash_prev: verification.secret_hash,
    version: version + 1,
    updated_at: now.to_i,
    expiry:,
  )
end