Google の OAuth 2.0 API は認証と認可の両方に使用できます。このドキュメントでは、OpenID Connect 仕様に準拠し、OpenID Certified を受けている、認証用の OAuth 2.0 実装について説明します。このサービスには、OAuth 2.0 を使用した Google API へのアクセスのドキュメントも適用されます。このプロトコルをインタラクティブに試すには、Google OAuth 2.0 Playground の使用をおすすめします。 Stack Overflow でヘルプを表示するには、質問に「google-oauth」のタグを付けます。
OAuth 2.0 の設定
アプリケーションでユーザー ログインに Google の OAuth 2.0 認証システムを使用するには、 Google API Console でプロジェクトを設定し、OAuth 2.0 認証情報を取得してリダイレクト URI を設定し、(必要に応じて)ユーザーの同意画面に表示されるブランド情報をカスタマイズする必要があります。また、 API Console を使用して、サービス アカウントの作成、課金の有効化、フィルタリングの設定などのタスクを行うこともできます。詳細については、Google API Consoleヘルプをご覧ください。
OAuth 2.0 認証情報を取得する
ユーザーを認証し、Google の API にアクセスするには、クライアント ID とクライアント シークレットを含む OAuth 2.0 認証情報が必要です。
特定のOAuth 2.0認証情報のクライアントIDとクライアントシークレットを表示するには、次のテキストをクリックします 。 認証情報を選択 。開いたウィンドウで、プロジェクトと必要な認証情報を選択し、[ 表示 ]をクリックします 。
または、 API Console [ 認証情報]ページからクライアントIDとクライアントシークレットを表示しAPI Console 。
- Go to the Credentials page.
- 資格情報の名前または鉛筆( create )アイコンをクリックします。クライアントIDとシークレットはページの上部にあります。
リダイレクト URI を設定する
API Console で設定したリダイレクト URI によって、認証リクエストに対するレスポンスの送信先が決まります。
To create, view, or edit the redirect URIs for a given OAuth 2.0 credential, do the following:
- Go to the Credentials page.
- In the OAuth 2.0 client IDs section of the page, click a credential.
- View or edit the redirect URIs.
If there is no OAuth 2.0 client IDs section on the Credentials page, then your project has no OAuth credentials. To create one, click Create credentials.
ユーザーの同意画面をカスタマイズする
OAuth 2.0 認証には、ユーザーが開示する情報と適用される規約を説明する同意画面が用意されています。たとえば、ユーザーがログインしたときに、メールアドレスと基本的なアカウント情報へのアクセス権をアプリに付与するように求められることがあります。この情報へのアクセスをリクエストするには、scope
パラメータを使用します。このパラメータは、アプリの認証リクエストに含めます。スコープを使用して、他の Google API へのアクセス権をリクエストすることもできます。
ユーザーの同意画面には、プロダクト名、ロゴ、ホームページ URL などのブランド情報も表示されます。ブランディング情報は API Consoleで制御します。
プロジェクトの同意画面を有効にするには:
- Consent Screen pageでGoogle API Consoleます。
- If prompted, select a project, or create a new one.
- フォームに入力して[ 保存 ]をクリックします 。
次の同意ダイアログは、リクエストに OAuth 2.0 と Google ドライブのスコープの組み合わせが含まれている場合にユーザーに表示される内容を示しています。(この汎用ダイアログは Google OAuth 2.0 Playground を使用して生成されたため、 API Consoleで設定されるブランド情報は含まれていません)。
![同意ページのスクリーンショット](https://developers-dot-devsite-v2-prod.appspot.com/static/identity/protocols/oauth2/images/examples/scope-authorization.png?authuser=8&hl=ja)
サービスへのアクセス
Google とサードパーティは、ユーザーの認証や Google API へのアクセスの取得など、実装の詳細の多くを処理するために使用できるライブラリを提供しています。たとえば、Google Identity Services や Google クライアント ライブラリなど、さまざまなプラットフォームで利用できます。
ライブラリを使用しない場合は、このドキュメントの残りの部分の手順に沿って操作してください。このドキュメントでは、使用可能なライブラリの基礎となる HTTP リクエスト フローについて説明しています。
ユーザーの認証
ユーザーの認証には、ID トークンを取得して検証します。ID トークンは OpenID Connect の標準化された機能で、インターネット上で ID アサーションを共有する目的で使用するように設計されています。
ユーザーの認証と ID トークンの取得に最も一般的に使用されるアプローチは、「サーバー」フローと「暗黙的」フローと呼ばれます。サーバーフローでは、アプリケーションのバックエンド サーバーがブラウザまたはモバイル デバイスを使用して本人確認を行うことができます。暗黙的フローは、クライアント側アプリケーション(通常はブラウザで実行されている JavaScript アプリ)が、バックエンド サーバー経由ではなく、直接 API にアクセスする必要がある場合に使用されます。
このドキュメントでは、ユーザーを認証するためのサーバーフローの実行方法について説明します。暗黙的フローは、クライアント側でトークンを処理して使用する際のセキュリティ リスクがあるため、非常に複雑です。暗黙的フローを実装する必要がある場合は、Google Identity Services を使用することを強くおすすめします。
サーバーフロー
API Console内でアプリをセットアップして、これらのプロトコルを使用してユーザーを認証できるようにします。ユーザーが Google でログインしようとすると、管理者は次のことを行う必要があります。
- 偽造防止状態トークンを作成する
- Google に認証リクエストを送信する
- 偽造防止状態トークンを確認する
code
をアクセス トークンと ID トークンを交換する- ID トークンからユーザー情報を取得する
- お客様を認証する
1. 偽造防止状態トークンを作成する
あなたは、リクエスト フォージェリ攻撃を防ぎ、ユーザーのセキュリティを保護する必要があります。最初のステップは、アプリとユーザーのクライアントの間で状態を保持する一意のセッション トークンを作成することです。その後、この一意のセッション トークンと Google OAuth ログイン サービスから返された認証レスポンスを照合して、ユーザーが悪意のある攻撃者ではなく、リクエストを行っていることを確認します。これらのトークンは多くの場合、クロスサイト リクエスト フォージェリ(CSRF)トークンと呼ばれます。
状態トークンに適した選択肢の一つは、高品質の乱数ジェネレータを使用して作成した 30 文字程度の文字列です。もう 1 つは、バックエンドで非公開の鍵を使用してセッション状態変数の一部に署名することで生成されるハッシュです。
次のコードは、一意のセッション トークンを生成する方法を示しています。
PHP
このサンプルを使用するには、PHP 用 Google API クライアント ライブラリをダウンロードする必要があります。
// Create a state token to prevent request forgery. // Store it in the session for later validation. $state = bin2hex(random_bytes(128/8)); $app['session']->set('state', $state); // Set the client ID, token state, and application name in the HTML while // serving it. return $app['twig']->render('index.html', array( 'CLIENT_ID' => CLIENT_ID, 'STATE' => $state, 'APPLICATION_NAME' => APPLICATION_NAME ));
Java
このサンプルを使用するには、Java 用 Google API クライアント ライブラリをダウンロードする必要があります。
// Create a state token to prevent request forgery. // Store it in the session for later validation. String state = new BigInteger(130, new SecureRandom()).toString(32); request.session().attribute("state", state); // Read index.html into memory, and set the client ID, // token state, and application name in the HTML before serving it. return new Scanner(new File("index.html"), "UTF-8") .useDelimiter("\\A").next() .replaceAll("[{]{2}\\s*CLIENT_ID\\s*[}]{2}", CLIENT_ID) .replaceAll("[{]{2}\\s*STATE\\s*[}]{2}", state) .replaceAll("[{]{2}\\s*APPLICATION_NAME\\s*[}]{2}", APPLICATION_NAME);
Python
このサンプルを使用するには、Python 用 Google API クライアント ライブラリをダウンロードする必要があります。
# Create a state token to prevent request forgery. # Store it in the session for later validation. state = hashlib.sha256(os.urandom(1024)).hexdigest() session['state'] = state # Set the client ID, token state, and application name in the HTML while # serving it. response = make_response( render_template('index.html', CLIENT_ID=CLIENT_ID, STATE=state, APPLICATION_NAME=APPLICATION_NAME))
2. Google に認証リクエストを送信する
次のステップでは、適切な URI パラメータを使用して HTTPS GET
リクエストを作成します。このプロセスのすべての手順で HTTP ではなく HTTPS を使用していることに注意してください。HTTP 接続は拒否されます。authorization_endpoint
メタデータ値を使用して、ディスカバリ ドキュメントからベース URI を取得する必要があります。以下の説明では、ベース URI が https://accounts.google.com/o/oauth2/v2/auth
であると仮定しています。
基本リクエストでは、次のパラメータを指定します。
client_id
: API Console Credentials page.response_type
: 基本的な認可コードフロー リクエストではcode
にする必要があります。(詳しくはresponse_type
をご覧ください)。scope
。基本的なリクエストではopenid email
にする必要があります。(詳しくはscope
をご覧ください)。redirect_uri
には、Google からのレスポンスを受け取るサーバー上の HTTP エンドポイントを指定します。この値は、 Credentials pageで構成した OAuth 2.0 クライアント用に承認済みのリダイレクト URI のいずれかと完全に一致する必要があります。 API Consoleこの値が承認済みの URI と一致しない場合、リクエストはredirect_uri_mismatch
エラーで失敗します。state
には、偽造防止の一意のセッション トークンの値と、ユーザーがアプリケーションに戻ったときにコンテキストを復元するために必要なその他の情報(開始 URL など)を含める必要があります。(詳しくはstate
をご覧ください)。nonce
はアプリによって生成されるランダムな値です。存在する場合にリプレイ保護を有効にします。login_hint
には、ユーザーのメールアドレス、またはユーザーの Google ID と同じsub
文字列を指定します。login_hint
を指定せず、ユーザーが現在ログインしている場合、同意画面には、ユーザーのメールアドレスをアプリに解放するための承認リクエストが表示されます(詳しくは、login_hint
をご覧ください)。hd
パラメータを使用して、Google Workspace または Cloud 組織に関連付けられた特定のドメインのユーザーの OpenID Connect フローを最適化します(詳細はhd
をご覧ください)。
以下に、完全な OpenID Connect 認証 URI の例を示します。読みやすくするために改行とスペースを入れています。
https://accounts.google.com/o/oauth2/v2/auth? response_type=code& client_id=424911365001.apps.googleusercontent.com& scope=openid%20email& redirect_uri=https%3A//oauth2.example.com/code& state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foauth2-login-demo.example.com%2FmyHome& login_hint=jsmith@example.com& nonce=0394852-3190485-2490358& hd=example.com
アプリがユーザーに関する新しい情報をリクエストする場合や、ユーザーが以前に承認していないアカウントへのアクセスをリクエストする場合、ユーザーは同意する必要があります。
3. 偽造防止状態トークンを確認する
レスポンスは、リクエストで指定した redirect_uri
に送信されます。以下に示すように、すべてのレスポンスがクエリ文字列で返されます。
https://oauth2.example.com/code?state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Foa2cb.example.com%2FmyHome&code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7&scope=openid%20email%20https://www.googleapis.com/auth/userinfo.email
サーバーで、Google から受け取った state
が、ステップ 1 で作成したセッション トークンと一致することを確認する必要があります。このラウンドトリップ検証により、悪意のあるスクリプトではなくユーザーがリクエストを行っていることを確認できます。
次のコードは、手順 1 で作成したセッション トークンを確認する方法を示しています。
PHP
このサンプルを使用するには、PHP 用 Google API クライアント ライブラリをダウンロードする必要があります。
// Ensure that there is no request forgery going on, and that the user // sending us this connect request is the user that was supposed to. if ($request->get('state') != ($app['session']->get('state'))) { return new Response('Invalid state parameter', 401); }
Java
このサンプルを使用するには、Java 用 Google API クライアント ライブラリをダウンロードする必要があります。
// Ensure that there is no request forgery going on, and that the user // sending us this connect request is the user that was supposed to. if (!request.queryParams("state").equals( request.session().attribute("state"))) { response.status(401); return GSON.toJson("Invalid state parameter."); }
Python
このサンプルを使用するには、Python 用 Google API クライアント ライブラリをダウンロードする必要があります。
# Ensure that the request is not a forgery and that the user sending # this connect request is the expected user. if request.args.get('state', '') != session['state']: response = make_response(json.dumps('Invalid state parameter.'), 401) response.headers['Content-Type'] = 'application/json' return response
4. code
をアクセス トークンと ID トークンと交換する
レスポンスには code
パラメータが含まれます。これは、サーバーがアクセス トークンと ID トークンと交換できるワンタイム認証コードです。サーバーは HTTPS POST
リクエストを送信して、この交換を行います。POST
リクエストがトークン エンドポイントに送信されます。トークン エンドポイントは、token_endpoint
メタデータ値を使用してディスカバリ ドキュメントから取得する必要があります。以下の説明では、エンドポイントが https://oauth2.googleapis.com/token
であることを前提としています。リクエストの POST
本文に次のパラメータを含める必要があります。
フィールド | |
---|---|
code |
最初のリクエストから返される認証コード。 |
client_id |
Credentials pageから取得した API Consoleクライアント ID。OAuth 2.0 認証情報を取得するをご覧ください。 |
client_secret |
Credentials pageから取得したクライアント シークレット。 API Console OAuth 2.0 認証情報を取得するをご覧ください。 |
redirect_uri |
API Console
Credentials pageで指定された特定の client_id の承認済みのリダイレクト URI。リダイレクト URI を設定するをご覧ください。 |
grant_type |
このフィールドには、
OAuth 2.0 仕様で定義されている authorization_code の値を含める必要があります。 |
実際のリクエストは次の例のようになります。
POST /token HTTP/1.1 Host: oauth2.googleapis.com Content-Type: application/x-www-form-urlencoded code=4/P7q7W91a-oMsCeLvIaQm6bTrgtp7& client_id=your-client-id& client_secret=your-client-secret& redirect_uri=https%3A//oauth2.example.com/code& grant_type=authorization_code
このリクエストへの成功レスポンスには、JSON 配列に次のフィールドが含まれます。
フィールド | |
---|---|
access_token |
Google API に送信できるトークン。 |
expires_in |
アクセス トークンの残りの存続期間(秒)。 |
id_token |
Google によってデジタル署名されたユーザーに関する ID 情報を含む JWT。 |
scope |
access_token によって付与されるアクセス スコープ。スペース区切りの文字列(大文字と小文字を区別)のリストとして表されます。 |
token_type |
返されるトークンのタイプを指定します。この時点では、このフィールドの値は常に Bearer です。 |
refresh_token |
(省略可) このフィールドは、認証リクエストで |
5. ID トークンからユーザー情報を取得する
ID トークンは JWT(JSON ウェブトークン)、つまり暗号署名付きの Base64 エンコード JSON オブジェクトです。通常は、使用する前に ID トークンを検証することが非常に重要ですが、中継のない HTTPS チャネルを介して Google と直接通信し、クライアント シークレットを使用して Google への認証を行っているため、受け取ったトークンが本当に Google からのものであり、有効であることを確認できます。サーバーが ID トークンをアプリの他のコンポーネントに渡す場合、他のコンポーネントがトークンを使用する前にトークンを検証することが非常に重要です。
ほとんどの API ライブラリはこの検証と、base64url でエンコードされた値をデコードして JSON を解析する作業を組み合わせているため、ID トークン内のクレームにアクセスするときに、最終的にトークンを検証することになります。
ID トークンのペイロード
ID トークンは、名前と値のペアのセットを含む JSON オブジェクトです。以下に、読みやすい形式で例を示します。
{ "iss": "https://accounts.google.com", "azp": "1234987819200.apps.googleusercontent.com", "aud": "1234987819200.apps.googleusercontent.com", "sub": "10769150350006150715113082367", "at_hash": "HK6E_P6Dh8Y93mRNtsDB1Q", "hd": "example.com", "email": "jsmith@example.com", "email_verified": "true", "iat": 1353601026, "exp": 1353604926, "nonce": "0394852-3190485-2490358" }
Google ID トークンには、次のフィールド(クレーム)が含まれる場合があります。
申し立て | 指定のクレジット カード | 説明 |
---|---|---|
aud |
常に | この ID トークンの対象となるオーディエンス。アプリケーションの OAuth 2.0 クライアント ID のいずれかを指定する必要があります。 |
exp |
常に | ID トークンを受け付けない有効期限。Unix 時間(整数秒)で表されます。 |
iat |
常に | ID トークンが発行された時刻。Unix 時間(整数秒)で表されます。 |
iss |
常に | レスポンスの発行者の発行者 ID。Google ID トークンの場合は、常に https://accounts.google.com または accounts.google.com になります。 |
sub |
常に | ユーザーの識別子。すべての Google アカウントの中で一意であり、再利用されることはありません。Google アカウントは、異なる時点で複数のメールアドレスを持つことができますが、sub 値は変更されません。ユーザーの一意の識別子キーとしてアプリケーション内で sub を使用します。大文字と小文字を区別する ASCII 文字は最大 255 文字です。 |
at_hash |
アクセス トークンのハッシュ。アクセス トークンが ID トークンに関連付けられていることを検証します。サーバーフローで ID トークンが access_token 値で発行された場合、このクレームは常に含まれます。このクレームは、クロスサイト リクエスト フォージェリ攻撃から保護するための代替メカニズムとして使用できますが、ステップ 1 とステップ 3 を行うと、アクセス トークンの検証は不要です。 |
|
azp |
承認済みのプレゼンターの client_id 。このクレームは、ID トークンをリクエストする当事者が ID トークンのオーディエンスと同じでない場合にのみ必要です。Google では、ウェブアプリと Android アプリの OAuth 2.0 client_id が異なるものの、同じ Google API プロジェクトを共有しているハイブリッド アプリの場合がこれに該当します。 |
|
email |
ユーザーのメールアドレス。リクエストに email スコープを含めた場合にのみ提供されます。このクレームの値はこのアカウントに対して一意ではなく、時間の経過とともに変化する可能性があるため、ユーザー レコードにリンクするメインの識別子としてこの値を使用しないでください。また、Google Workspace または Cloud 組織のユーザーの特定に email クレームのドメインに依存することもできません。代わりに hd クレームを使用してください。 |
|
email_verified |
ユーザーのメールアドレスが確認済みであれば true、そうでない場合は false です。 | |
family_name |
ユーザーの姓または名。name クレームが存在する場合に提供されます。 |
|
given_name |
ユーザーの名。name クレームが存在する場合に提供されます。 |
|
hd |
ユーザーの Google Workspace または Cloud の組織に関連付けられているドメイン。 ユーザーが Google Cloud 組織に属している場合にのみ提供されます。リソースへのアクセスを特定のドメインのメンバーのみに制限する場合は、このクレームを確認する必要があります。このクレームがない場合、アカウントは Google がホストするドメインに属していません。 | |
locale |
BCP 47 言語タグで表されるユーザーの言語 / 地域。name クレームが存在する場合に提供されます。 |
|
name |
表示可能な形式でのユーザーの氏名。次の場合に提供される可能性があります。
|
|
nonce |
認証リクエストでアプリによって提供される nonce の値。この攻撃は 1 回だけ提示して、リプレイ攻撃から保護する必要があります。 |
|
picture |
ユーザーのプロフィール写真の URL。次の場合に提供される可能性があります。
|
|
profile |
ユーザーのプロフィール ページの URL。次の場合に提供される可能性があります。
|
6. お客様を認証する
ID トークンからユーザー情報を取得したら、アプリのユーザー データベースにクエリを実行する必要があります。ユーザーがデータベースにすでに存在する場合、Google API レスポンスがすべてのログイン要件を満たしていれば、そのユーザーのアプリケーション セッションを開始する必要があります。
ユーザーがユーザー データベースに存在しない場合は、新規ユーザーの登録フローにユーザーをリダイレクトする必要があります。Google から受け取った情報に基づいてユーザーを自動登録できるか、少なくとも、登録フォームで必要な項目の多くを事前入力できる場合があります。ID トークンの情報に加えて、追加のユーザー プロフィール情報をユーザー プロフィールのエンドポイントで取得できます。
高度なトピック
以下のセクションでは、Google OAuth 2.0 API について詳しく説明します。この情報は、認証と認可に関する高度な要件を持つデベロッパーを対象としています。
他の Google API へのアクセス
認証に OAuth 2.0 を使用する利点の 1 つは、ユーザーの認証と同時に、アプリケーションがユーザーの代わりに他の Google API(YouTube、Google ドライブ、カレンダー、コンタクトなど)を使用する権限を取得できることです。そのためには、Google に送信する認証リクエストに必要な他のスコープを含めます。たとえば、ユーザーの年齢層を認証リクエストに追加するには、scope パラメータ openid email https://www.googleapis.com/auth/profile.agerange.read
を渡します。同意画面で、ユーザーに適切に通知されます。Google から受け取ったアクセス トークンを使用すると、リクエストおよび付与されたアクセス スコープに関連するすべての API にアクセスできます。
更新トークン
API アクセスのリクエストでは、code
の交換の際に更新トークンを返すようにリクエストできます。更新トークンを使用すると、ユーザーがアプリケーションにアクセスしていない間も、アプリから Google API に継続的にアクセスできます。更新トークンをリクエストするには、認証リクエストで access_type
パラメータを offline
に設定します。
考慮事項:
- 更新トークンは、コード交換フローを初めて実行したときにのみ取得できるため、更新トークンを安全かつ永続的に保存してください。
- 発行される更新トークンの数には上限があります(クライアントとユーザーの組み合わせごとに 1 回、すべてのクライアントでユーザーあたりに 1 回)。アプリケーションがリクエストする更新トークンの数が多すぎると、これらの制限に達することがあり、その場合は古い更新トークンが機能しなくなります。
詳細については、アクセス トークンの更新(オフライン アクセス)をご覧ください。
再同意を求める
認証リクエストで prompt
パラメータを consent
に設定すると、アプリの再承認をユーザーに求めることができます。prompt=consent
が含まれていると、アプリがアクセス スコープの承認をリクエストするたびに同意画面が表示されます。これは、すべてのスコープが以前に Google API プロジェクトに付与されている場合も同様です。このため、必要な場合にのみ prompt=consent
を含めます。
prompt
パラメータについて詳しくは、認証 URI パラメータの表の prompt
をご覧ください。
認証 URI パラメータ
次の表は、Google の OAuth 2.0 認証 API で使用できるパラメータの詳細な説明を示しています。
パラメータ | 必須 | 説明 |
---|---|---|
client_id |
(必須) | API Console Credentials pageから取得したクライアント ID の文字列。OAuth 2.0 認証情報を取得するをご覧ください。 |
nonce |
(必須) | アプリによって生成された、リプレイ保護を有効にするランダム値。 |
response_type |
(必須) | 値が code の場合、基本認可コードフローを起動し、トークンを取得するためにトークン エンドポイントに POST を要求します。値が token id_token または id_token token の場合、暗黙的フローが起動し、リダイレクト URI で JavaScript を使用して URI #fragment 識別子からトークンを取得する必要があります。 |
redirect_uri |
(必須) | レスポンスの送信先を指定します。このパラメータの値は、 API Console Credentials page で設定した承認済みのリダイレクト値のいずれかと完全に一致している必要があります(HTTP または HTTPS スキーム、大文字と小文字、末尾の「/」がある場合など)。 |
scope |
(必須) | スコープ パラメータは
これらの OpenID 固有のスコープに加えて、スコープ引数には他のスコープ値を含めることもできます。スコープの値はすべてスペースで区切ります。たとえば、ユーザーの Google ドライブにファイルごとにアクセスする必要がある場合は、scope パラメータに 使用可能なスコープについては、Google API の OAuth 2.0 スコープまたは使用する Google API のドキュメントをご覧ください。 |
state |
(省略可、ただし強く推奨) | プロトコルでラウンドトリップされる不透明な文字列。つまり、Basic フローでは URI パラメータとして返され、暗黙的フローでは URI
|
access_type |
(省略可) | 指定できる値は offline と online です。効果については、オフライン アクセスに記載されています。アクセス トークンがリクエストされている場合、offline の値が指定されていない限り、クライアントは更新トークンを受信しません。 |
display |
(省略可) | 認証サーバーによる認証と同意のユーザー インターフェース ページの表示方法を指定するための ASCII 文字列値。page 、popup 、touch 、wap の値は、指定されて Google のサーバーで受け入れられますが、その動作には影響しません。 |
hd |
(省略可) | Google Cloud 組織が所有するアカウントのログイン プロセスを合理化します。Google Cloud 組織ドメイン(mycollege.edu など)を含めると、アカウント選択 UI がそのドメインのアカウント向けに最適化されるように示すことができます。1 つの Google Cloud 組織ドメインだけではなく、通常 Google Cloud 組織アカウント向けに最適化するには、アスタリスク( クライアントサイドのリクエストは変更される可能性があるため、アプリにアクセスできるユーザーを制御するために、この UI の最適化に依存しないでください。返された ID トークンの |
include_granted_scopes |
(省略可) | このパラメータに値 true を指定し、承認リクエストが許可されている場合、承認には、他のスコープでこのユーザー/アプリケーションの組み合わせに付与されていた以前の承認が含まれます。段階的な承認をご覧ください。インストール済みアプリのフローでは、増分承認を行うことはできません。 |
login_hint |
(省略可) | 認証しようとしているユーザーをアプリが認識している場合、認証サーバーへのヒントとしてこのパラメータを指定できます。このヒントを渡すと、Account Chooser が抑制され、ログイン フォームにメールボックスが事前入力されるか、適切なセッション(ユーザーがマルチログインを使用している場合)が選択されます。これにより、アプリで誤ったユーザー アカウントにログインした場合に発生する問題を回避できます。
値には、メールアドレス、またはユーザーの Google ID に相当する sub 文字列を指定できます。 |
prompt |
(省略可) | 認可サーバーがユーザーに再認証と同意を求めるかどうかを指定する文字列値のスペース区切りリスト。可能な値は次のとおりです。
値が指定されず、ユーザーが以前にアクセスを承認したことがない場合は、同意画面が表示されます。 |
ID トークンの検証
ID トークンが Google から直接取得されたものであることがわかっている場合を除き、サーバーですべての ID トークンを検証する必要があります。たとえば、サーバーはクライアント アプリから受け取るすべての ID トークンを本物として検証する必要があります。
ID トークンをサーバーに送信する一般的な状況は次のとおりです。
- 認証が必要なリクエストとともに ID トークンを送信する。ID トークンは、リクエストを行った特定のユーザーと、その ID トークンが付与されたクライアントを示します。
ID トークンは機密性が高いため、傍受されると悪用される可能性があります。これらのトークンは、HTTPS 経由でのみ、POST データまたはリクエスト ヘッダー内でのみ送信することで、安全に処理する必要があります。ID トークンをサーバーに保存する場合は、ID トークンも安全に保管する必要があります。
ID トークンは、アプリのさまざまなコンポーネントに渡せる点で有用です。これらのコンポーネントは、アプリとユーザーを認証するための軽量な認証メカニズムとして ID トークンを使用できます。ただし、ID トークン内の情報を使用したり、ユーザーが認証されたことを示すアサーションとして ID トークンを使用したりする前に、検証する必要があります。
ID トークンの検証には、いくつかの手順が必要です。
- ID トークンが発行元によって適切に署名されていることを確認します。Google が発行するトークンは、ディスカバリ ドキュメントの
jwks_uri
メタデータ値で指定された URI にある証明書のいずれかを使用して署名されます。 - ID トークンの
iss
クレームの値がhttps://accounts.google.com
またはaccounts.google.com
と等しいことを確認します。 - ID トークンの
aud
クレームの値がアプリのクライアント ID と等しいことを確認します。 - ID トークンの有効期限(
exp
クレーム)を過ぎていないことを確認します。 - リクエストで hd parameter 値を指定した場合は、ID トークンに、Google Cloud 組織に関連付けられた承認済みドメインと一致する
hd
クレームがあることを確認します。
ステップ 2 ~ 5 では、文字列と日付の比較のみが非常に単純であるため、ここでは詳しく説明しません。
最初のステップはより複雑で、暗号による署名チェックが含まれます。デバッグ目的で、Google の tokeninfo
エンドポイントを使用して、サーバーまたはデバイスに実装されたローカル処理と比較できます。ID トークンの値が XYZ123
であるとします。この場合、URI https://oauth2.googleapis.com/tokeninfo?id_token=XYZ123
を逆参照します。トークンの署名が有効な場合、レスポンスは、デコードされた JSON オブジェクト形式の JWT ペイロードになります。
tokeninfo
エンドポイントはデバッグに役立ちますが、本番環境では鍵エンドポイントから Google の公開鍵を取得し、ローカルで検証を行います。jwks_uri
メタデータ値を使用して、ディスカバリ ドキュメントから鍵の URI を取得する必要があります。デバッグ エンドポイントへのリクエストはスロットリングされるか、断続的なエラーが発生する可能性があります。
Google が公開鍵を変更する頻度は低いため、HTTP レスポンスのキャッシュ ディレクティブを使用して公開鍵をキャッシュに保存できます。また、ほとんどの場合、tokeninfo
エンドポイントを使用するよりもはるかに効率的にローカルで検証を実行できます。この検証では、証明書を取得して解析し、署名を確認するための適切な暗号呼び出しを行う必要があります。幸い、これを実現するための十分にデバッグされたライブラリがさまざまな言語で利用できます(jwt.io を参照)。
ユーザー プロフィール情報の取得
ユーザーに関する追加のプロフィール情報を取得するには、アクセス トークン(認証フローでアプリケーションが受け取る)と OpenID Connect 標準を使用します。
OpenID を遵守するには、認証リクエストに
openid profile
スコープ値を含める必要があります。ユーザーのメールアドレスを含める場合は、追加のスコープ値
email
を指定できます。profile
とemail
の両方を指定するには、認証リクエスト URI に次のパラメータを含めます。scope=openid%20profile%20email
- アクセス トークンを Authorization ヘッダーに追加し、userinfo エンドポイントに HTTPS
GET
リクエストを送信します。これは、userinfo_endpoint
メタデータ値を使用してディスカバリ ドキュメントから取得する必要があります。userinfo レスポンスには、OpenID Connect Standard Claims
と、Discovery ドキュメントのclaims_supported
メタデータ値に記載されているユーザーに関する情報が含まれます。ユーザーまたはその組織は特定のフィールドを指定または非表示にすることがあるため、承認されたアクセス スコープのすべてのフィールドの情報を取得できない場合があります。
ディスカバリ ドキュメント
OpenID Connect プロトコルでは、ユーザーの認証や、トークン、ユーザー情報、公開鍵などのリソースのリクエストに複数のエンドポイントを使用する必要があります。
実装を簡素化して柔軟性を高めるために、OpenID Connect では「ディスカバリ ドキュメント」を使用できます。これは、よく知られた場所にある JSON ドキュメントで、Key-Value ペアが含まれ、OpenID Connect プロバイダの構成に関する詳細(認可、トークン、取り消し、userinfo、公開鍵エンドポイントの URI を含む)を提供します。Google の OpenID Connect サービスのディスカバリ ドキュメントは、次の場所から取得できます。
https://accounts.google.com/.well-known/openid-configuration
Google の OpenID Connect サービスを使用するには、ディスカバリ ドキュメントの URI(https://accounts.google.com/.well-known/openid-configuration
)をアプリケーションにハードコードする必要があります。アプリケーションはドキュメントを取得し、レスポンスのキャッシュ ルールを適用して、必要に応じてそこからエンドポイント URI を取得します。たとえば、ユーザーを認証するために、Google に送信される認証リクエストのベース URI として authorization_endpoint
メタデータ値(次の例の https://accounts.google.com/o/oauth2/v2/auth
)をコードで取得します。
以下にそのようなドキュメントの例を示します。フィールド名は OpenID Connect Discovery 1.0 で指定されているものです(意味については、ドキュメントを参照してください)。これらの値は単なる例示を目的としたものであり、変更される可能性があります。ただし、実際の Google Discovery ドキュメントの最新バージョンからコピーされています。
{ "issuer": "https://accounts.google.com", "authorization_endpoint": "https://accounts.google.com/o/oauth2/v2/auth", "device_authorization_endpoint": "https://oauth2.googleapis.com/device/code", "token_endpoint": "https://oauth2.googleapis.com/token", "userinfo_endpoint": "https://openidconnect.googleapis.com/v1/userinfo", "revocation_endpoint": "https://oauth2.googleapis.com/revoke", "jwks_uri": "https://www.googleapis.com/oauth2/v3/certs", "response_types_supported": [ "code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token", "none" ], "subject_types_supported": [ "public" ], "id_token_signing_alg_values_supported": [ "RS256" ], "scopes_supported": [ "openid", "email", "profile" ], "token_endpoint_auth_methods_supported": [ "client_secret_post", "client_secret_basic" ], "claims_supported": [ "aud", "email", "email_verified", "exp", "family_name", "given_name", "iat", "iss", "locale", "name", "picture", "sub" ], "code_challenge_methods_supported": [ "plain", "S256" ] }
ディスカバリ ドキュメントの値をキャッシュに保存することで、HTTP ラウンド トリップを回避できます。標準の HTTP キャッシュ ヘッダーが使用されており、遵守する必要があります。
クライアント ライブラリ
次のクライアント ライブラリを使用すると、一般的なフレームワークと統合することで、OAuth 2.0 の実装が簡単になります。
OpenID Connect のコンプライアンス
Google の OAuth 2.0 認証システムは、OpenID Connect Core 仕様の必須機能をサポートしています。OpenID Connect と連携するように設計されているクライアントは、OpenID リクエスト オブジェクトを除き、このサービスと相互運用できます。