class Firebase::FirebaseTokenGenerator

This class handles generating signed authentication tokens for use with Firebase

Constants

CLAIMS_MAP
TOKEN_SEP
TOKEN_VERSION

Public Class Methods

new(secret) click to toggle source

When creating an instance of the generator, you must provide your Firebase Application Secret

# File lib/firebase_token_generator.rb, line 13
def initialize(secret)
  if (!secret.is_a?(String))
    raise ArgumentError, "FirebaseTokenGenerator: secret must be a string."
  end
  @secret = secret
end

Public Instance Methods

create_token(auth_data, options = {}) click to toggle source

Returns a signed Firebase Authentication Token Takes the following arguments:

auth_data

A hash of arbitrary data to be included in the token

options

An optional hash of extra claims that may be included in the token. Allowed values are:

expires

Epoch time after which the token will no longer be valid

notBefore

Epoch time before which the token will not be valid

admin

If set to true, this client will bypass all security rules

debug

If set to true, this client will receive debug information about the security rules

simulate

(internal-only for now) Runs security rules but makes no data changes

Throws ArgumentError if given invalid data or an invalid option Throws RuntimeError if generated token is too long

# File lib/firebase_token_generator.rb, line 32
def create_token(auth_data, options = {})
  if (auth_data.nil? or auth_data.empty?) and (options.nil? or options.empty?)
    raise ArgumentError, "FirebaseTokenGenerator.create_token: data is empty and no options are set.  This token will have no effect on Firebase."
  end
  validate_auth_data(auth_data, (!options.nil? and options[:admin] == true))
  claims = create_options_claims(options)
  claims[:v] = TOKEN_VERSION
  claims[:iat] = Time.now.to_i
  claims[:d] = auth_data
  token = encode_token(claims)
  if (token.length > 1024)
    raise RuntimeError, "FirebaseTokenGenerator.create_token: generated token is too long."
  end
  token
end

Private Instance Methods

create_options_claims(options) click to toggle source
# File lib/firebase_token_generator.rb, line 74
def create_options_claims(options)
  opts = {}
  options.each do |key, value|
    if value.respond_to?(:strftime) then
      value = value.strftime("%s").to_i
    end
    if CLAIMS_MAP.include?(key.to_sym) then
      opts[CLAIMS_MAP[key.to_sym]] = value
    else
      raise ArgumentError, "FirebaseTokenGenerator.create_token: #{key.to_s} is not a valid option"
    end
  end
  opts
end
encode(s) click to toggle source
# File lib/firebase_token_generator.rb, line 101
def encode(s)
  Base64.urlsafe_encode64(s).gsub('=', '')
end
encode_json(obj) click to toggle source
# File lib/firebase_token_generator.rb, line 97
def encode_json(obj)
  encode(JSON.dump(obj))
end
encode_token(claims) click to toggle source
# File lib/firebase_token_generator.rb, line 89
def encode_token(claims)
  encoded_header = encode_json({:typ => "JWT", :alg => "HS256"})
  encoded_claims = encode_json(claims)
  secure_bits = [encoded_header, encoded_claims].join(TOKEN_SEP)
  sig = sign(secure_bits)
  [encoded_header, encoded_claims, sig].join(TOKEN_SEP)
end
sign(to_sign) click to toggle source
# File lib/firebase_token_generator.rb, line 105
def sign(to_sign)
  encode(OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, @secret, to_sign))
end
validate_auth_data(auth_data, is_admin_token) click to toggle source
# File lib/firebase_token_generator.rb, line 62
def validate_auth_data(auth_data, is_admin_token)
  if (!auth_data.nil? && !auth_data.is_a?(Hash))
    raise ArgumentError, "FirebaseTokenGenerator.create_token: auth data must be a hash"
  end
  contains_uid = (!auth_data.nil? and auth_data.has_key?(:uid))
  if ((!contains_uid and !is_admin_token) or (contains_uid and !auth_data[:uid].is_a?(String)))
    raise ArgumentError, "FirebaseTokenGenerator.create_token: auth data must contain a :uid key that must be a string."
  elsif (contains_uid and (auth_data[:uid].length > 256))
    raise ArgumentError, "FirebaseTokenGenerator.create_token: auth data must contain a :uid key that must not be longer than 256 bytes."
  end
end