サーバー側で Google ID トークンを確認する

Google が ID トークンを返すと、HTTP POST メソッド リクエストによって、パラメータ名 credential とともにログイン エンドポイントに送信されます。

次の例は、ID トークンを検証して使用する一般的な手順を示しています。

  1. クロスサイト リクエスト フォージェリ(CSRF)トークンを検証します。ログイン エンドポイントに認証情報を送信する際は、CSRF 攻撃を防ぐためにダブル送信 Cookie パターンを使用します。送信のたびにトークンが生成されます。次に、次のコード例に示すように、トークンが Cookie と POST 本文の両方に配置されます。

    csrf_token_cookie = self.request.cookies.get('g_csrf_token')
    if not csrf_token_cookie:
        webapp2.abort(400, 'No CSRF token in Cookie.')
    csrf_token_body = self.request.get('g_csrf_token')
    if not csrf_token_body:
        webapp2.abort(400, 'No CSRF token in post body.')
    if csrf_token_cookie != csrf_token_body:
        webapp2.abort(400, 'Failed to verify double submit cookie.')
    
  2. ID トークンを検証します。

    トークンが有効であることを確認するには、次の条件が満たされていることを確認します。

    • ID トークンは Google によって適切に署名されています。トークンの署名を確認するには、Google の公開鍵(JWK 形式または PEM 形式で入手可能)を使用します。これらの鍵は定期的にローテーションされます。レスポンスの Cache-Control ヘッダーを調べて、再度取得するタイミングを確認してください。
    • ID トークンの aud の値が、アプリのクライアント ID のいずれかと等しい。このチェックは、悪意のあるアプリに発行された ID トークンが、アプリのバックエンド サーバーで同じユーザーのデータにアクセスするために使用されるのを防ぐために必要です。
    • ID トークンの iss の値が accounts.google.com または https://accounts.google.com と等しい。
    • ID トークンの有効期限(exp)が切れていない。
    • ID トークンが Google Workspace または Cloud 組織アカウントを表していることを検証する必要がある場合は、ユーザーのホストドメインを示す hd クレームを確認します。これは、リソースへのアクセスを特定のドメインのメンバーのみに制限する場合に使用する必要があります。このクレームがない場合、アカウントが Google ホスト型ドメインに属していないことを示します。

    emailemail_verifiedhd の各フィールドを使用して、Google がメールアドレスをホストし、そのメールアドレスの権限を持っているかどうかを判断できます。Google が権限を持つ場合、ユーザーが正当なアカウント所有者であることがわかっているため、パスワードなどのチャレンジ方法をスキップできます。

    Google が信頼できる情報源となるケース:

    • email@gmail.com という接尾辞が付いている場合、これは Gmail アカウントです。
    • email_verified が true で hd が設定されている場合、これは Google Workspace アカウントです。

    ユーザーは Gmail や Google Workspace を使用せずに Google アカウントに登録できます。email@gmail.com 接尾辞が含まれておらず、hd が存在しない場合、Google は権威がなく、ユーザーの確認にはパスワードなどのチャレンジ メソッドが推奨されます。Google アカウントの作成時に Google がユーザーを最初に確認しているため、email_verified が true になることもあります。ただし、サードパーティのメール アカウントの所有権がその後変更されている可能性があります。

    これらの検証手順を実行する独自のコードを作成するのではなく、プラットフォーム用の Google API クライアント ライブラリまたは汎用 JWT ライブラリを使用することを強くおすすめします。開発とデバッグでは、tokeninfo 検証エンドポイントを呼び出すことができます。

    Google API クライアント ライブラリの使用

    Google API クライアント ライブラリのいずれか( JavaNode.jsPHPPython など) は、本番環境で Google ID トークンを検証する場合におすすめの方法です。

    <ph type="x-smartling-placeholder">
    </ph> <ph type="x-smartling-placeholder">
    </ph>
    Java

    Java で ID トークンを検証するには、 GoogleIdTokenVerifier オブジェクトです。例:

    import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken;
    import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
    import com.google.api.client.googleapis.auth.oauth2.GoogleIdTokenVerifier;
    
    ...
    
    GoogleIdTokenVerifier verifier = new GoogleIdTokenVerifier.Builder(transport, jsonFactory)
        // Specify the WEB_CLIENT_ID of the app that accesses the backend:
        .setAudience(Collections.singletonList(WEB_CLIENT_ID))
        // Or, if multiple clients access the backend:
        //.setAudience(Arrays.asList(WEB_CLIENT_ID_1, WEB_CLIENT_ID_2, WEB_CLIENT_ID_3))
        .build();
    
    // (Receive idTokenString by HTTPS POST)
    
    GoogleIdToken idToken = verifier.verify(idTokenString);
    if (idToken != null) {
      Payload payload = idToken.getPayload();
    
      // Print user identifier
      String userId = payload.getSubject();
      System.out.println("User ID: " + userId);
    
      // Get profile information from payload
      String email = payload.getEmail();
      boolean emailVerified = Boolean.valueOf(payload.getEmailVerified());
      String name = (String) payload.get("name");
      String pictureUrl = (String) payload.get("picture");
      String locale = (String) payload.get("locale");
      String familyName = (String) payload.get("family_name");
      String givenName = (String) payload.get("given_name");
    
      // Use or store profile information
      // ...
    
    } else {
      System.out.println("Invalid ID token.");
    }

    GoogleIdTokenVerifier.verify() メソッドで JWT を検証する 署名、aud クレーム、iss クレーム、 exp の申し立て。

    ID トークンが Google Workspace または Cloud 組織アカウントの場合は、ドメイン名を確認することで hd クレームを確認できます。 Payload.getHostedDomain() メソッドが返す値。ドメインの アカウントがドメインによって管理されていることを確認するには email 申請では不十分です できます。

    で確認できます。 <ph type="x-smartling-placeholder">
    </ph>
    Node.js

    Node.js で ID トークンを検証するには、Node.js 用 Google 認証ライブラリを使用します。 ライブラリをインストールします。

    npm install google-auth-library --save
    次に、verifyIdToken() 関数を呼び出します。例:

    const {OAuth2Client} = require('google-auth-library');
    const client = new OAuth2Client();
    async function verify() {
      const ticket = await client.verifyIdToken({
          idToken: token,
          audience: WEB_CLIENT_ID,  // Specify the WEB_CLIENT_ID of the app that accesses the backend
          // Or, if multiple clients access the backend:
          //[WEB_CLIENT_ID_1, WEB_CLIENT_ID_2, WEB_CLIENT_ID_3]
      });
      const payload = ticket.getPayload();
      const userid = payload['sub'];
      // If the request specified a Google Workspace domain:
      // const domain = payload['hd'];
    }
    verify().catch(console.error);

    verifyIdToken 関数は、以下を確認します。 JWT 署名、aud クレーム、exp クレーム、 iss クレーム。

    ID トークンが Google Workspace または Cloud 組織アカウントの場合は、hd クレームを確認できます。これは、ホストされている Pod が ユーザーのドメインです。これは、リソースへのアクセスをメンバーのみに制限する場合に使用します 特定のドメインのこの申し立てがない場合は、アカウントが Google がホストするドメインです。

    で確認できます。 <ph type="x-smartling-placeholder">
    </ph>
    PHP

    PHP で ID トークンを検証するには、PHP 用の Google API クライアント ライブラリを使用します。 ライブラリをインストールします(Composer を使用するなど)。

    composer require google/apiclient
    次に、verifyIdToken() 関数を呼び出します。例:

    require_once 'vendor/autoload.php';
    
    // Get $id_token via HTTPS POST.
    
    $client = new Google_Client(['client_id' => $WEB_CLIENT_ID]);  // Specify the WEB_CLIENT_ID of the app that accesses the backend
    $payload = $client->verifyIdToken($id_token);
    if ($payload) {
      $userid = $payload['sub'];
      // If the request specified a Google Workspace domain
      //$domain = $payload['hd'];
    } else {
      // Invalid ID token
    }

    verifyIdToken 関数は、以下を確認します。 JWT 署名、aud クレーム、exp クレーム、 iss クレーム。

    ID トークンが Google Workspace または Cloud 組織アカウントの場合は、hd クレームを確認できます。これは、ホストされている Pod が ユーザーのドメインです。これは、リソースへのアクセスをメンバーのみに制限する場合に使用します 特定のドメインのこの申し立てがない場合は、アカウントが Google がホストするドメインです。

    で確認できます。 <ph type="x-smartling-placeholder">
    </ph>
    Python

    Python で ID トークンを検証するには、 verify_oauth2_token 使用します。例:

    from google.oauth2 import id_token
    from google.auth.transport import requests
    
    # (Receive token by HTTPS POST)
    # ...
    
    try:
        # Specify the WEB_CLIENT_ID of the app that accesses the backend:
        idinfo = id_token.verify_oauth2_token(token, requests.Request(), WEB_CLIENT_ID)
    
        # Or, if multiple clients access the backend server:
        # idinfo = id_token.verify_oauth2_token(token, requests.Request())
        # if idinfo['aud'] not in [WEB_CLIENT_ID_1, WEB_CLIENT_ID_2, WEB_CLIENT_ID_3]:
        #     raise ValueError('Could not verify audience.')
    
        # If the request specified a Google Workspace domain
        # if idinfo['hd'] != DOMAIN_NAME:
        #     raise ValueError('Wrong domain name.')
    
        # ID token is valid. Get the user's Google Account ID from the decoded token.
        userid = idinfo['sub']
    except ValueError:
        # Invalid token
        pass

    verify_oauth2_token 関数で JWT を検証する aud クレーム、exp クレームの 3 つが存在します。 hd も確認する必要があります (該当する場合は)そのオブジェクトを調べ、 verify_oauth2_token が返品可能。複数のクライアントが aud クレームも手動で検証します。

  3. トークンの有効性が確認できたら、Google ID トークンの情報を使用して、サイトのアカウント ステータスを関連付けることができます。

    • 未登録のユーザー: 必要に応じて、ユーザーが追加のプロファイル情報を提供できる登録ユーザー インターフェース(UI)を表示できます。また、ユーザーは新しいアカウントとログイン中のユーザー セッションをサイレントで作成することもできます。

    • サイトにすでに存在する既存のアカウント: エンドユーザーがパスワードを入力して、以前のアカウントを Google 認証情報にリンクできるウェブページを表示できます。これにより、ユーザーが既存のアカウントにアクセスできることを確認できます。

    • 再びログインする連携ユーザー: ユーザーをサイレント ログインできます。