Class: Philiprehberger::SignedPayload::Signer

Inherits:
Object
  • Object
show all
Defined in:
lib/philiprehberger/signed_payload/signer.rb

Constant Summary collapse

ALGORITHMS =
{
  sha256: 'SHA256',
  sha384: 'SHA384',
  sha512: 'SHA512'
}.freeze

Instance Method Summary collapse

Constructor Details

#initialize(key:, algorithm: :sha256) ⇒ Signer

Returns a new instance of Signer.



16
17
18
19
# File 'lib/philiprehberger/signed_payload/signer.rb', line 16

def initialize(key:, algorithm: :sha256)
  @key = key
  @algorithm = validate_algorithm!(algorithm)
end

Instance Method Details

#decode(token) ⇒ Object



41
42
43
44
45
46
47
# File 'lib/philiprehberger/signed_payload/signer.rb', line 41

def decode(token)
  encoded, _sig = split_token(token)
  parsed = JSON.parse(Base64.urlsafe_decode64(encoded))
  parsed['data']
rescue JSON::ParserError
  raise MalformedToken, 'invalid payload encoding'
end

#expired?(token) ⇒ Boolean

Check if a token has expired without verifying the signature.

Parameters:

  • token (String)

    the token to check

Returns:

  • (Boolean)

    true if the token has expired or has no expiration



64
65
66
67
68
69
70
71
72
# File 'lib/philiprehberger/signed_payload/signer.rb', line 64

def expired?(token)
  encoded, _sig = split_token(token)
  parsed = JSON.parse(Base64.urlsafe_decode64(encoded))
  return false unless parsed.key?('exp')

  parsed['exp'] <= Time.now.to_i
rescue JSON::ParserError
  raise MalformedToken, 'invalid payload encoding'
end

#peek(token) ⇒ Hash

Inspect token metadata without verifying the signature.

Parameters:

  • token (String)

    the token to inspect

Returns:

  • (Hash)

    with :data, :exp (Integer or nil), and :expired (Boolean)



78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/philiprehberger/signed_payload/signer.rb', line 78

def peek(token)
  encoded, _sig = split_token(token)
  parsed = JSON.parse(Base64.urlsafe_decode64(encoded))
  exp = parsed['exp']
  {
    data: parsed['data'],
    exp: exp,
    expired: exp ? exp <= Time.now.to_i : false
  }
rescue JSON::ParserError
  raise MalformedToken, 'invalid payload encoding'
end

#refresh(token, expires_in:) ⇒ String

Re-sign a verified token with a new expiration.

Parameters:

  • token (String)

    the token to refresh

  • expires_in (Integer)

    new TTL in seconds

Returns:

  • (String)

    a new token with the same data and a fresh expiration

Raises:



55
56
57
58
# File 'lib/philiprehberger/signed_payload/signer.rb', line 55

def refresh(token, expires_in:)
  data = verify(token)
  sign(data, expires_in: expires_in)
end

#sign(data, expires_in: nil) ⇒ Object



21
22
23
24
25
26
# File 'lib/philiprehberger/signed_payload/signer.rb', line 21

def sign(data, expires_in: nil)
  payload = build_payload(data, expires_in)
  encoded = Base64.urlsafe_encode64(payload)
  signature = compute_signature(encoded)
  "#{encoded}.#{Base64.urlsafe_encode64(signature)}"
end

#valid?(token) ⇒ Boolean

Returns:

  • (Boolean)


34
35
36
37
38
39
# File 'lib/philiprehberger/signed_payload/signer.rb', line 34

def valid?(token)
  verify(token)
  true
rescue Error
  false
end

#verify(token) ⇒ Object



28
29
30
31
32
# File 'lib/philiprehberger/signed_payload/signer.rb', line 28

def verify(token)
  encoded, sig = split_token(token)
  verify_signature!(encoded, sig)
  decode_payload(encoded)
end