Module: Sandal

Defined in:
lib/sandal.rb,
lib/sandal/enc.rb,
lib/sandal/sig.rb,
lib/sandal/util.rb,
lib/sandal/claims.rb,
lib/sandal/sig/es.rb,
lib/sandal/sig/hs.rb,
lib/sandal/sig/rs.rb,
lib/sandal/enc/alg.rb,
lib/sandal/version.rb,
lib/sandal/enc/agcm.rb,
lib/sandal/enc/acbc_hs.rb,
lib/sandal/enc/alg/direct.rb,
lib/sandal/enc/alg/rsa1_5.rb,
lib/sandal/enc/alg/rsa_oaep.rb

Overview

A library for creating and reading JSON Web Tokens (JWT), supporting JSON Web Signatures (JWS) and JSON Web Encryption (JWE).

Currently supports draft-06 of the JWT spec, and draft-08 of the JWS and JWE specs.

Defined Under Namespace

Modules: Claims, Enc, Sig Classes: ClaimError, TokenError

Constant Summary collapse

DEFAULT_OPTIONS =

The default options for token handling.

ignore_exp

Whether to ignore the expiry date of the token. This setting is just to help get things working and should always be false in real apps!

ignore_nbf

Whether to ignore the not-before date of the token. This setting is just to help get things working and should always be false in real apps!

ignore_signature

Whether to ignore the signature of signed (JWS) tokens. This setting is just tohelp get things working and should always be false in real apps!

max_clock_skew

The maximum clock skew, in seconds, when validating times. If your server time is out of sync with the token server then this can be increased to take that into account. It probably shouldn’t be more than about 300.

valid_iss

A list of valid token issuers, if validation of the issuer claim is required.

valid_aud

A list of valid audiences, if validation of the audience claim is required.

{
  ignore_exp: false,
  ignore_nbf: false,
  ignore_signature: false,
  max_clock_skew: 0,
  valid_iss: [],
  valid_aud: [],
}
VERSION =

The semantic version of the library.

'0.3.0'

Class Method Summary collapse

Class Method Details

.decode_token(token) {|header, options| ... } ⇒ Hash or String

Decodes and validates a signed JSON Web Token.

The block is called with the token header as the first parameter, and should return the appropriate signature method to validate the signature. It can optionally have a second options parameter which can be used to override the DEFAULT_OPTIONS on a per-token basis.

Parameters:

  • token (String)

    The encoded JSON Web Token.

Yield Parameters:

  • header (Hash)

    The JWT header values.

  • options (Hash)

    (Optional) A hash that can be used to override the default options.

Yield Returns:

  • (#valid?)

    The signature validator.

Returns:

  • (Hash or String)

    The payload of the token as a Hash if it was JSON, otherwise as a String.

Raises:



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/sandal.rb', line 104

def self.decode_token(token)
  parts = token.split('.')
  header, payload, signature = decode_jws_token_parts(parts)

  options = DEFAULT_OPTIONS.clone
  validator = yield header, options if block_given?
  validator ||= Sandal::Sig::NONE

  unless options[:ignore_signature]
    secured_input = parts.take(2).join('.')
    unless validator.valid?(signature, secured_input)
      raise TokenError, 'Invalid signature.'
    end
  end

  parse_and_validate(payload, header['cty'], options)
end

.decrypt_token(token) {|header, options| ... } ⇒ Hash or String

Decrypts and validates an encrypted JSON Web Token.

The block is called with the token header as the first parameter, and should return the appropriate encryption method to decrypt the token. It can optionally have a second options parameter which can be used to override the DEFAULT_OPTIONS on a per-token basis.

Parameters:

  • token (String)

    The encrypted JSON Web Token.

Yield Parameters:

  • header (Hash)

    The JWT header values.

  • options (Hash)

    (Optional) A hash that can be used to override the default options.

Yield Returns:

  • (#decrypt)

    The token decrypter.

Returns:

  • (Hash or String)

    The payload of the token as a Hash if it was JSON, otherwise as a String.

Raises:



155
156
157
158
159
160
161
162
163
164
165
# File 'lib/sandal.rb', line 155

def self.decrypt_token(token)
  parts = token.split('.')
  decoded_parts = decode_jwe_token_parts(parts)
  header = decoded_parts[0]

  options = DEFAULT_OPTIONS.clone
  decrypter = yield header, options if block_given?

  payload = decrypter.decrypt(parts, decoded_parts)
  parse_and_validate(payload, header['cty'], options)
end

.default!(defaults) ⇒ Hash

Overrides the default options.

Parameters:

  • defaults (Hash)

    The options to override (see DEFAULT_OPTIONS for details).

Returns:

  • (Hash)

    The new default options.



59
60
61
# File 'lib/sandal.rb', line 59

def self.default!(defaults)
  DEFAULT_OPTIONS.merge!(defaults)
end

.encode_token(payload, signer, header_fields = nil) ⇒ String

Creates a signed JSON Web Token.

Parameters:

  • payload (String or Hash)

    The payload of the token. Hashes will be encoded as JSON.

  • signer (#name, #sign)

    The token signer, which may be nil for an unsigned token.

  • header_fields (Hash) (defaults to: nil)

    Header fields for the token (note: do not include ‘alg’).

Returns:

  • (String)

    A signed JSON Web Token.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/sandal.rb', line 72

def self.encode_token(payload, signer, header_fields = nil)
  signer ||= Sandal::Sig::NONE

  header = {}
  header['alg'] = signer.name if signer.name != Sandal::Sig::NONE.name
  header = header_fields.merge(header) if header_fields
  header = MultiJson.dump(header)

  payload = MultiJson.dump(payload) unless payload.is_a?(String)

  sec_input = [header, payload].map { |p| jwt_base64_encode(p) }.join('.')
  signature = signer.sign(sec_input)
  [sec_input, jwt_base64_encode(signature)].join('.')
end

.encrypt_token(payload, encrypter, header_fields = nil) ⇒ String

Creates an encrypted JSON Web Token.

Parameters:

  • payload (String)

    The payload of the token.

  • encrypter (#name, #alg, #encrypt)

    The token encrypter.

  • header_fields (Hash) (defaults to: nil)

    Header fields for the token (note: do not include ‘alg’ or ‘enc’).

Returns:

  • (String)

    An encrypted JSON Web Token.



129
130
131
132
133
134
135
136
# File 'lib/sandal.rb', line 129

def self.encrypt_token(payload, encrypter, header_fields = nil)
  header = {}
  header['enc'] = encrypter.name
  header['alg'] = encrypter.alg.name
  header = header_fields.merge(header) if header_fields

  encrypter.encrypt(header, payload)
end