Class: Shakha::JwtHandler

Inherits:
Object
  • Object
show all
Defined in:
lib/shakha/jwt_handler.rb

Constant Summary collapse

ALGORITHM =
"ES256"

Class Method Summary collapse

Class Method Details

.encode(payload, exp: 24.hours.from_now) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/shakha/jwt_handler.rb', line 13

def encode(payload, exp: 24.hours.from_now)
  secret = signing_key || raise(ConfigurationError, "RSA/EC private key required for signing")

  header = {
    alg: ALGORITHM,
    typ: "JWT",
    kid: key_id
  }

  payload = payload.with_indifferent_access.merge(
    iss: Shakha.config.issuer,
    aud: Shakha.config.audience,
    iat: Time.current.to_i,
    exp: exp.to_i,
    jti: SecureRandom.uuid
  )

  JWT.encode(payload, secret, ALGORITHM, header)
end

.jwksObject



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/shakha/jwt_handler.rb', line 55

def jwks
  {
    keys: [
      {
        kty: "EC",
        crv: "P-256",
        x: Base64.urlsafe_encode64(public_key_point&.x || public_key_raw_point[0..31], padding: false),
        y: Base64.urlsafe_encode64(public_key_point&.y || public_key_raw_point[32..63], padding: false),
        use: "sig",
        alg: ALGORITHM,
        kid: key_id
      }
    ]
  }.to_json
end

.verify(token, audience: nil) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/shakha/jwt_handler.rb', line 33

def verify(token, audience: nil)
  public_key = verification_key || raise(ConfigurationError, "RSA/EC public key required for verification")

  decoded = JWT.decode(
    token,
    public_key,
    true,
    {
      algorithm: ALGORITHM,
      iss: Shakha.config.issuer,
      aud: audience || Shakha.config.audience,
      verify_iss: true,
      verify_aud: true,
      verify_expiration: true
    }
  )

  decoded[0].with_indifferent_access
rescue JWT::DecodeError => e
  raise JWTError, e.message
end