Как проверить подпись JWT с помощью Node-jose
Я пытаюсь использовать node-jose для проверки подписей моих JWT. Я знаю секрет, но у меня проблемы с преобразованием этого секрета в JWK, используемый для проверки.
Вот пример того, как я пытаюсь создать свой ключ с моим секретом и проверить свой токен. Это приводит к
Error: no key found
.
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXJpYWxfbnVtYmVyIjoiNWYxMGExNjMtMjk2OC00ZDZkLWIyZDgtOGQxNjQwMDNlMmQ0Iiwic2VxIjo1MTI4MTYsIm5hbWUiOiJOYW1lMSIsImlkIjo2NTQsImRlc2NyaXB0aW9uIjoiVGVzdCBEZWNvZGluZyJ9.ahLaTEhdgonxb8rfLG6NjcIg6rqbGzcHkwwFtvb9KTE"
let secret = "SuperSecretKey"
let props = {
kid: "test-key",
alg: "HS256",
use: "sig",
k: secret,
kty: "oct"
}
let key;
jose.JWK.asKey(props).then(function(result) {key = result})
jose.JWS.createVerify(key).verify(token).then(function(result){console.log(result)})
Нужно ли мне изменять свой токен, чтобы включить
kid
заголовок где-нибудь? Правильно ли я генерирую ключ из известного секрета для этой библиотеки?
1 ответ
У вас есть три проблемы с вашим кодом.
из-за асинхронного характера промисов,
key
получает значение, когда обещание выполнено (в.then
часть), но это происходит после вызова следующей строки.Поместите
console.log(key)
сразу после строкиjose.JWK.asKey(...
и вы видите, что в результате вы получаете «неопределенное». Так что на самом деле ключа нет.значение в JWK обрабатывается как октет в кодировке Base64Url. Когда вы подписываете токен, вы должны использовать декодированное значение base64url , но не напрямую.
секрет «SuperSecretKey» слишком короткий для node.jose. Для алгоритма HS256 секрет должен иметь длину 256 бит. node.jose кажется довольно строгим по сравнению с другими библиотеками.
Чтобы решить первую проблему, вы можете либо вложить вызовы (что быстро становится трудно читать), либо использовать синтаксис async/await, как показано ниже:
var jose = require('node-jose')
async function tokenVerifyer()
{
let token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzZXJpYWxfbnVtYmVyIjoiNWYxMGExNjMtMjk2OC00ZDZkLWIyZDgtOGQxNjQwMDNlMmQ0Iiwic2VxIjo1MTI4MTYsIm5hbWUiOiJOYW1lMSIsImlkIjo2NTQsImRlc2NyaXB0aW9uIjoiVGVzdCBEZWNvZGluZyJ9.KK9F14mwi8amhsPT7ppqp_yCYwwOGcHculKByNPlDB8"
let secret = "SuperSecretKeyThatIsLongEnough!!" // A 32 character long secret to get 256 bits.
let props = {
kid: "test-key",
alg: "HS256",
use: "sig",
k: "cynZGe3BenRNOV2AY__-hwxraC9CkBoBMUdaDHgj5bQ",
//k : jose.util.base64url.encode(secret), // alternatively use above secret
kty: "oct"
}
let key = await jose.JWK.asKey(props)
let result = await jose.JWS.createVerify(key).verify(token)
}
tokenVerifyer()
В приведенном выше примере
k
это ключ, сгенерированный на https://mkjwk.org/ , и токен был создан с этим ключом на https://jwt.io (отметьте «секрет в кодировке base64»). В качестве альтернативы вы можете использовать свой собственный секрет, но убедитесь, что он достаточно длинный.
Нужно ли мне изменить свой токен, чтобы включить где-нибудь заголовок для детей?
Небольшой пример выше работает без добавления токена. Для любых реальных приложений вы обычно добавляете в заголовок токена. В вашем хранилище ключей может быть больше ключей или чередующихся ключей, а
kid
помогает выбрать правильный.