OpenID Connect

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 。

  1. Go to the Credentials page.
  2. 資格情報の名前または鉛筆( )アイコンをクリックします。クライアントIDとシークレットはページの上部にあります。

リダイレクト URI を設定する

API Console で設定したリダイレクト URI によって、認証リクエストに対するレスポンスの送信先が決まります。

特定のOAuth 2.0認証情報のリダイレクトURIを作成、表示、または編集するには、次の手順を実行します。

  1. Go to the Credentials page.
  2. ページのOAuth 2.0クライアントIDセクションで、認証情報をクリックします。
  3. リダイレクトURIを表示または編集します。

[認証情報]ページにOAuth 2.0クライアントIDセクションがない場合、プロジェクトにはOAuth認証情報がありません。 アカウントを作成するには、[ 認証情報を作成]をクリックします

ユーザーの同意画面をカスタマイズする

OAuth 2.0 認証には、ユーザーが開示する情報と適用される規約を説明する同意画面が用意されています。たとえば、ユーザーがログインしたときに、メールアドレスと基本的なアカウント情報へのアクセス権をアプリに付与するように求められることがあります。この情報へのアクセスをリクエストするには、scope パラメータを使用します。このパラメータは、アプリの認証リクエストに含めます。スコープを使用して、他の Google API へのアクセス権をリクエストすることもできます。

ユーザーの同意画面には、プロダクト名、ロゴ、ホームページ URL などのブランド情報も表示されます。ブランディング情報は API Consoleで制御します。

To enable your project's consent screen:

  1. Open the Consent Screen page in the Google API Console.
  2. If prompted, select a project, or create a new one.
  3. Fill out the form and click Save.

次の同意ダイアログは、リクエストに OAuth 2.0 と Google ドライブのスコープの組み合わせが含まれている場合にユーザーに表示される内容を示しています。(この汎用ダイアログは Google OAuth 2.0 Playground を使用して生成されたため、 API Consoleで設定されるブランド情報は含まれていません)。

同意ページのスクリーンショット

サービスへのアクセス

Google とサードパーティは、ユーザーの認証や Google API へのアクセスの取得など、実装の詳細の多くを処理するために使用できるライブラリを提供しています。たとえば、Google Identity ServicesGoogle クライアント ライブラリなど、さまざまなプラットフォームで利用できます。

ライブラリを使用しない場合は、このドキュメントの残りの部分の手順に沿って操作してください。このドキュメントでは、使用可能なライブラリの基礎となる HTTP リクエスト フローについて説明しています。

ユーザーの認証

ユーザーの認証には、ID トークンを取得して検証します。ID トークンOpenID Connect の標準化された機能で、インターネット上で ID アサーションを共有する目的で使用するように設計されています。

ユーザーの認証と ID トークンの取得に最も一般的に使用されるアプローチは、「サーバー」フローと「暗黙的」フローと呼ばれます。サーバーフローでは、アプリケーションのバックエンド サーバーがブラウザまたはモバイル デバイスを使用して本人確認を行うことができます。暗黙的フローは、クライアント側アプリケーション(通常はブラウザで実行されている JavaScript アプリ)が、バックエンド サーバー経由ではなく、直接 API にアクセスする必要がある場合に使用されます。

このドキュメントでは、ユーザーを認証するためのサーバーフローの実行方法について説明します。暗黙的フローは、クライアント側でトークンを処理して使用する際のセキュリティ リスクがあるため、非常に複雑です。暗黙的フローを実装する必要がある場合は、Google Identity Services を使用することを強くおすすめします。

サーバーフロー

API Console内でアプリをセットアップして、これらのプロトコルを使用してユーザーを認証できるようにします。ユーザーが Google でログインしようとすると、管理者は次のことを行う必要があります。

  1. 偽造防止状態トークンを作成する
  2. Google に認証リクエストを送信する
  3. 偽造防止状態トークンを確認する
  4. code をアクセス トークンと ID トークンを交換する
  5. ID トークンからユーザー情報を取得する
  6. お客様を認証する

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 (省略可)

