Jak mogę dekodować google OAuth 2.0 JWT (OpenID Connect) w aplikacji node?

Mam tu kawał czasu, próbując użyć google OAuth do uwierzytelniania użytkowników w mojej aplikacji node express. Mogę z powodzeniem zrobić OAuth, który zwraca odpowiedź w ten sposób:

{
  access_token: 'token string',
  id_token: 'id.string',
  expires_in: 3599,
  token_type: "Bearer"
}
To wszystko ma sens, ale nie mogę na całe życie wymyślić, jak rozszyfrować JWT. Jestem trochę niedoświadczony w tym wszystkim, więc to wszystko jest dla mnie trochę obce.

Postępuj zgodnie z instrukcjami podanymi tutaj: https://developers.google.com/accounts/docs/OAuth2Login#validatinganidtoken Próbuję dekodować JWT lokalnie w mojej aplikacji węzła.

Zainstalowałem https://github.com/hokaccha/node-jwt-simple w moim środowisku węzłów.

I jestem pewien, że muszę użyć tego certyfikatu ( https://www.googleapis.com/oauth2/v1/certs ) w tym wszystkim jakoś to rozszyfrować, ale jestem w trochę przegranej tutaj. Nie bardzo rozumiem, w jaki sposób mogę dostać certyfikat do mojej aplikacji node, a następnie jak go używać z node-JWT-simple. I nie bardzo zrozum, skąd wiem, kiedy muszę pobrać świeży certyfikat, a nie używać buforowanego.

Ktoś ma w tym jakieś doświadczenie, które może mi pomóc? Dzięki za pomoc. Jestem kompletnie zagubiony w tym momencie.

** Update * *

Więc poczyniłem pewne postępy... Tak jakby. Dzwoniąc do jwt.decode (id_token, certificate, true); jestem w stanie pomyślnie zdekodować token. Nawet jeśli certyfikat var jest pustym obiektem {}. Pozostaje mi jeszcze 3 pytania. 1: Jaki jest najlepszy sposób, aby uzyskać certyfikat do aplikacji My express przy użyciu adresu URL od google? 2: Skąd będę wiedział, kiedy muszę pobrać jego świeżą wersję? 3: wydaje się, że Przejście W true dla noVerify (3rd arg w jwt.dekodowanie) to okropny pomysł. Jak mogę to uruchomić, nie przekazując tego? Wygląda na to, że jwt-simple spodziewa się hs256, a token używa rs256. Znowu, jestem w tym bardzo niedoświadczony, więc mogę być daleko od podstaw.

* Aktualizacja * Dzięki pomocy Nat udało mi się to uruchomić! Myślę, że wypróbowałem każdy pojedynczy moduł JWT i JWS. To, na czym w końcu wylądowałem, jest następujące: Stwierdziłem, że żaden z modułów, na które patrzyłem, nie zrobił tego, czego chciałem po wyjęciu z pudełka. Stworzyłem następujące metody dekodowania JWT, których używam do dekodowania id_token, więc mogę pobrać dziecko z nagłówka.

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, '/');
}

Używam tego dekodowania, aby określić, czy muszę pobrać nowy publiczny cert z: https://www.googleapis.com/oauth2/v1/certs

Następnie używam tego publicznego cert i node-jws ( https://github.com/brianloveswords/node-jws ) jws.verify (id_token, cert) aby zweryfikować podpis!

Hura! Jeszcze raz dziękuję za dodatkowe wyjaśnienia podane w odpowiedzi. Pomogło mi to zrozumieć, co nawet próbowałem zrobić. Mam nadzieję, że to może pomóc innym.
Author: ThePuzzleMaster, 2013-11-23

1 answers

Z punktu widzenia specyfikacji, to co napotkasz to [OpenID Connect].

Id_token jest podpisem [JWS] [JWT]. W tym przypadku jest to"."rozdzielony łańcuch z trzema składnikami. Pierwsza część to nagłówek. Drugi to ładunek. Trzeci to podpis. Każdy z nich jest zakodowanym łańcuchem Base64url.

Kiedy dekodujesz nagłówek, otrzymasz coś w stylu:

{"alg": "RS256", "kid": "43ebb53b0397e7aaf3087d6844e37d55c5fb1b67"}

The "alg" oznacza, że algorytm sygnatury to RS256, który jest zdefiniowany w [JWA]. "Kid" wskazuje identyfikator klucza publicznego odpowiadający kluczowi używanemu do podpisania.

Teraz jestem gotowy odpowiedzieć na niektóre z twoich pytań:

2: Skąd będę wiedział, kiedy będę musiał wyciągnąć nową wersję?

Jeśli potomek buforowanego pliku cert (pliku [JWK]) nie pasuje do potomka w nagłówku, pobierz nowy plik cert. (BTW, URL, z którego wyciągasz certy są nazywane x5u.)

3: wydaje się, że Przejście W true dla noVerify (3rd arg w jwt.decode) to okropny pomysł. Jak mogę to zrobić, nie przekazując tego w środku?

W rzeczy samej. Być może warto zajrzeć do innej biblioteki, takiej jak kjur.github.io/jsjws /

Referencje

  • [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
 50
Author: Nat Sakimura,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-28 19:38:25