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 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 により、Google が認証リクエストにレスポンスを送信する場所が決まります。

特定の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で管理します。

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

  1. Consent Screen pageでGoogle API Consoleます。
  2. If prompted, select a project, or create a new one.
  3. フォームに入力して[ 保存 ]をクリックします

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

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

サービスへのアクセス

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

ライブラリを使用しない場合は、このドキュメントの後半で説明する手順を進めてください。ここでは、使用可能なライブラリの基盤となる HTTP リクエスト フローについて説明します。

ユーザーの認証

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

ユーザーの認証と 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 ConsoleCredentials pageから取得します。
  • response_type。基本認証コードフローのリクエストでは、code にする必要があります。(詳しくは response_type をご覧ください)。
  • scope。基本リクエストでは openid email にする必要があります。(詳しくは scope をご覧ください)。
  • redirect_uri は、Google からのレスポンスを受信する、サーバーの HTTP エンドポイントです。この値は、 API ConsoleCredentials pageで構成した OAuth 2.0 クライアントの承認済みのリダイレクト URI のいずれかと完全に一致する必要があります。この値が承認済みの URI と一致しない場合、リクエストは redirect_uri_mismatch エラーで失敗します。
  • state には、偽造防止を行わない一意のセッション トークンの値と、ユーザーがアプリケーションに戻ったときにコンテキストの復元に必要なその他の情報(開始 URL など)を含めます。 (詳しくは state をご覧ください)。
  • nonce は、アプリによって生成されたランダムな値です。存在する場合、リプレイ保護を有効にします。
  • login_hint には、ユーザーのメールアドレスまたは sub 文字列(ユーザーの Google ID と同等)を指定できます。login_hint を指定しておらず、ユーザーが現在ログインしている場合、同意画面にはユーザーのメールアドレスをアプリにリリースするための承認リクエストが表示されます(詳しくは、login_hint をご覧ください)。
  • hd パラメータを使用して、Google 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 トークンと交換できる 1 回限りの認証コードです。サーバーはこの交換を行うために、HTTPS POST リクエストを送信します。POST リクエストはトークン エンドポイントに送信されます。トークン エンドポイントは、token_endpoint メタデータ値を使用してディスカバリ ドキュメントから取得する必要があります。以下の説明では、エンドポイントが https://oauth2.googleapis.com/token であることを前提としています。リクエストの POST 本文には、次のパラメータを含める必要があります。

フィールド
code 最初のリクエストから返される認証コード。
client_id API ConsoleCredentials pageから取得したクライアント ID。OAuth 2.0 の認証情報を取得するをご覧ください。
client_secret API ConsoleCredentials pageから取得したクライアント シークレット(OAuth 2.0 認証情報の取得を参照)。
redirect_uri API ConsoleCredentials 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 Web Token)です。つまり、暗号的に署名された 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 アカウントで固有の、再利用されないユーザーの ID。Google アカウントには、それぞれ異なる時点で複数のメールアドレスを設定できますが、sub 値は変更されません。アプリケーション内で、ユーザーの一意の ID キーとして sub を使用します。大文字と小文字を区別する 255 文字の ASCII 文字の最大長。
at_hash アクセス トークンのハッシュ。アクセス トークンが ID トークンに関連付けられていることを検証します。サーバーフローで access_token トークンを使用して ID トークンを発行する場合、このクレームは常に含まれます。このクレームは、クロスサイト リクエスト フォージェリ攻撃から保護するための代替メカニズムとして使用できますが、ステップ 1ステップ 3 の手順では、アクセス トークンを検証する必要はありません。
azp 承認されたプレゼンターの client_id。このクレームは、ID トークンをリクエストする当事者が ID トークンのオーディエンスと同じでない場合にのみ必要です。Google では、ウェブ アプリケーションと Android アプリの OAuth 2.0 client_id は同じでも、同じ Google API プロジェクトを共有しています。
email ユーザーのメールアドレス。この値はこのユーザーに固有ではなく、主キーとしての使用には適していません。スコープに email スコープ値が含まれている場合にのみ指定されます。
email_verified ユーザーのメールアドレスが確認済みの場合は true、そうでない場合は false です。
family_name ユーザーの姓(名)。name クレームが存在する場合に指定される場合もあります。
given_name ユーザーの氏名です。name クレームが存在する場合に指定される場合もあります。
hd ユーザーの Google Cloud 組織に関連付けられているドメイン。ユーザーが Google Cloud 組織に属している場合にのみ提供されます。
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 を使用するメリットの一つは、ユーザーの認証と同時に、アプリケーションが他の 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 つの上限と、すべてのクライアントにわたるユーザーごとに 1 つの上限があります。アプリケーションがリクエストする更新トークンが多すぎると、これらの制限に達する可能性があり、古い更新トークンが動作しなくなります。

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

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

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