このフィールドは、認証リクエストaccess_type パラメータが offline に設定されている場合にのみ表示されます。詳しくは、更新トークンをご覧ください。

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 表示可能な形式でのユーザーの氏名。次の場合に提供される可能性があります。
  • リクエスト スコープに文字列「profile」が含まれています
  • ID トークンはトークンの更新から返されます

name クレームが存在する場合は、それを使用してアプリのユーザー レコードを更新できます。このクレームが必ず存在するとは限りません。

nonce 認証リクエストでアプリによって提供される nonce の値。この攻撃は 1 回だけ提示して、リプレイ攻撃から保護する必要があります。
picture ユーザーのプロフィール写真の URL。次の場合に提供される可能性があります。
  • リクエスト スコープに文字列「profile」が含まれています
  • ID トークンはトークンの更新から返されます

picture クレームが存在する場合は、それを使用してアプリのユーザー レコードを更新できます。このクレームが必ず存在するとは限りません。

profile ユーザーのプロフィール ページの URL。次の場合に提供される可能性があります。
  • リクエスト スコープに文字列「profile」が含まれています
  • ID トークンはトークンの更新から返されます

profile クレームが存在する場合は、それを使用してアプリのユーザー レコードを更新できます。このクレームが必ず存在するとは限りません。

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 値で始めて、profile 値、email 値、またはその両方を含める必要があります。

profile スコープ値が存在する場合、ID トークンにユーザーのデフォルトの profile クレームが含まれる場合があります(ただし、保証されるとは限りません)。

email スコープ値が存在する場合、ID トークンには email クレームと email_verified クレームが含まれます。

これらの OpenID 固有のスコープに加えて、スコープ引数には他のスコープ値を含めることもできます。スコープの値はすべてスペースで区切ります。たとえば、ユーザーの Google ドライブにファイルごとにアクセスする必要がある場合は、scope パラメータに openid profile email https://www.googleapis.com/auth/drive.file を指定できます。

使用可能なスコープについては、Google API の OAuth 2.0 スコープまたは使用する Google API のドキュメントをご覧ください。

state (省略可、ただし強く推奨)

プロトコルでラウンドトリップされる不透明な文字列。つまり、Basic フローでは URI パラメータとして返され、暗黙的フローでは URI #fragment 識別子として返されます。

state は、リクエストとレスポンスを関連付けるのに役立ちます。redirect_uri は推測可能なため、state 値を使用すると、受信接続がアプリによって開始された認証リクエストの結果であるという保証が向上します。この state 変数でランダムな文字列を生成するか、いくつかのクライアント状態のハッシュ(Cookie など)をエンコードすると、レスポンスを検証して、リクエストとレスポンスが同じブラウザから送信されたことも確認できます。これにより、クロスサイト リクエスト フォージェリなどの攻撃から保護できます。

access_type (省略可) 指定できる値は offlineonline です。効果については、オフライン アクセスに記載されています。アクセス トークンがリクエストされている場合、offline の値が指定されていない限り、クライアントは更新トークンを受信しません。
display (省略可) 認証サーバーによる認証と同意のユーザー インターフェース ページの表示方法を指定するための ASCII 文字列値。pagepopuptouchwap の値は、指定されて Google のサーバーで受け入れられますが、その動作には影響しません。
hd (省略可)

Google Cloud 組織が所有するアカウントのログイン プロセスを合理化します。Google Cloud 組織ドメイン(mycollege.edu など)を含めると、アカウント選択 UI がそのドメインのアカウント向けに最適化されるように示すことができます。1 つの Google Cloud 組織ドメインだけではなく、通常 Google Cloud 組織アカウント向けに最適化するには、アスタリスク(*)の値(hd=*)を設定します。

クライアントサイドのリクエストは変更される可能性があるため、アプリにアクセスできるユーザーを制御するために、この UI の最適化に依存しないでください。返された ID トークンhd クレーム値が想定どおりであること(mycolledge.edu など)を必ずvalidateしてください。リクエスト パラメータとは異なり、ID トークンの hd クレームは Google からのセキュリティ トークンに含まれているため、値が信頼できるものとなります。

