JWS - nov/json-jwt GitHub Wiki

JSON Web Signature (JWS)

Signing

In this gem, you'll generate a JSON::JWT instance, then call JSON::JWT#sign(key, algorithm).

How to generate a JSON::JWT instance is described in JWT.

If algorithm is ommited, RS256 will be used as default.
(For historical reasons, HS256 is the default when a String key is given.)

When the given key is a JSON::JWK instance, and it has kid, then generated JSON::JWS instance has the same kid value in its header automatically.

HMAC***

shared_key = 'shared-key'
jwt.sign(shared_key) # HS256 is the default when a String key is given
jwt.sign(shared_key, :HS384)
jwt.sign(shared_key, :HS512)

RSA***

private_key = OpenSSL::PKey::RSA.new(2048)
jwt.sign(private_key) # RS256 is the default when a RSA private key is given
jwt.sign(private_key, :RS384)
jwt.sign(private_key, :RS512)

RSA-PSS***

private_key = OpenSSL::PKey::RSA.new(2048)
jwt.sign(private_key, :PS256)
jwt.sign(private_key, :PS384)
jwt.sign(private_key, :PS512)

ECDSA-SHA

private_key = OpenSSL::PKey::EC.new('prime256v1').generate_key
jwt.sign(private_key) # ES256 is auto-detected when prime256v1 key is given
jwt.sign(private_key, :ES256)

private_key = OpenSSL::PKey::EC.new('secp384r1').generate_key
jwt.sign(private_key) # ES384 is auto-detected when secp384r1 key is given
jwt.sign(private_key, :ES384)

private_key = OpenSSL::PKey::EC.new('secp521r1').generate_key
jwt.sign(private_key) # ES512 is auto-detected when secp521r1 key is given
jwt.sign(private_key, :ES512)

Verifying

JSON::JWT#decode(jwt_string, key) is for decoding and verifying compact-seiralized JWT/JWS token.

public_key = JSON::JWK.new(
  kty: 'RSA',
  e: 'AQAB',
  n: '0OIOijENzP0A...'
)
jwt = JSON::JWT.decode 'eyJ...', public_key

You can explicitly specify expected alg.
If you didn't specify the alg, this gem automatically detect it from given JWT header and class of given public key / secret instance.

jwt = JSON::JWT.decode 'eyJ...', public_key, :PS256

You can also skip signature verification at decoding, then verify the signature later by calling JSON::JWS#verify!(key).

jwt = JSON::JWT.decode 'eyJ...', :skip_verification
# DO SOMETHING
jwt.verify! public_key

Serialization

Follow JWT's Serialization section.

jws = jwt.sign(private_key, :RS256)
jws.to_s # => "eyJ..."

Supported Signing Algorithms

These values are supported as signing algorithms.

  • HS256 (HMAC-SHA256)
  • HS384 (HMAC-SHA384)
  • HS512 (HMAC-SHA512)
  • RS256 (RSA-SHA256)
  • RS384 (RSA-SHA384)
  • RS512 (RSA-SHA512)
  • PS256 (RSAPSS-SHA256)
  • PS384 (RSAPSS-SHA384)
  • PS512 (RSAPSS-SHA512)
  • ES256 (ECDSA-SHA256)
  • ES384 (ECDSA-SHA384)
  • ES512 (ECDSA-SHA512)

NOTE: You need OpenSSL gem v2.1.0+ to use PS256, PS384 and PS512.

For each algorithm details, read [RFC7518] JSON Web Algorithms (JWA).

If you don't sign your JWT, then none is used.

Key Representation

Supported key representations are

  • String (for shared key)
  • OpenSSL::PKey::RSA
  • OpenSSL::PKey::EC
  • JSON::JWK
  • JSON::JWK::Set
  • :skip_verification # NOTE: magic word for skipping signature verification

For HMAC keys, String, JSON::JWK and JSON::JWK::Set instances are available.

For RSA/ECDSA keys, OpenSSL::PKey::RSA, OpenSSL::PKey::EC, JSON::JWK and JSON::JWK::Set instances are available.

String-represented RSA/ECDSA keys are not supported.

JSON::JWK::Set key works only when your JWT header includes kid attributes.

About JSON::JWK and JSON::JWK::Set, please read JWK.