Как я могу декодировать google OAuth 2.0 JWT (OpenID Connect) в приложении узла?
у меня здесь чертовски много времени, пытаясь использовать google OAuth для аутентификации пользователей в моем приложении Node express. Я могу успешно сделать OAuth, который возвращает ответ следующим образом:
{
access_token: 'token string',
id_token: 'id.string',
expires_in: 3599,
token_type: "Bearer"
}
все это имеет смысл, но я не могу для жизни меня понять, как декодировать JWT. Я немного неопытен во всем этом, поэтому все это немного чуждо мне.
следуя инструкциям, приведенным здесь: https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken я пытаюсь декодировать JWT локально в моем приложении узла.
Я установил https://github.com/hokaccha/node-jwt-simple в моей среде узла.
и я уверен, что мне нужно использовать этот сертификат (https://www.googleapis.com/oauth2/v1/certs) во всем этом как-то расшифровать его, но я здесь немного в растерянности. Я действительно не понимаю, как я получите сертификат в мое приложение узла, и после этого, как использовать его с node-jwt-simple. И я также не понимаю, как я знаю,когда мне нужно вытащить новый сертификат, а не использовать кэшированный.
кто-нибудь там с некоторым опытом в этом, что может мне помочь?
Спасибо за любую помощь. Я в полной растерянности.
** обновление **
Итак, я добился некоторого прогресса... Вроде. Позвонив в jwt.декодировать (id_token, сертификат, true); Я могу успешно расшифровать токен. Даже если сертификат var является пустым объектом {}. Это оставляет мне еще 3 вопроса. 1: каков наилучший способ получить сертификат в мое экспресс-приложение, используя url-адрес от google? 2:Как я узнаю, когда мне нужно вытащить новую версию? 3: Похоже, что переход в true для noVerify (3-й arg в jwt.decode) - ужасная идея. Как я могу заставить это работать, не передавая это? Похоже, что, возможно, jwt-simple ожидает hs256 и маркер использует rs256.
опять же, я супер неопытен в этом, поэтому я могу быть далеко от базы здесь.
* обновление * Благодаря помощи Nat, я смог заставить это работать! Я думаю, что я пробовал каждый модуль узла JWT и JWS. В конце концов я приземлился на следующее:: Я обнаружил, что ни один из модулей, на которые я смотрел, не делал того, что я хотел из коробки. Я создал следующие вспомогательные методы декодирования JWT, которые я использую для декодирования маркер, так что я могу получить ребенка из заголовка.
module.exports = {
decodeJwt: function (token) {
var segments = token.split('.');
if (segments.length !== 3) {
throw new Error('Not enough or too many segments');
}
// All segment should be base64
var headerSeg = segments[0];
var payloadSeg = segments[1];
var signatureSeg = segments[2];
// base64 decode and parse JSON
var header = JSON.parse(base64urlDecode(headerSeg));
var payload = JSON.parse(base64urlDecode(payloadSeg));
return {
header: header,
payload: payload,
signature: signatureSeg
}
}
}
function base64urlDecode(str) {
return new Buffer(base64urlUnescape(str), 'base64').toString();
};
function base64urlUnescape(str) {
str += Array(5 - str.length % 4).join('=');
return str.replace(/-/g, '+').replace(/_/g, '/');
}
Я использую это декодирование, чтобы определить, нужно ли мне вытаскивать новый публичный сертификат из:https://www.googleapis.com/oauth2/v1/certs
тогда я использую этот публичный сертификат и node-jws (https://github.com/brianloveswords/node-jws) jws.проверьте (id_token, cert), чтобы проверить подпись!
Ура! Еще раз спасибо за дополнительное объяснение, которое вы дали в своем ответе. Вот и пошла долгий путь, чтобы помочь мне понять, что я даже пытался сделать. Надеюсь, это поможет и другим.
1 ответов
с точки зрения спецификации, вы сталкиваетесь с [OpenID Connect].
id_token-это [JWS] со знаком [JWT]. В данном случае, это ".- разделенная струна с тремя компонентами. Первая часть-заголовок. Второй-полезная нагрузка. Третья подпись. Каждый из них-строка в кодировке Base64url.
когда вы расшифровать заголовок, вы получите что-то вроде:
{"alg": "RS256", "kid": "43ebb53b0397e7aaf3087d6844e37d55c5fb1b67"}
"alg" указывает, что алгоритм подписи RS256, который определен в [JWA]. "Kid" указывает идентификатор ключа открытого ключа, который соответствует ключу, используемому для подписи.
теперь я готов ответить на некоторые ваши вопросы:
2:Как я узнаю, когда мне нужно вытащить новую версию?
когда ребенок кэшируется файл сертификата (файл [JWK]) не соответствует малышу в заголовке, получить новый файл сертификата. (Кстати, URL, из которого вы вытаскиваете сертификаты, называется x5u.)
3: Похоже, что передача true для noVerify (3rd arg в jwt.декодировать) это ужасная идея. Как я могу заставить это работать, не передавая это внутрь?
действительно. Возможно, вы захотите взглянуть на другую библиотеку, такую как kjur.гитуб.io/ jsjws/.
ссылки
- [OpenID Connect] openid.bitbucket.org/openid-connect-core-1_0.html
- [JWS] tools.ietf.org/html/draft-ietf-jose-json-web-signature
- [JWT] tools.ietf.org/html/draft-ietf-oauth-json-web-token
- [JWK] tools.ietf.org/html/draft-ietf-oauth-json-web-keys
- [JWA] tools.ietf.org/html/draft-ietf-jose-json-web-algorithms