Skip to content

Commit a626e32

Browse files
committed
refactored jwt signature validation to use more built in jwt methods
1 parent c35ac6f commit a626e32

2 files changed

Lines changed: 11 additions & 33 deletions

File tree

app/controllers/concerns/alma_jwt_validator.rb

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,18 @@ def jwk_set
1818

1919
# rubocop:disable Metrics/MethodLength
2020
def decode_and_verify_jwt(token)
21-
# Decode header to get the 'kid'
22-
header = JWT.decode(token, nil, false).last
23-
kid = header['kid']
24-
25-
# Find the key from the JWK set
26-
jwk = jwk_set.keys.find { |key| key.kid == kid }
27-
raise JWT::VerificationError, 'Key not found in JWKS' unless jwk
28-
29-
public_key = jwk.public_key
30-
3121
options = {
3222
algorithm: 'RS256',
3323
verify_expiration: true,
3424
verify_aud: false,
3525
verify_iss: true,
36-
iss: EXPECTED_ISS
26+
iss: EXPECTED_ISS,
27+
jwks: jwk_set
3728
}
3829

39-
# Returns [payload, header] array if valid
40-
JWT.decode(token, public_key, true, options)
41-
rescue JWT::ExpiredSignature
42-
raise JWT::VerificationError, 'Token has expired'
43-
rescue JWT::InvalidIssuerError
44-
raise JWT::VerificationError, 'Token issuer mismatch'
30+
JWT.decode(token, nil, true, options)
4531
rescue JWT::DecodeError => e
46-
raise JWT::VerificationError, "Invalid JWT: #{e.message}"
32+
raise JWT::VerificationError, e.message
4733
end
4834
# rubocop:enable Metrics/MethodLength
4935
end

spec/controllers/concerns/alma_jwt_validator_spec.rb

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,10 @@
1313
let(:kid) { 'test-key-id' }
1414
let(:test_payload) { { 'userName' => '10335026', 'iss' => expected_iss } }
1515

16-
# Helper to create JWK from RSA public key
17-
def create_jwk(public_key, kid)
18-
n = Base64.urlsafe_encode64(public_key.n.to_s(2)).gsub(/=+$/, '')
19-
e = Base64.urlsafe_encode64(public_key.e.to_s(2)).gsub(/=+$/, '')
20-
{
21-
'kty' => 'RSA',
22-
'kid' => kid,
23-
'use' => 'sig',
24-
'alg' => 'RS256',
25-
'n' => n,
26-
'e' => e
27-
}
16+
# Helper to create JWK hash from RSA key using JWT::JWK
17+
def create_jwk_hash(key, kid)
18+
jwk = JWT::JWK.new(key, kid: kid)
19+
jwk.export
2820
end
2921

3022
# Helper to generate a valid JWT
@@ -34,7 +26,7 @@ def generate_jwt(payload, key, kid, algorithm = 'RS256')
3426
end
3527

3628
before do
37-
jwk = create_jwk(rsa_key.public_key, kid)
29+
jwk = create_jwk_hash(rsa_key, kid)
3830

3931
stub_request(:get, jwks_url)
4032
.to_return(
@@ -79,10 +71,10 @@ def generate_jwt(payload, key, kid, algorithm = 'RS256')
7971
end
8072

8173
context 'with a malformed JWT' do
82-
it 'raises JWT::DecodeError' do
74+
it 'raises JWT::VerificationError' do
8375
expect do
8476
AlmaJwtValidator.decode_and_verify_jwt('not.a.jwt')
85-
end.to raise_error(JWT::DecodeError)
77+
end.to raise_error(JWT::VerificationError)
8678
end
8779
end
8880

0 commit comments

Comments
 (0)