Class: Philiprehberger::SignedPayload::Signer
- Inherits:
-
Object
- Object
- Philiprehberger::SignedPayload::Signer
- Defined in:
- lib/philiprehberger/signed_payload/signer.rb
Constant Summary collapse
- ALGORITHMS =
{ sha256: 'SHA256', sha384: 'SHA384', sha512: 'SHA512' }.freeze
Instance Method Summary collapse
- #decode(token) ⇒ Object
-
#expired?(token) ⇒ Boolean
Check if a token has expired without verifying the signature.
-
#initialize(key:, algorithm: :sha256) ⇒ Signer
constructor
A new instance of Signer.
-
#peek(token) ⇒ Hash
Inspect token metadata without verifying the signature.
-
#refresh(token, expires_in:) ⇒ String
Re-sign a verified token with a new expiration.
- #sign(data, expires_in: nil) ⇒ Object
-
#sign_with_exp(data, exp:) ⇒ String
Re-sign a verified token’s payload preserving the original expiration timestamp.
- #valid?(token) ⇒ Boolean
-
#verify(token, keys: nil) ⇒ Object
Verify a token’s signature and decode its payload.
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
53 54 55 56 57 58 59 |
# File 'lib/philiprehberger/signed_payload/signer.rb', line 53 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.
91 92 93 94 95 96 97 98 99 |
# File 'lib/philiprehberger/signed_payload/signer.rb', line 91 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.
105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/philiprehberger/signed_payload/signer.rb', line 105 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.
67 68 69 70 |
# File 'lib/philiprehberger/signed_payload/signer.rb', line 67 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 |
#sign_with_exp(data, exp:) ⇒ String
Re-sign a verified token’s payload preserving the original expiration timestamp. Used internally by key rotation to avoid shifting expiry during re-signing.
78 79 80 81 82 83 84 85 |
# File 'lib/philiprehberger/signed_payload/signer.rb', line 78 def sign_with_exp(data, exp:) hash = { 'data' => data } hash['exp'] = exp unless exp.nil? payload = JSON.generate(hash) encoded = Base64.urlsafe_encode64(payload) signature = compute_signature(encoded) "#{encoded}.#{Base64.urlsafe_encode64(signature)}" end |
#valid?(token) ⇒ Boolean
46 47 48 49 50 51 |
# File 'lib/philiprehberger/signed_payload/signer.rb', line 46 def valid?(token) verify(token) true rescue Error false end |
#verify(token, keys: nil) ⇒ Object
Verify a token’s signature and decode its payload.
38 39 40 41 42 43 44 |
# File 'lib/philiprehberger/signed_payload/signer.rb', line 38 def verify(token, keys: nil) raise ArgumentError, 'no keys provided' if keys.is_a?(Array) && keys.empty? encoded, sig = split_token(token) verify_signature!(encoded, sig, keys: keys) decode_payload(encoded) end |