Как проверить подпись 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 ответ

У вас есть три проблемы с вашим кодом.

  1. из-за асинхронного характера промисов, keyполучает значение, когда обещание выполнено (в .thenчасть), но это происходит после вызова следующей строки.

    Поместите console.log(key)сразу после строки jose.JWK.asKey(...и вы видите, что в результате вы получаете «неопределенное». Так что на самом деле ключа нет.

  2. значение в JWK обрабатывается как октет в кодировке Base64Url. Когда вы подписываете токен, вы должны использовать декодированное значение base64url , но не напрямую.

  3. секрет «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помогает выбрать правильный.

Другие вопросы по тегам