我们正在尝试使用 ruby-jwt 来编码/解码 HS256 签名的 JWT,使用
kid
来指示密钥库中代表要使用的密钥的记录,但似乎我们需要进行 2 次解码才能进行验证。一个解码不使用秘密或向 ruby-jwt 指示我们想要验证 JWT,这样我们就可以从中刮除 kid
,然后第二个解码传递 kid
代表的秘密,以及标志来验证 JWT。这是一件小事,而且 b64 很便宜,但是进行 2 次解码真的是包含 kid
的 HMAC JWT 需要采取的方法吗?这是库的限制,还是关于如何使用 kids
和 HMAC 的知识差距?
keys = {'31b88f20-8edd-49fe-a839-57b8f681888c' => 'mysecret'}
payload = {user_id: 99, kid: keys.first.first, exp: 5.years.from_now.to_i}
token = JWT.encode(payload, keys.first.second, 'HS256')
# Get the kid from the jwt so we can look up what secret to use to verify it by the kid
decoded_jwt = JWT.decode(token, nil, false)
kid = decoded_jwt[0]['kid']
secret = keys[kid]
# decode the jwt again with the secret, and verify it
decoded_jwt = JWT.decode(token, secret, true)
# => [{"user_id"=>99, "kid"=>"31b88f20-8edd-49fe-a839-57b8f681888c", "exp"=>1865946624}, {"alg"=>"HS256"}]
它有效,但试图看看是否有更好的方法。谢谢!
要使用 JWKS 实施此过程,您可以按如下方式操作
require 'jwt'
secret = 'mysecret'
kid = '31b88f20-8edd-49fe-a839-57b8f681888c'
payload = {user_id: 99, exp: 5.years.from_now.to_i}
# Import a JWK Hash
jwk = JWT::JWK.new({ kty: 'oct', k: secret, kid: kid, alg: 'HS256' })
# Encoding
token = JWT.encode(payload, jwk.signing_key, jwk[:alg], kid: jwk[:kid])
# JSON Web Key Set for advertising your signing keys
jwks_hash = JWT::JWK::Set.new(jwk)
#Decoding
jwks = JWT::JWK::Set.new(jwks_hash)
algorithms = jwks.map { |key| key[:alg] }.compact.uniq
decoded = JWT.decode(token, nil, true, algorithms: algorithms, jwks: jwks)
decoded[0] == payload
#=> true