OpenID Connect

Google の OAuth 2.0 API は、認証と認可の両方に使用できます。このドキュメントでは、認証用の OAuth 2.0 実装について説明します。これは OpenID Connect 仕様に準拠しており、OpenID Certified を受けています。OAuth 2.0 を使用して Google API にアクセスするに記載されているドキュメントも、このサービスに適用されます。このプロトコルをインタラクティブに試すには、Google OAuth 2.0 Playground をおすすめします。Stack Overflow でサポートを受けるには、質問に「google-oauth」というタグを付けます。

OAuth 2.0 の設定

アプリケーションでユーザー ログインに Google の OAuth 2.0 認証システムを使用するには、 Google Cloud コンソール でプロジェクトを設定して OAuth 2.0 認証情報を取得し、リダイレクト URI を設定して、ユーザーの同意画面に表示されるブランディング情報をカスタマイズする必要があります(省略可)。Cloud コンソールを使用して、サービス アカウントの作成、課金の有効化、フィルタリングの設定などのタスクを行うこともできます。詳細については、Google Cloud コンソール ヘルプをご覧ください。

OAuth 2.0 認証情報を取得する

ユーザーを認証して Google の API にアクセスするには、クライアント ID やクライアント シークレットなどの OAuth 2.0 認証情報が必要です。

特定の OAuth 2.0 認証情報のクライアント ID とクライアント シークレットを表示するには、[認証情報を選択] をクリックします。表示されたウィンドウで、プロジェクトと目的の認証情報を選択し、[表示] をクリックします。

または、Cloud コンソールの [クライアント] ページでクライアント ID とクライアント シークレットを表示します。

  1. [クライアント] ページに移動します。
  2. クライアントの名前または編集アイコン()をクリックします。クライアント ID とシークレットはページの上部に表示されます。

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

Cloud コンソールで設定したリダイレクト URI によって、Google が認証リクエストへのレスポンスを送信する場所が決まります。

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

  1. [クライアント] ページに移動します。
  2. クライアントをクリックします。
  3. リダイレクト URI を表示または編集します。

[クライアント] ページにクライアントがリストされていない場合、プロジェクトには OAuth 認証情報がありません。作成するには、[クライアントを作成] をクリックします。

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

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

ユーザーの同意画面には、商品名、ロゴ、ホームページの URL などのブランディング情報も表示されます。Cloud コンソールでブランディング情報を管理します。

プロジェクトの同意画面を有効にするには:

  1. Google Cloud コンソールで [ブランディング ページ] を開きます。
  2. プロンプトが表示されたら、プロジェクトのいずれかを選択するか、新しいプロジェクトを作成します。
  3. フォームに記入して [保存] をクリックします。

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

同意ページの例
図 1. 同意ページのスクリーンショット

サービスへのアクセス

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

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

ユーザーの認証

ユーザーの認証には、ID トークンの取得と検証が含まれます。 ID トークンは、インターネット上で ID アサーションを共有するために設計された OpenID Connect の標準機能です。

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

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

サーバーフロー

Cloud コンソールでアプリを設定して、これらのプロトコルを使用し、ユーザーを認証できるようにしてください。ユーザーが Google でログインしようとしたときに、次のことを行う必要があります。

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

1. 偽造防止状態トークンを作成する

リクエスト フォージェリ攻撃を防止して、ユーザーのセキュリティを保護する必要があります。最初のステップは、アプリとユーザーのクライアントの間で状態を保持する一意のセッション トークンを作成することです。後で、この一意のセッション トークンを Google OAuth ログイン サービスから返された認証レスポンスと照合して、リクエストを行っているのがユーザーであり、悪意のある攻撃者ではないことを確認します。これらのトークンは、クロスサイト リクエスト フォージェリ(CSRF)トークンと呼ばれることがよくあります。