認証 URI パラメータ

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

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

スコープ パラメータは openid 値で始まり、profile 値か email 値、またはその両方を含める必要があります。

profile スコープ値が存在する場合、ID トークンにユーザーのデフォルトの profile クレームが含まれる場合があります(必ずしも保証されているわけではありません)。

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

これらの OpenID 固有のスコープに加えて、scope 引数には他のスコープ値を含めることもできます。すべてのスコープ値はスペースで区切る必要があります。たとえば、ファイルごとにユーザーの 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 変数でランダムな文字列を生成したり、クライアント状態(Cookie など)のハッシュをエンコードしたりする場合は、レスポンスを検証することで、リクエストとレスポンスが同じブラウザで発生したものであることをさらに確認できます。これにより、クロスサイト リクエスト フォージェリなどの攻撃を防ぐことができます。

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

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

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

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

なお、インストール済みアプリのフローでは、段階的な認可を行うことはできません。

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

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

  • consent

    承認サーバーは、情報をクライアントに返す前にユーザーに同意を求めるプロンプトを表示します。

  • select_account

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

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

ID トークンの検証

Google から直接取得した ID トークンでない限り、サーバー上のすべての ID トークンを検証する必要があります。たとえば、サーバーは、クライアント アプリから受信するすべての ID トークンを検証する必要があります。

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

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

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

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

ID トークンを検証するには、いくつかのステップが必要です。

  1. カード発行会社によって ID トークンが適切に署名されていることを確認します。Google が発行するトークンは、Discovery ドキュメントjwks_uri メタデータ値で指定された URI で見つかった証明書を使用して署名されます。
  2. ID トークン内の iss クレームの値が https://accounts.google.com または accounts.google.com と等しいことを確認します。
  3. ID トークン内の aud クレームの値が、アプリのクライアント ID と一致していることを確認します。
  4. ID トークンの有効期限(exp クレーム)が過ぎていないことを確認します。
  5. リクエストで hd パラメータの値を指定した場合は、Google Cloud 組織に関連付けられた承認済みドメインと一致する hd クレームが ID トークンにあることを確認します。

ステップ 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. 認証ヘッダーにアクセス トークンを追加し、userinfo_endpoint メタデータ値を使用して Discovery ドキュメントから取得する必要がある userinfo エンドポイントに HTTPS GET リクエストを行います。userinfo のレスポンスには、ユーザーに関する情報が含まれます。この情報は、OpenID Connect Standard Claims とディスカバリ ドキュメントの claims_supported メタデータ値に記述されています。ユーザーまたはユーザーの組織は、特定の項目に情報を提供したり、しなかったりするため、承認済みのアクセス スコープのすべての項目に対する情報を得られるとは限りません。

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

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

OpenID Connect を使用すると、実装を簡素化し、柔軟性を向上させることができます。「ディスカバリ ドキュメント」を使用できます。これは、認証、トークン、取り消し、userinfo、公開鍵のエンドポイントなど、OpenID Connect プロバイダの構成に関する詳細を提供する既知の場所にある JSON ドキュメントです。Google の OpenID Connect サービスのディスカバリ ドキュメントは、次の場所から取得できます。

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

Google の OpenID Connect サービスを使用するには、Discovery ドキュメント 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 Request Object を除いて)このサービスを相互運用する必要があります。