class Slosilo::JWT

A JWT-formatted Slosilo token. @note This is not intended to be a general-purpose JWT implementation.

Attributes

claims[RW]
header[RW]
signature[RW]

Public Class Methods

new(claims = {}) click to toggle source

Create a new unsigned token with the given claims. @param claims [#to_h] claims to embed in this token.

# File lib/slosilo/jwt.rb, line 9
def initialize claims = {}
  @claims = JSONHash[claims]
end
parse_compact(raw) click to toggle source

Parse a token in compact representation

# File lib/slosilo/jwt.rb, line 14
def self.parse_compact raw
  load *raw.split('.', 3).map(&Base64.method(:urlsafe_decode64))
end
parse_json(raw) click to toggle source

Parse a token in JSON representation. @note only single signature is currently supported.

# File lib/slosilo/jwt.rb, line 20
def self.parse_json raw
  raw = JSON.load raw unless raw.respond_to? :to_h
  parts = raw.to_h.values_at(*%w(protected payload signature))
  fail ArgumentError, "input not a complete JWT" unless parts.all?
  load *parts.map(&Base64.method(:urlsafe_decode64))
end

Private Class Methods

load(header, payload, signature) click to toggle source

Create a JWT token object from existing header, payload, and signature strings. @param header [#to_s] URLbase64-encoded representation of the protected header @param payload [#to_s] URLbase64-encoded representation of the token payload @param signature [#to_s] URLbase64-encoded representation of the signature

# File lib/slosilo/jwt.rb, line 63
def self.load header, payload, signature
  self.new(JSONHash.load payload).tap do |token|
    token.header = JSONHash.load header
    token.signature = signature.to_s.freeze
    token.freeze
  end
end

Public Instance Methods

add_signature(header, &sign) click to toggle source

Add a signature. @note currently only a single signature is handled; the token will be frozen after this operation.

# File lib/slosilo/jwt.rb, line 30
def add_signature header, &sign
  @claims = canonicalize_claims.freeze
  @header = JSONHash[header].freeze
  @signature = sign[string_to_sign].freeze
  freeze
end
string_to_sign() click to toggle source
# File lib/slosilo/jwt.rb, line 37
def string_to_sign
  [header, claims].map(&method(:encode)).join '.'
end
to_json(*a) click to toggle source

Returns the JSON serialization of this JWT.

# File lib/slosilo/jwt.rb, line 42
def to_json *a
  {
    protected: encode(header),
    payload: encode(claims),
    signature: encode(signature)
  }.to_json *a
end
to_s() click to toggle source

Returns the compact serialization of this JWT.

# File lib/slosilo/jwt.rb, line 51
def to_s
  [header, claims, signature].map(&method(:encode)).join('.')
end

Private Instance Methods

canonicalize_claims() click to toggle source
# File lib/slosilo/jwt.rb, line 71
def canonicalize_claims
  claims[:iat] = Time.now unless claims.include? :iat
  claims[:iat] = claims[:iat].to_time.to_i
  claims[:exp] = claims[:exp].to_time.to_i if claims.include? :exp
  JSONHash[claims.to_a]
end
encode(s) click to toggle source

Convenience method to make the above code clearer. Converts to string and urlbase64-encodes.

# File lib/slosilo/jwt.rb, line 80
def encode s
  Base64.urlsafe_encode64 s.to_s
end