状態トークンとして適切な選択肢の 1 つは、高品質の乱数ジェネレータを使用して作成された 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。これは、Cloud コンソールのクライアント ページから取得します。
  • response_type。基本的な認可コードフロー リクエストでは code にする必要があります。(詳しくは、response_type をご覧ください)。
  • scope。基本的なリクエストでは openid email にする必要があります。 (詳しくは scope をご覧ください)。
  • redirect_uri は、Google からのレスポンスを受信するサーバー上の HTTP エンドポイントにする必要があります。この値は、Cloud Console の [認証情報] ページで構成した OAuth 2.0 クライアントの承認済みリダイレクト URI のいずれかと完全に一致する必要があります。この値が承認済みの URI と一致しない場合、リクエストは失敗し、redirect_uri_mismatch エラーが返されます。
  • state には、偽造防止の一意のセッション トークンの値と、ユーザーがアプリケーションに戻ったときにコンテキストを復元するために必要なその他の情報(開始 URL など)を含める必要があります。(詳しくは state をご覧ください)。
  • nonce は、アプリによって生成されるランダムな値です。この値が存在する場合、リプレイ保護が有効になります。
  • login_hint には、ユーザーのメールアドレスまたは sub 文字列(ユーザーの Google ID と同等)を指定できます。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//developers.google.com/oauthplayground&
 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://developers.google.com/oauthplayground?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

RFC 6749 に従って、クライアントは認識されないレスポンス パラメータを無視する必要があります。サーバーで、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 トークンと交換できる 1 回限りの認証コードです。サーバーは、HTTPS POST リクエストを送信してこの交換を行います。POST リクエストはトークン エンドポイントに送信されます。トークン エンドポイントは、token_endpoint メタデータ値を使用してディスカバリ ドキュメントから取得する必要があります。以下の説明では、エンドポイントが https://oauth2.googleapis.com/token であることを前提としています。リクエストの POST 本文には、次のパラメータを含める必要があります。

フィールド
code 最初のリクエストから返される認証コード。
client_id OAuth 2.0 認証情報を取得するで説明されているように、Cloud コンソールのクライアント ページから取得するクライアント ID。
client_secret OAuth 2.0 認証情報を取得するで説明されているように、Cloud コンソールのクライアント ページから取得するクライアント シークレット。
redirect_uri Cloud コンソールのクライアント ページで指定された、特定の 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//developers.google.com/oauthplayground&
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 Web Token)です。つまり、暗号的に署名された Base64 エンコードの JSON オブジェクトです。通常、ID トークンを使用する前に 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 をユーザーの一意の識別子キーとして使用します。最大長は 255 文字(大文字と小文字を区別する ASCII 文字)です。
amr Google アカウントへのログインに使用される認証方法を識別する文字列の JSON 配列。存在する場合、次の [IANA.AMR] 値の 1 つ以上が含まれます。
  • hwk ハードウェア キーが使用された
  • mfa 多要素認証が完了しました
  • pwd パスワードが使用されました
  • sms SMS メッセージが確認に使用された
  • swk: パスキーなどのソフトウェア キーが使用された
  • tel 電話による確認が行われた
amr クレームが認証リクエストに含まれ、設定で有効になっている場合にのみ存在します。
auth_time ユーザー認証が行われた時刻。Unix エポック(1970 年 1 月 1 日 00:00:00 UTC)からの経過秒数を表す JSON 数値。auth_time クレームが認証リクエストに含まれ、設定で有効になっている場合に提供されます。
at_hash アクセス トークンのハッシュ。アクセス トークンが ID トークンに関連付けられていることを検証します。サーバーフローで access_token 値を含む ID トークンが発行された場合、このクレームは常に含まれます。このクレームは、クロスサイト リクエスト フォージェリ攻撃から保護するための代替メカニズムとして使用できますが、ステップ 1 とステップ 3 を実行する場合は、アクセス トークンを検証する必要はありません。
azp 承認されたプレゼンターの client_id。このクレームは、ID トークンをリクエストするパーティが ID トークンのオーディエンスと異なる場合にのみ必要です。Google では、ウェブ アプリケーションと Android アプリが異なる OAuth 2.0 client_id を持ち、同じ Google API プロジェクトを共有するハイブリッド アプリの場合に、この状況が発生することがあります。
email ユーザーのメールアドレスです。リクエストに email スコープを含めた場合にのみ提供されます。このクレームの値は、このアカウントに固有のものではなく、時間の経過とともに変化する可能性があるため、ユーザー レコードにリンクするプライマリ ID としてこの値を使用しないでください。また、email クレームのドメインを使用して Google Workspace または Google 組織のユーザーを識別することはできません。代わりに 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 のユーザー プロフィール エンドポイントで追加のユーザー プロフィール情報を取得できます。

高度なトピック

