ユーザーが Google アカウントを選択すると、ワンタップ ログイン クライアントは Google ID トークンを取得します。ID トークンはユーザー ID の署名付きアサーションです。これにはユーザーの基本的なプロフィール情報も含まれます。Google によって確認済みのメールアドレスが含まれる場合もあります。
ID トークンが使用可能な場合は、それを使用してアプリのバックエンドで安全に認証できます。また、ユーザーのメールアドレスを確認しなくても、ユーザーを新しいユーザーに自動的に登録できます。
ID トークンを使用してユーザーのログインまたは登録を行うには、トークンをアプリのバックエンドに送信します。バックエンドで、Google API クライアント ライブラリまたは汎用 JWT ライブラリを使用してトークンを検証します。ユーザーが以前にこの Google アカウントでアプリにログインしたことがない場合は、新しいアカウントを作成します。
必要に応じてノンスを使用してリプレイ攻撃を回避する場合は、getNonce を使用して ID トークンとともにバックエンド サーバーに送信し、期待される値を確認します。ユーザーの安全性とセキュリティを高めるため、ノンスを使用することを強くおすすめします。
認証情報オブジェクトから ID トークンを取得する
ユーザーの認証情報を取得したら、認証情報オブジェクトに ID トークンが含まれているかどうかを確認します。ある場合は、バックエンドに送信します。
Java
public class YourActivity extends AppCompatActivity { // ... private static final int REQ_ONE_TAP = 2; // Can be any integer unique to the Activity. private boolean showOneTapUI = true; // ... @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case REQ_ONE_TAP: try { SignInCredential credential = oneTapClient.getSignInCredentialFromIntent(data); String idToken = credential.getGoogleIdToken(); if (idToken != null) { // Got an ID token from Google. Use it to authenticate // with your backend. Log.d(TAG, "Got ID token."); } } catch (ApiException e) { // ... } break; } } }
Kotlin
class YourActivity : AppCompatActivity() { // ... private val REQ_ONE_TAP = 2 // Can be any integer unique to the Activity private var showOneTapUI = true // ... override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (requestCode) { REQ_ONE_TAP -> { try { val credential = oneTapClient.getSignInCredentialFromIntent(data) val idToken = credential.googleIdToken when { idToken != null -> { // Got an ID token from Google. Use it to authenticate // with your backend. Log.d(TAG, "Got ID token.") } else -> { // Shouldn't happen. Log.d(TAG, "No ID token!") } } } catch (e: ApiException) { // ... } } } // ... }
ID トークンの整合性を検証する
HTTPS POST で 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
クレームを確認できます。これは、ホストされている Pod が ユーザーのドメインです。これは、リソースへのアクセスをそのメンバーのみに制限する場合に できます。このクレームがない場合、アカウントは Google がホストするドメイン。
email
、email_verified
、hd
フィールドを使用して、
Google はメールアドレスをホストし、その権威があります。Google が信頼できる場合、
そのユーザーが正当なアカウント所有者であることがわかっているため、パスワードやその他の
確認しましょう。
Google が信頼できるケース:
email
には@gmail.com
という接尾辞が付いています。これは Gmail アカウントです。email_verified
は true で、hd
が設定されています。これは G Suite アカウントです。
ユーザーは Gmail や G Suite を使用せずに Google アカウントを登録できます。日時
email
に @gmail.com
という接尾辞がなく、hd
が存在しないと、Google にはありません。
認証には、信頼できる認証方法、パスワード、その他の本人確認方法を使用することが推奨されます。
できます。email_verified
も、Google が最初に検証した
ユーザーに付与できますが、サードパーティの所有権が付与されます。
アカウントが変更された可能性があります。
これらの検証ステップを実行するために独自のコードを記述するのではなく、
プラットフォームに適した Google API クライアント ライブラリを使用するか、
JWT ライブラリ。開発とデバッグの場合は、tokeninfo
を呼び出すことができます。
検証エンドポイントを指定します。
Google API クライアント ライブラリの使用
本番環境で Google ID トークンを検証するには、いずれかの Google API クライアント ライブラリ(Java、Node.js、PHP、Python など)を使用することをおすすめします。
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 CLIENT_ID of the app that accesses the backend: .setAudience(Collections.singletonList(CLIENT_ID)) // Or, if multiple clients access the backend: //.setAudience(Arrays.asList(CLIENT_ID_1, CLIENT_ID_2, 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 の組織アカウントを表すことを検証する必要がある場合は、Payload.getHostedDomain()
メソッドから返されたドメイン名を確認して hd
クレームを検証できます。アカウントをドメインまたは組織によって管理するには、email
クレームのドメインだけでは不十分です。
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: CLIENT_ID, // Specify the CLIENT_ID of the app that accesses the backend // Or, if multiple clients access the backend: //[CLIENT_ID_1, CLIENT_ID_2, 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
クレームを確認できます。リソースへのアクセスを特定のドメインのメンバーのみに制限する場合は、このオプションを使用する必要があります。このクレームがない場合、アカウントは Google がホストするドメインに属していません。
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' => $CLIENT_ID]); // Specify the 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
クレームを確認できます。リソースへのアクセスを特定のドメインのメンバーのみに制限する場合は、このオプションを使用する必要があります。このクレームがない場合、アカウントは Google がホストするドメインに属していません。
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 CLIENT_ID of the app that accesses the backend: idinfo = id_token.verify_oauth2_token(token, requests.Request(), CLIENT_ID) # Or, if multiple clients access the backend server: # idinfo = id_token.verify_oauth2_token(token, requests.Request()) # if idinfo['aud'] not in [CLIENT_ID_1, CLIENT_ID_2, 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
クレームを検証します。また、verify_oauth2_token
が返すオブジェクトを調べて、hd
クレームを検証する必要があります(該当する場合)。複数のクライアントがバックエンド サーバーにアクセスする場合は、aud
クレームも手動で確認します。
tokeninfo エンドポイントの呼び出し
tokeninfo
エンドポイントを使用すると、デバッグのために ID トークンの署名を簡単に検証できます。このエンドポイントを呼び出すと、追加のネットワーク リクエストが必要になりますが、検証の大部分は、独自のコードで適切な検証とペイロード抽出のテストを行います。リクエストがスロットリングされたり、断続的にエラーが発生する可能性があるため、本番環境コードでの使用には適していません。
tokeninfo
エンドポイントを使用して ID トークンを検証するには、エンドポイントに HTTPS POST または GET リクエストを作成し、id_token
パラメータで ID トークンを渡します。たとえば、トークン「XYZ123」を検証するには、次の GET リクエストを作成します。
https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123
トークンが適切に署名され、iss
クレームと exp
クレームに想定される値がある場合は、HTTP 200 レスポンスが返されます。本文には JSON 形式の ID トークン クレームが含まれます。以下はレスポンスの例です。
{ // These six fields are included in all Google ID Tokens. "iss": "https://accounts.google.com", "sub": "110169484474386276334", "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com", "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com", "iat": "1433978353", "exp": "1433981953", // These seven fields are only included when the user has granted the "profile" and // "email" OAuth scopes to the application. "email": "testuser@gmail.com", "email_verified": "true", "name" : "Test User", "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg", "given_name": "Test", "family_name": "User", "locale": "en" }
ID トークンが Google Workspace アカウントを表すことを検証する必要がある場合は、ユーザーのホスト ドメインを示す hd
クレームを確認できます。リソースへのアクセスを特定のドメインのメンバーのみに制限する場合は、このオプションを使用する必要があります。このクレームがない場合、アカウントは Google Workspace でホストされているドメインに属していません。
アカウントまたはセッションを作成する
トークンを検証したら、ユーザーがすでにユーザー データベースに登録されているかどうかを確認します。該当する場合は、ユーザーの認証済みセッションを確立します。ユーザーがユーザー データベースにまだ登録されていない場合は、ID トークン ペイロードの情報から新しいユーザー レコードを作成し、ユーザーのセッションを確立します。アプリで新しく作成されたユーザーを検出したときに、必要な追加のプロフィール情報の入力をユーザーに求めることができます。
クロスアカウント保護機能でユーザーのアカウントを保護する
ユーザーのログインを Google に任せると、ユーザーデータを保護するために Google が構築したすべてのセキュリティ機能とインフラストラクチャが自動的に使用されます。ただし、万が一ユーザーの Google アカウントが不正使用された場合や、他の重大なセキュリティ イベントが発生した場合、アプリが攻撃に対して脆弱になる可能性もあります。重大なセキュリティ イベントからアカウントをより適切に保護するには、クロスアカウント保護機能を使用して Google からセキュリティ通知を受信します。これらのイベントを受け取ると、ユーザーの Google アカウントのセキュリティに関する重要な変更を可視化し、アカウントを保護するためのアクションを実行できます。