class GoInstant::Auth::Signer
Creates JWTs from user-hashes, signing with your GoInstant
app secret key.
Constants
- OPTIONAL_CLAIMS
Optional user_data properties and their corresponding JWT claim name
- REQUIRED_CLAIMS
Required user_data properties and their corresponding JWT claim name
- REQUIRED_GROUP_CLAIMS
Required group properties and their corresponding JWT claim name
Public Class Methods
Create a Signer
with a particular key.
A single Signer
can be used to create multiple tokens.
@param secret_key [String] A base64 or base64url format string representing the secret key for your GoInstant
App.
@raise [TypeError] when the key isn’t in base64/base64url format. @raise [SignerError] when the key is too short
# File lib/goinstant/auth/signer.rb, line 24 def initialize(secret_key) if secret_key.nil? then raise TypeError.new('Signer requires key in base64url or base64 format') end @binary_key = Auth.decode64(secret_key) if !@binary_key or @binary_key == '' then raise TypeError.new('Signer requires key in base64url or base64 format') end if @binary_key.size < 32 then raise SignerError.new( 'expected key length >= 32 bytes, got %d bytes' % @binary_key.size ) end end
Private Class Methods
Maps optional claims, mutating in-place (caller should clone).
@param claims [Hash] modified to use JWT claim names @param table [Hash] conversion table of optional keys
# File lib/goinstant/auth/signer.rb, line 131 def self.map_optional_claims(claims, table) table.each do |name,claimName| if claims.has_key?(name) then claims[claimName] = claims.delete(name) end end return claims end
Maps required claims, mutating in-place (caller should clone).
@raise [SignerError] if a required claim is missing @param claims [Hash] modified to use JWT claim names @param table [Hash] conversion table of required keys @param msg [String] message format for the SignerError
# File lib/goinstant/auth/signer.rb, line 117 def self.map_required_claims(claims, table, msg="missing required key: %s") table.each do |name,claimName| if !claims.has_key?(name) then raise SignerError.new(msg % name) end claims[claimName] = claims.delete(name) end return claims end
Public Instance Methods
Create and sign a token for a user.
@param user_data [Hash] properties about this user.
See README.md for a complete list of options.
@param extra_headers [Hash] Optional, additional JWT headers to include.
@raise [SignerError] if a required user or group claim is missing
@return [String] a JWS Compact Serialization format-string representing this user.
# File lib/goinstant/auth/signer.rb, line 51 def sign(user_data, extra_headers={}) if !user_data.is_a?(Hash) then raise SignerError.new('Signer#sign() requires a user_data Hash') end claims = user_data.clone Signer.map_required_claims(claims, REQUIRED_CLAIMS) Signer.map_optional_claims(claims, OPTIONAL_CLAIMS) claims[:aud] = 'goinstant.net' claims[:sub] = claims[:sub].to_s if claims.has_key?(:g) then groups = claims[:g] if !groups.is_a?(Array) then raise SignerError.new('groups must be an Array') end i = 0 claims[:g] = groups.map do |group| group = group.clone msg = "group #{i} missing required key: %s" i += 1 Signer.map_required_claims(group, REQUIRED_GROUP_CLAIMS, msg) group[:id] = group[:id].to_s group end else claims[:g] = [] end headers = extra_headers.clone headers[:typ] = 'JWT' headers[:alg] = 'HS256' signing_input = '%s.%s' % [headers, claims].map{ |x| Auth.compact_encode(x) } sig = OpenSSL::HMAC::digest('SHA256', @binary_key, signing_input) return '%s.%s' % [ signing_input, Auth.encode64(sig) ] end