以降のセクションでは、Google OAuth 2.0 API について詳しく説明します。この情報は、認証と認可に関する高度な要件を持つデベロッパーを対象としています。

他の Google API へのアクセス

認証に OAuth 2.0 を使用する利点の 1 つは、ユーザーの認証と同時に、ユーザーに代わって他の Google API(YouTube、Google ドライブ、カレンダー、連絡先など)を使用する権限をアプリケーションが取得できることです。これを行うには、Google に送信する認証リクエストに、必要な他のスコープを含めます。たとえば、ユーザーの年齢層を認証リクエストに追加するには、openid email https://www.googleapis.com/auth/profile.agerange.read のスコープ パラメータを渡します。同意画面で、ユーザーに適切なプロンプトが表示されます。Google から返されるアクセス トークンを使用すると、アプリケーションは、リクエストして付与されたアクセス スコープに関連するすべての API にアクセスできます。

更新トークン

API アクセスのリクエストでは、code の交換中に更新トークンが返されるようにリクエストできます。更新トークンを使用すると、ユーザーがアプリケーションにログインしていないときでも、アプリは Google API に継続的にアクセスできます。更新トークンをリクエストするには、認証リクエストで access_type パラメータを offline に設定します。

考慮事項:

  • 更新トークンは、コード交換フローを初めて実行するときにのみ取得できるため、安全かつ永続的に保存してください。
  • 発行される更新トークンの数には上限があります。クライアントとユーザーの組み合わせごとに 1 つの上限があり、すべてのクライアントのユーザーごとに別の上限があります。アプリケーションがリクエストする更新トークンが多すぎると、この上限に達する可能性があります。その場合、古い更新トークンは機能しなくなります。

詳細については、アクセス トークンの更新(オフライン アクセス)をご覧ください。

認証リクエストで prompt パラメータを consent に設定することで、アプリの再承認をユーザーに求めることができます。prompt=consent が含まれている場合、以前にすべてのスコープが Google API プロジェクトに付与されていても、アプリがアクセス スコープの認可をリクエストするたびに同意画面が表示されます。このため、prompt=consent は必要な場合にのみ含めてください。

prompt パラメータの詳細については、認証 URI パラメータの表の prompt をご覧ください。

認証 URI パラメータ

次の表に、Google の OAuth 2.0 認証 API で使用できるパラメータの詳細を示します。

パラメータ 必須 説明
client_id (必須) OAuth 2.0 認証情報を取得するで説明されているように、Cloud コンソールのクライアント ページから取得するクライアント ID 文字列。
nonce (必須) リプレイ保護を有効にする、アプリによって生成されたランダムな値。
response_type (必須) 値が code の場合、基本的な認可コードフローが開始され、トークンを取得するためにトークン エンドポイントへの POST が必要になります。値が token id_token または id_token token の場合、暗黙的フローが開始されます。この場合、リダイレクト URI で JavaScript を使用して、URI #fragment 識別子からトークンを取得する必要があります。
redirect_uri (必須) レスポンスの送信先を決定します。このパラメータの値は、Cloud コンソールのクライアント ページで設定した承認済みのリダイレクト値のいずれかと完全に一致する必要があります(HTTP または HTTPS スキーム、大文字と小文字、末尾の「/」がある場合はそれも含みます)。
scope (必須)

scope パラメータは、openid 値で始まり、profile 値、email 値、またはその両方を含む必要があります。

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

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

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

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

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

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

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

access_type (省略可) 指定できる値は offline と online です。この効果については、オフライン アクセスをご覧ください。アクセス トークンがリクエストされている場合、offline の値が指定されていない限り、クライアントは更新トークンを受け取りません。
claims (省略可) claims パラメータは、userinfo エンドポイントまたは認証リクエスト ID トークン レスポンス タイプに含める 1 つ以上のオプション フィールドを指定するために使用されます。値は、レスポンス タイプとリクエストされたクレームを含む JSON オブジェクトです。Google サーバーは、次のクレーム リクエストを受け入れます。
申請リクエスト
amr ユーザーが最後に認証されたときに使用された方法をリクエストします。amr を ID トークン レスポンスのフィールドとして返すには、claims リクエスト パラメータ claims={"id_token":{"amr":{"essential":true}}} を含めます。設定で有効にする必要があります。
auth_time ユーザーが最後に認証された時刻をリクエストします。auth_time を ID トークン レスポンスのフィールドとして返すには、claims リクエスト パラメータ claims={"id_token":{"auth_time":{"essential":true}}} を含めます。設定で有効にする必要があります。
display (省略可) 認可サーバーが認証と同意のユーザー インターフェース ページを表示する方法を指定する ASCII 文字列値。次の値は指定され、Google サーバーによって受け入れられますが、プロトコルフローの動作には影響しません。page、popup、touch、wap。
hd (省略可)

