web-dev-qa-db-ja.com

ノードアプリでgoogle OAuth 2.0 JWT(OpenID Connect)をデコードするにはどうすればよいですか?

ここでは、google OAuthを使用してノードエクスプレスアプリでユーザーを認証しようとしています。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アプリに証明書を取得する方法と、その後node-jwt-simpleで証明書を使用する方法を本当に理解していません。また、キャッシュされた証明書を使用する場合と比べて、新しい証明書をいつプルする必要があるかを実際にどのように理解しているのかもわかりません。

これで私を助けることができるいくつかの経験がある人はいますか?

助けてくれてありがとう。私はこの時点で完全に迷っています。

**更新**

だから私はいくつかの進歩を遂げました...種類。 jwt.decode(id_token、certificate、true)を呼び出すことにより;トークンを正常にデコードできました。証明書変数が空のオブジェクト{}であっても。これにより、3つの質問が残ります。 1:GoogleのURLを使用して、エクスプレスアプリに証明書を取得する最良の方法は何ですか? 2:いつ新しいバージョンを取り込む必要があるかをどのようにして知ることができますか? 3:noVerify(jwt.decodeの3番目の引数)にtrueを渡すことは、ひどい考えです。それを渡すことなく動作させるにはどうすればよいですか?おそらくjwt-simpleはhs256を期待しており、トークンはrs256を使用しているようです。

繰り返しになりますが、私はこれに非常に不慣れなので、ここから離れることができます。

*更新*Natの助けのおかげで、これを機能させることができました!私はすべてのJWTおよびJWSノードモジュールをすべて試しました。最終的に私が着陸したのは次のとおりです。私が見たモジュールはどれも、私が箱から出して欲しいものをまったく実行しなかったことがわかりました。 id_tokenのデコードに使用している次の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.verify(id_token、cert)を使用して署名を検証しています!

やった!返信で追加の説明をありがとうございます。それは、私がやろうとしていたことを理解するのに大いに役立ちました。これが他の人にも役立つことを願っています。

36
ThePuzzleMaster

仕様の観点から見ると、発生しているのは[OpenID Connect]です。

id_tokenは[JWS]署名済み[JWT]です。この場合、「。」です。 3つのコンポーネントで区切られた文字列。最初の部分はヘッダーです。 2番目はペイロードです。 3番目は署名です。それらはそれぞれBase64urlエンコードされた文字列です。

ヘッダーをデコードすると、次のようなものが得られます:

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

「alg」は、署名アルゴリズムが[JWA]で定義されているRS256であることを示します。 「kid」は、署名に使用されるキーに対応する公開キーのキーIDを示します。

これで、いくつかの質問に答える準備ができました。

2:いつ新しいバージョンを取り込む必要があるかをどのようにして知ることができますか?

キャッシュされた証明書ファイル([JWK]ファイル)の子供がヘッダー内の子供と一致しない場合、新しい証明書ファイルを取得します。 (ところで、証明書をプルするURLはx5uと呼ばれます。)

3:noVerify(jwt.decodeの3番目の引数)にtrueを渡すことは、ひどい考えです。それを渡すことなく動作させるにはどうすればよいですか?

確かに。たぶん、kjur.github.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
54
Nat Sakimura