class AccessToken
Constants
- AUTHORIZATION_HEADER
- BEARER_HEADER
- BEARER_REGEX
- EXPIRES_HEADER
- ID_KEY
- SIGNATURE_KEY
- TIME_KEY
- VERSION
Attributes
encryptor[R]
Set the token encryptor strategy. By default it uses the Parsel::JSON encryptor.
request[R]
Set the HTTP request object. It must implement the `ip` and `user_agent` methods.
response[R]
Set the HTTP response object. It must implement the `headers` method.
secret[R]
Set the encryption secret.
store[R]
Set the token store strategy. By default it uses in-memory store.
ttl[R]
Set the token TTL. Defaults to 86400 (24 hours).
Public Class Methods
new(request:, response:, secret:, ttl: 3600, store: NullStore.new, encryptor: Parsel::JSON)
click to toggle source
# File lib/access_token.rb, line 40 def initialize(request:, response:, secret:, ttl: 3600, store: NullStore.new, encryptor: Parsel::JSON) @request = request @response = response @store = store @secret = secret @ttl = ttl @encryptor = encryptor end
Public Instance Methods
bearer()
click to toggle source
# File lib/access_token.rb, line 77 def bearer request.env[AUTHORIZATION_HEADER].to_s[BEARER_REGEX, 1] end
fresh?(timestamp)
click to toggle source
# File lib/access_token.rb, line 81 def fresh?(timestamp) timestamp > Time.now.to_i - ttl end
request_signature()
click to toggle source
# File lib/access_token.rb, line 49 def request_signature @request_signature ||= Digest::SHA1.hexdigest("#{request.ip}#{request.user_agent}") end
resolve(token = bearer)
click to toggle source
# File lib/access_token.rb, line 64 def resolve(token = bearer) return unless store.key?(token) data = encryptor.decrypt(secret, token) store.del(token) return unless data return unless fresh?(data[TIME_KEY]) return unless secure_compare?(request_signature, data[SIGNATURE_KEY]) data[ID_KEY] end
secure_compare?(a, b)
click to toggle source
# File lib/access_token.rb, line 85 def secure_compare?(a, b) return false if a.blank? || b.blank? || a.bytesize != b.bytesize l = a.unpack "C#{a.bytesize}" res = 0 b.each_byte { |byte| res |= byte ^ l.shift } res == 0 end
update(record)
click to toggle source
# File lib/access_token.rb, line 53 def update(record) now = Time.now timestamp = now.to_i data = {TIME_KEY => timestamp, SIGNATURE_KEY => request_signature, ID_KEY => record.id} token = encryptor.encrypt(secret, data) store.set(token, timestamp, ttl) response[BEARER_HEADER] = token response[EXPIRES_HEADER] = (Time.now + ttl).httpdate token end