Google Cloud 組織が所有するアカウントのログイン プロセスを効率化します。Google Cloud 組織のドメイン(mycollege.edu など)を含めることで、アカウント選択 UI をそのドメインのアカウント用に最適化する必要があることを示すことができます。1 つの Google Cloud 組織ドメインだけでなく、Google Cloud 組織アカウント全般を最適化するには、アスタリスク(*)の値(hd=*)を設定します。

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

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

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

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

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

  • consent

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

  • select_account

    認可サーバーは、ユーザー アカウントを選択するようユーザーに求めます。これにより、認可サーバーに複数のアカウントを持つユーザーは、現在のセッションで使用できる複数のアカウントから選択できます。

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

hl (省略可) ログイン、Account Chooser、同意画面の表示言語を指定するために使用される BCP 47 言語タグ。このパラメータを指定しない場合、言語はデフォルトでユーザーの Google アカウントまたはブラウザの設定になります。たとえば、イギリス英語の UI をリクエストするには、パラメータを en-GB に設定します。

ID トークンの検証

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

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

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

ID トークンは機密性が高く、傍受されると不正使用される可能性があります。これらのトークンは、HTTPS 経由でのみ、POST データを使用するかリクエスト ヘッダー内で送信することで、安全に処理されるようにする必要があります。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 パラメータ値を指定した場合は、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 を指定することができます。profile と email の両方を指定したい場合は、以下のパラメータを認証リクエスト URI に含めることができます。

    scope=openid%20profile%20email
  2. アクセス トークンを承認ヘッダーに追加し、HTTPS GET リクエストをユーザー情報エンドポイントに行います。ユーザー情報エンドポイントは、userinfo_endpoint メタデータ値を使用してディスカバリ ドキュメントから取得する必要があります。ユーザー情報の回答にはユーザーに関する情報が含まれます。この情報は、OpenID Connect Standard Claims とディスカバリ ドキュメントのメタデータ値 claims_supported に記述されているとおりです。ユーザーまたはユーザーの組織は、特定の項目に情報を提供したり、しなかったりするため、パートナー様がアクセスを許可されているスコープのすべての項目に対する情報を得られるとは限りません。

ディスカバリ ドキュメント

OpenID Connect プロトコルでは、ユーザーの認証、およびトークン、ユーザー情報、公開鍵などのリソースのリクエストに複数のエンドポイントを使用する必要があります。

実装を簡素化し、柔軟性を高めるために、OpenID Connect では「ディスカバリ ドキュメント」を使用できます。これは、OpenID Connect プロバイダの構成に関する詳細(認可、トークン、取り消し、ユーザー情報、公開鍵のエンドポイントの URI など)を提供する Key-Value ペアを含む、既知の場所にある JSON ドキュメントです。Google の OpenID Connect サービスのディスカバリ ドキュメントは、次の場所から取得できます。

https://accounts.google.com/.well-known/openid-configuration

Google の OpenID Connect サービスを使用するには、ディスカバリ ドキュメントの URI(https://accounts.google.com/.well-known/openid-configuration)をアプリケーションにハードコードする必要があります。アプリケーションはドキュメントを取得し、レスポンスにキャッシュ保存ルールを適用して、必要に応じてエンドポイント URI を取得します。たとえば、ユーザーを認証する場合、コードは authorization_endpoint メタデータ値(以下の例では https://accounts.google.com/o/oauth2/v2/auth)を、Google に送信される認証リクエストのベース URI として取得します。

このようなドキュメントの例を次に示します。フィールド名は、OpenID Connect Discovery 1.0 で指定されているものです(意味については、そのドキュメントをご覧ください)。値は純粋に説明用であり、変更される可能性がありますが、実際の Google ディスカバリ ドキュメントの最新バージョンからコピーされています。

{
  "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 リクエスト オブジェクトを除く)。