Class: GoInstant::Auth::Signer

Inherits:
Object
  • Object
show all
Defined in:
lib/goinstant/auth/signer.rb

Overview

Creates JWTs from user-hashes, signing with your GoInstant app secret key.

Instance Method Summary collapse

Constructor Details

#initialize(secret_key) ⇒ Signer

Create a Signer with a particular key.

A single Signer can be used to create multiple tokens.

representing the secret key for your GoInstant App.

Parameters:

  • secret_key (String)

    A base64 or base64url format string

Raises:

  • (TypeError)

    when the key isn’t in base64/base64url format.

  • (SignerError)

    when the key is too short



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 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

Instance Method Details

#sign(user_data, extra_headers = {}) ⇒ String

Create and sign a token for a user.

Parameters:

  • user_data (Hash)

    properties about this user. See README.md for a complete list of options.

  • extra_headers (Hash) (defaults to: {})

    Optional, additional JWT headers to include.

Returns:

  • (String)

    a JWS Compact Serialization format-string representing this user.

Raises:

  • (SignerError)

    if a required user or group claim is missing



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# 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