2013-11-23 3 views
32

У меня есть время, пытаясь использовать Google OAuth для аутентификации пользователей в моем экспресс-приложении. Я могу успешно сделать OAuth, который возвращает ответ, как так:Как я могу декодировать google OAuth 2.0 JWT (OpenID Connect) в приложении узла?

{ 
    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.decode (id_token, certificate, true); Я могу успешно декодировать токен. Даже если сертификат var является пустым объектом {}. Это оставляет мне еще 3 вопроса. 1: Каков наилучший способ получить сертификат в моем экспресс-приложении, используя URL-адрес Google? 2: Как я узнаю, когда мне нужно вставить новую версию? 3: Кажется, что передача true для noVerify (3rd arg in jwt.decode) - ужасная идея. Как я могу заставить это работать, не передавая это? Похоже, что jwt-simple ожидает hs256, а токен использует rs256.

Опять же, я очень неопытен в этом, поэтому я могу быть здесь вне базы.

* UPDATE * Благодаря помощи Nat, я смог получить эту работу! Я думаю, что я пробовал каждый модуль JWT и JWS. Я наконец приземлился следующим образом: Я обнаружил, что ни один из модулей, на которые я смотрел, не сделал то, что я хотел из коробки. Я создал следующие вспомогательные методы jwt-декодирования, которые я использую для декодирования id_token, поэтому я могу получить ребенка из заголовка.

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

Тогда я использую, что публичный сертификат и узел-JWS (https://github.com/brianloveswords/node-jws) jws.verify (id_token , cert), чтобы проверить подпись!

Ура! Еще раз спасибо за дополнительное объяснение, которое вы дали в своем ответе. Это помогло мне понять, что я даже пытался сделать. Надеюсь, это тоже поможет другим.

ответ

48

С точки зрения спецификации, вы сталкиваетесь с [OpenID Connect].

id_token [JWS] подписан [JWT]. В этом случае это «.». разделенная строка с тремя компонентами. Первая часть - это заголовок. Вторая - полезная нагрузка. Третья - подпись. Каждая из них - кодировка Base64url.

Когда вы расшифровать заголовок, вы получите что-то вроде:

{ "ALG": "RS256", "ребенок": "43ebb53b0397e7aaf3087d6844e37d55c5fb1b67"}

"ALG" указывает на то, что алгоритм подписи это RS256, который определен в [JWA]. «Малыш» указывает идентификатор ключа открытого ключа, который соответствует ключу, используемому для подписи.

Теперь я готов ответить на некоторые вопросы:

2: Как я буду знать, когда мне нужно тянуть в свежей версии этого?

Когда ребенок файла кэшированного сертификата (файл [JWK]) не совпадает с малыша в заголовке, выберите новый файл сертификата. (Кстати, то URL, с которого вы вытаскиваете сертификаты называются x5u.)

3: Похоже, что проходит в верно для noVerify (3-й ARG в jwt.decode) страшная мысль. Как я могу заставить это работать, не передавая это ?

Действительно. Возможно, вам захочется взглянуть на другую библиотеку, такую ​​как kjur.github.io/jsjws/.

Ссылки

  • [OpenID Connect] openid.bitbucket.org/openid-connect-core-1_0.html
  • [JWS] tools.ietf.org/html/draft-ietf- хосе-JSON-веб-подпись
  • [JWT] tools.ietf.org/html/draft-ietf-oauth-json-web-token
  • [JWK] tools.ietf.org/html/draft-ietf -oauth-json-web-ключи
  • [JWA] tools.ietf.org/html/draft-ietf-j ose-json-web-алгоритмы
+0

Удивительный! Большое спасибо за подробное и подробное объяснение. Это очень помогло мне понять, что я даже пытался сделать. И теперь я знаю, что я должен искать, если у меня есть еще вопросы. Я очень ценю это. – ThePuzzleMaster

Смежные вопросы