include_granted_scopes (省略可) このパラメータに値 true を指定し、承認リクエストが許可されている場合、承認には、他のスコープでこのユーザー/アプリケーションの組み合わせに付与されていた以前の承認が含まれます。段階的な承認をご覧ください。

インストール済みアプリのフローでは、増分承認を行うことはできません。

login_hint (省略可) 認証しようとしているユーザーをアプリが認識している場合、認証サーバーへのヒントとしてこのパラメータを指定できます。このヒントを渡すと、Account Chooser が抑制され、ログイン フォームにメールボックスが事前入力されるか、適切なセッション(ユーザーがマルチログインを使用している場合)が選択されます。これにより、アプリで誤ったユーザー アカウントにログインした場合に発生する問題を回避できます。 値には、メールアドレス、またはユーザーの Google ID に相当する sub 文字列を指定できます。
prompt (省略可) 認可サーバーがユーザーに再認証と同意を求めるかどうかを指定する文字列値のスペース区切りリスト。可能な値は次のとおりです。
  • none

    認証サーバーには、認証画面やユーザーの同意画面は表示されません。ユーザーがまだ認証されておらず、リクエストされたスコープに同意が事前設定されていない場合は、エラーが返されます。none を使用すると、既存の認証や同意を確認できます。

  • consent

    認可サーバーはクライアントに情報を返す前に、ユーザーに同意を求めます。

  • select_account

    認可サーバーが、ユーザー アカウントの選択を求めるプロンプトを表示します。これにより、認可サーバーで複数のアカウントを持っているユーザーは、現在のセッションがある可能性のある複数のアカウントから選択できるようになります。

値が指定されず、ユーザーが以前にアクセスを承認したことがない場合は、同意画面が表示されます。

ID トークンの検証

ID トークンが Google から直接取得されたものであることがわかっている場合を除き、サーバーですべての ID トークンを検証する必要があります。たとえば、サーバーはクライアント アプリから受け取るすべての ID トークンを本物として検証する必要があります。

ID トークンをサーバーに送信する一般的な状況は次のとおりです。

  • 認証が必要なリクエストとともに ID トークンを送信する。ID トークンは、リクエストを行った特定のユーザーと、その ID トークンが付与されたクライアントを示します。

ID トークンは機密性が高いため、傍受されると悪用される可能性があります。これらのトークンは、HTTPS 経由でのみ、POST データまたはリクエスト ヘッダー内でのみ送信することで、安全に処理する必要があります。ID トークンをサーバーに保存する場合は、ID トークンも安全に保管する必要があります。

ID トークンは、アプリのさまざまなコンポーネントに渡せる点で有用です。これらのコンポーネントは、アプリとユーザーを認証するための軽量な認証メカニズムとして ID トークンを使用できます。ただし、ID トークン内の情報を使用したり、ユーザーが認証されたことを示すアサーションとして ID トークンを使用したりする前に、検証する必要があります

ID トークンの検証には、いくつかの手順が必要です。

  1. ID トークンが発行元によって適切に署名されていることを確認します。Google が発行するトークンは、ディスカバリ ドキュメントjwks_uri メタデータ値で指定された URI にある証明書のいずれかを使用して署名されます。
  2. ID トークンの iss クレームの値が https://accounts.google.com または accounts.google.com と等しいことを確認します。
  3. ID トークンの aud クレームの値がアプリのクライアント ID と等しいことを確認します。
  4. ID トークンの有効期限(exp クレーム)を過ぎていないことを確認します。
  5. リクエストで 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 標準を使用します。

  1. OpenID を遵守するには、認証リクエストopenid profile スコープ値を含める必要があります。

    ユーザーのメールアドレスを含める場合は、追加のスコープ値 email を指定できます。profileemail の両方を指定するには、認証リクエスト URI に次のパラメータを含めます。

    scope=openid%20profile%20email
  2. アクセス トークンを 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 リクエスト オブジェクトを除き、このサービスと相互運用できます。