lib/rodauth/features/oauth_jwt_base.rb in rodauth-oauth-1.4.0 vs lib/rodauth/features/oauth_jwt_base.rb in rodauth-oauth-1.5.0
- old
+ new
@@ -165,10 +165,14 @@
def jwk_thumbprint(jwk)
jwk = jwk_import(jwk) if jwk.is_a?(Hash)
jwk.thumbprint
end
+ def private_jwk?(jwk)
+ %w[d p q dp dq qi].any?(&jwk.method(:key?))
+ end
+
def jwt_encode(payload,
jwks: nil,
headers: {},
encryption_algorithm: oauth_jwt_jwe_keys.keys.dig(0, 0),
encryption_method: oauth_jwt_jwe_keys.keys.dig(0, 1),
@@ -220,10 +224,11 @@
jwe_key: oauth_jwt_jwe_keys[[jws_encryption_algorithm, jws_encryption_method]] || oauth_jwt_jwe_keys.values.first,
verify_claims: true,
verify_jti: true,
verify_iss: true,
verify_aud: true,
+ verify_headers: nil,
**
)
jws_key = jws_key.first if jws_key.is_a?(Array)
if jwe_key
@@ -270,10 +275,12 @@
(verify_jti && !verify_jti(claims[:jti], claims))
)
return
end
+ return if verify_headers && !verify_headers.call(claims.header)
+
claims
rescue JSON::JWT::Exception
nil
end
@@ -331,10 +338,14 @@
def jwk_thumbprint(jwk)
jwk = jwk_import(jwk) if jwk.is_a?(Hash)
JWT::JWK::Thumbprint.new(jwk).generate
end
+ def private_jwk?(jwk)
+ jwk_import(jwk).private?
+ end
+
def jwt_encode(payload,
signing_algorithm: oauth_jwt_keys.keys.first,
headers: {}, **)
key = oauth_jwt_keys[signing_algorithm] || _jwt_key
@@ -392,11 +403,12 @@
jws_algorithm: oauth_jwt_public_keys.keys.first || oauth_jwt_keys.keys.first,
jws_key: oauth_jwt_keys[jws_algorithm] || _jwt_key,
verify_claims: true,
verify_jti: true,
verify_iss: true,
- verify_aud: true
+ verify_aud: true,
+ verify_headers: nil
)
jws_key = jws_key.first if jws_key.is_a?(Array)
# verifying the JWT implies verifying:
#
@@ -419,36 +431,38 @@
else
{}
end
# decode jwt
- claims = if is_authorization_server?
- if jwks
- jwks = jwks[:keys] if jwks.is_a?(Hash)
+ claims, headers = if is_authorization_server?
+ if jwks
+ jwks = jwks[:keys] if jwks.is_a?(Hash)
- # JWKs may be set up without a KID, when there's a single one
- if jwks.size == 1 && !jwks[0][:kid]
- key = jwks[0]
- algo = key[:alg]
- key = JWT::JWK.import(key).keypair
- JWT.decode(token, key, true, algorithms: [algo], **verify_claims_params).first
- else
- algorithms = jws_algorithm ? [jws_algorithm] : jwks.select { |k| k[:use] == "sig" }.map { |k| k[:alg] }
- JWT.decode(token, nil, true, algorithms: algorithms, jwks: { keys: jwks }, **verify_claims_params).first
- end
- elsif jws_key
- JWT.decode(token, jws_key, true, algorithms: [jws_algorithm], **verify_claims_params).first
- else
- JWT.decode(token, jws_key, false, **verify_claims_params).first
- end
- elsif (jwks = auth_server_jwks_set)
- algorithms = jwks[:keys].select { |k| k[:use] == "sig" }.map { |k| k[:alg] }
- JWT.decode(token, nil, true, jwks: jwks, algorithms: algorithms, **verify_claims_params).first
- end
+ # JWKs may be set up without a KID, when there's a single one
+ if jwks.size == 1 && !jwks[0][:kid]
+ key = jwks[0]
+ algo = key[:alg]
+ key = JWT::JWK.import(key).keypair
+ JWT.decode(token, key, true, algorithms: [algo], **verify_claims_params)
+ else
+ algorithms = jws_algorithm ? [jws_algorithm] : jwks.select { |k| k[:use] == "sig" }.map { |k| k[:alg] }
+ JWT.decode(token, nil, true, algorithms: algorithms, jwks: { keys: jwks }, **verify_claims_params)
+ end
+ elsif jws_key
+ JWT.decode(token, jws_key, true, algorithms: [jws_algorithm], **verify_claims_params)
+ else
+ JWT.decode(token, jws_key, false, **verify_claims_params)
+ end
+ elsif (jwks = auth_server_jwks_set)
+ algorithms = jwks[:keys].select { |k| k[:use] == "sig" }.map { |k| k[:alg] }
+ JWT.decode(token, nil, true, jwks: jwks, algorithms: algorithms, **verify_claims_params)
+ end
return if verify_claims && verify_aud && !verify_aud(claims["aud"], claims["client_id"])
+ return if verify_headers && !verify_headers.call(headers)
+
claims
rescue JWT::DecodeError, JWT::JWKError
nil
end
@@ -500,9 +514,13 @@
def jwt_encode(_token)
raise "#{__method__} is undefined, redefine it or require either \"jwt\" or \"json-jwt\""
end
def jwt_decode(_token, **)
+ raise "#{__method__} is undefined, redefine it or require either \"jwt\" or \"json-jwt\""
+ end
+
+ def private_jwk?(_jwk)
raise "#{__method__} is undefined, redefine it or require either \"jwt\" or \"json-jwt\""
end
# :nocov:
end
end