lib/toktok/token.rb in toktok-0.1.0 vs lib/toktok/token.rb in toktok-0.2.0
- old
+ new
@@ -1,48 +1,69 @@
+require 'jwt'
+
module Toktok
InvalidIdentity = Class.new(StandardError)
+ InvalidSignature = Class.new(StandardError)
class Token
attr_reader :config, :jwt, :payload
- def initialize(identity: nil, jwt: nil)
+ def initialize(identity: nil, jwt: nil, payload: nil)
@config = Toktok.config
@payload = {}
if jwt
initialize_decode(jwt, identity)
else
- initialize_encode(identity)
+ initialize_encode(identity, payload)
end
end
def identity
- payload['sub']
+ payload[:sub]
end
private
- def initialize_encode(identity)
- @payload['sub'] = identity
+ def initialize_encode(identity, extra)
+ prepare_payload(identity, extra)
+ normalize_payload
@jwt = JWT.encode(payload, config.secret_key, config.algorithm)
end
def initialize_decode(jwt, identity)
@jwt = jwt
options = decode_options(identity)
decoded_token = JWT.decode(jwt, config.secret_key, algorithm?, options)
- @payload = decoded_token[0]
+ @payload = symbolize_keys(decoded_token[0])
@header = decoded_token[1]
rescue JWT::InvalidSubError
raise InvalidIdentity, "Invalid identity. Expected #{identity}"
+ rescue JWT::VerificationError
+ raise InvalidSignature, 'Invalid or manipulated signature'
end
def decode_options(identity)
options = { algorithm: config.algorithm }
options = options.merge(sub: identity, verify_sub: true) if identity
options
end
def algorithm?
config.algorithm != 'none'
+ end
+
+ def prepare_payload(identity, extra = nil)
+ @payload.merge!(symbolize_keys(extra)) if extra
+ @payload[:sub] = identity
+ @payload[:exp] = Time.now.to_i + config.lifetime if config.lifetime.to_i > 0
+ end
+
+ # Guarantee the order in which the keys are inserted
+ def normalize_payload
+ @payload = Hash[payload.keys.sort.map { |k| [k, payload[k]] }]
+ end
+
+ def symbolize_keys(hash)
+ Hash[hash.map { |k, v| [k.to_sym, v] }]
end
end
end