バックエンドと通信するアプリやサイトで Google ログインを使用する場合 現在ログインしているユーザーを特定する必要があります。 これを安全に行うために、ユーザーがログインに成功したら、ユーザーの HTTPS を使用してサーバーに送信される ID トークン。次に、サーバーで整合性を検証し、 トークンに含まれるユーザー情報を使用して 新しいアカウントを作成することもできます。
ID トークンをサーバーに送信する
まず、ユーザーがログインしたら、ID トークンを取得します。
-
Google ログインを構成するときに、
requestIdToken
メソッドを呼び出して、サーバーのウェブ クライアント ID を渡します。// Request only the user's ID token, which can be used to identify the // user securely to your backend. This will contain the user's basic // profile (name, profile picture URL, etc) so you should not need to // make an additional call to personalize your application. GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) .requestIdToken(getString(R.string.server_client_id)) .requestEmail() .build();
-
アプリが起動したら、ユーザーがすでに Google を使用してアプリにログインしていることを確認します。 このデバイスまたは別のデバイス(
silentSignIn
を呼び出して作成)GoogleSignIn.silentSignIn() .addOnCompleteListener( this, new OnCompleteListener<GoogleSignInAccount>() { @Override public void onComplete(@NonNull Task<GoogleSignInAccount> task) { handleSignInResult(task); } });
-
ユーザーがサイレント ログインできない場合は、通常のログアウト エクスペリエンスを表示し、ユーザーにログイン オプションを提供します。ユーザーがログインしたら、ログイン インテントのアクティビティの結果でユーザーの
GoogleSignInAccount
を取得します。// This task is always completed immediately, there is no need to attach an // asynchronous listener. Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data); handleSignInResult(task);
-
ユーザーがサイレント ログインまたは明示的にログインしたら、
GoogleSignInAccount
オブジェクトから ID トークンを取得します。private void handleSignInResult(@NonNull Task<GoogleSignInAccount> completedTask) { try { GoogleSignInAccount account = completedTask.getResult(ApiException.class); String idToken = account.getIdToken(); // TODO(developer): send ID Token to server and validate updateUI(account); } catch (ApiException e) { Log.w(TAG, "handleSignInResult:error", e); updateUI(null); } }
次に、HTTPS POST リクエストを使用して ID トークンをサーバーに送信します。
HttpClient httpClient = new DefaultHttpClient(); HttpPost httpPost = new HttpPost("https://yourbackend.example.com/tokensignin"); try { List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(1); nameValuePairs.add(new BasicNameValuePair("idToken", idToken)); httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs)); HttpResponse response = httpClient.execute(httpPost); int statusCode = response.getStatusLine().getStatusCode(); final String responseBody = EntityUtils.toString(response.getEntity()); Log.i(TAG, "Signed in as: " + responseBody); } catch (ClientProtocolException e) { Log.e(TAG, "Error sending ID token to backend.", e); } catch (IOException e) { Log.e(TAG, "Error sending ID token to backend.", e); }
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
クレームを確認します。これは、リソースへのアクセスを特定のドメインのメンバーのみに制限する場合に使用する必要があります。このクレームがない場合、アカウントが Google ホスト型ドメインに属していないことを示します。
email
、email_verified
、hd
の各フィールドを使用して、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 クライアント ライブラリのいずれか( Java、 Node.js、 PHP、 Python など) は、本番環境で Google ID トークンを検証する場合におすすめの方法です。
<ph type="x-smartling-placeholder">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
申請では不十分です
できます。
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 がホストするドメインです。
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 がホストするドメインです。
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
クレームも手動で検証します。
tokeninfo エンドポイントの呼び出し
デバッグ用の ID トークンの署名を検証する簡単な方法は次のとおりです。
tokeninfo
エンドポイントを使用する。このエンドポイントを呼び出すには、
追加のネットワーク リクエストを作成し、適切なテストを行いながら、検証の大部分を担います。
独自のコードで検証とペイロード抽出を行えます本番環境での使用には適していない
リクエストが抑制される可能性があります。また、断続的なエラーが発生することがあります。
tokeninfo
エンドポイントを使用して ID トークンを検証するには、HTTPS を使用します。
POST または GET リクエストをエンドポイントに送信し、
id_token
パラメータ。
たとえば、トークン「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 アカウントのセキュリティに関する重要な変更に対する可視性を得る。 アカウントを保護するための措置を講じることができます。