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 認証システムを使用するには、まず でプロジェクトを設定して、OAuth 2.0 認証情報を取得し、リダイレクト URI を設定する必要があります。また、必要に応じて、ユーザーがユーザー同意画面で確認するブランディング情報をカスタマイズすることもできます。 を使用して、サービス アカウントの作成、課金の有効化、フィルタリングの設定などのタスクを行うこともできます。詳しくは、 ヘルプをご覧ください。

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 を設定する

で設定したリダイレクト 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 などのブランディング情報も表示されます。 でブランディング情報を管理します。

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

  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 を使用して生成されたため、 で設定されるブランド情報が含まれていません)。

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

サービスへのアクセス

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

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

ユーザーの認証

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

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

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

サーバーフロー

これらのプロトコルを使用してユーザーを認証できるように、 でアプリをセットアップしてください。ユーザーが 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。これは から取得します。
  • response_type。基本的な認証コードフロー リクエストでは code になります。(詳しくは、response_type をご覧ください)。
  • scope。基本的なリクエストでは openid email にする必要があります。(詳しくは、scope をご覧ください)。
  • redirect_uri は、Google からのレスポンスを受信するサーバー上の HTTP エンドポイントにする必要があります。この値は、 Credentials pageで構成した 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//oauth2.example.com/code&
 state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Fround-lake.dustinice.workers.dev%3A443%2Fhttps%2Foauth2-login-demo.example.com%2FmyHome&
 login_hint=[email protected]&
 nonce=0394852-3190485-2490358&
 hd=example.com

アプリがユーザーに関する新しい情報をリクエストする場合、またはユーザーが以前に承認していないアカウント アクセスをアプリがリクエストする場合は、ユーザーの同意が必要です。

3. 偽造防止状態トークンを確認する

レスポンスは、リクエストで指定した redirect_uri に送信されます。すべてのレスポンスはクエリ文字列で返されます。

https://oauth2.example.com/code?state=security_token%3D138r5719ru3e1%26url%3Dhttps%3A%2F%2Fround-lake.dustinice.workers.dev%3A443%2Fhttps%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 から取得したクライアント ID。OAuth 2.0 認証情報を取得するで説明しています。
client_secret から取得したクライアント シークレット。OAuth 2.0 認証情報を取得するをご覧ください。
redirect_uri で指定された 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": "[email protected]",
  "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 常に ユーザーの ID。すべての Google アカウントに固有で、決して再利用されません。Google アカウントには、異なる時点で複数のメールアドレスを設定できますが、sub 値は変更されません。アプリケーション内で sub をユーザーの一意の ID キーとして使用します。最大 255 文字(大文字と小文字が区別される ASCII 文字)。
at_hash アクセス トークンのハッシュ。アクセス トークンが ID トークンに関連付けられていることを検証します。ID トークンがサーバーフローで access_token 値とともに発行された場合、このクレームは常に含まれます。このクレームは、クロスサイト リクエスト フォージェリ攻撃から保護するための代替メカニズムとして使用できますが、ステップ 1ステップ 3 に従う場合は、アクセス トークンを検証する必要はありません。
azp 承認済みのプレゼンターの client_id。このクレームは、ID トークンをリクエストしている当事者が ID トークンのオーディエンスと同じでない場合にのみ必要になります。これは、Google のハイブリッド アプリで、ウェブ アプリケーションと Android アプリの OAuth 2.0 client_id が異なるものの、同じ Google API プロジェクトを共有するケースが考えられます。
email ユーザーのメールアドレス。リクエストに email スコープを含めた場合にのみ提供されます。このクレームの値はこのアカウントに固有のものではなく、時間の経過とともに変化する可能性があるため、この値をユーザー レコードにリンクするプライマリ ID として使用しないでください。また、email クレームのドメインを使用して Google Workspace または Cloud 組織のユーザーを識別することもできません。代わりに 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 に送信する認証リクエストに必要な他のスコープを含めます。たとえば、認証リクエストにユーザーの年齢層を追加するには、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 APIs プロジェクトに付与されている場合でも、アプリがアクセスのスコープの承認をリクエストするたびに同意画面が表示されます。そのため、prompt=consent は必要な場合にのみ含めてください。

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

認証 URI パラメータ

次の表に、Google の OAuth 2.0 認証 API で受け入れられるパラメータの詳細な説明を示します。

パラメータ 必須 説明
client_id (必須) OAuth 2.0 認証情報を取得するで説明されているように、 から取得するクライアント ID 文字列。
nonce (必須) リプレイ保護を有効にするためにアプリによって生成されるランダムな値。
response_type (必須) 値が code の場合、基本認証コードフローを開始します。トークンを取得するには、トークン エンドポイントに POST が必要です。値が token id_token または id_token token の場合、暗黙的フローを開始します。このフローでは、リダイレクト URI で JavaScript を使用して、URI #fragment 識別子からトークンを取得する必要があります。
redirect_uri (必須) レスポンスの送信先を決定します。このパラメータの値は、 で設定した承認済みリダイレクト値のいずれかと完全に一致する必要があります(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 (省略可ですが、強く推奨します)

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

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

access_type (省略可) 指定できる値は offlineonline です。この効果については、オフライン アクセスで説明しています。アクセス トークンがリクエストされている場合、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 トークンを検証する

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

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

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

ID トークンは機密情報であり、傍受されると悪用される可能性があります。これらのトークンは、HTTPS 経由でのみ送信し、POST データまたはリクエスト ヘッダー内でのみ使用することで、安全に処理する必要があります。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 パラメータの値を指定した場合は、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. アクセス トークンを承認ヘッダーに追加し、HTTPS GET リクエストをユーザー情報エンドポイントに行います。ユーザー情報エンドポイントは、userinfo_endpoint メタデータ値を使用してディスカバリ ドキュメントから取得する必要があります。ユーザー情報のレスポンスには、OpenID Connect Standard Claims とディスカバリ ドキュメントの claims_supported メタデータ値に記述されているとおり、ユーザーに関する情報が含まれます。ユーザーまたはユーザーの組織は、特定の項目に情報を提供したり、しなかったりするため、パートナー様がアクセスを許可されているスコープのすべての項目に対する情報を得られるとは限りません。

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

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

実装を簡素化し、柔軟性を高めるため、OpenID Connect では「ディスカバリ ドキュメント」の使用が認められています。これは、既知の場所にある JSON ドキュメントで、OpenID Connect プロバイダの構成に関する詳細情報(認可、トークン、取り消し、ユーザー情報、公開鍵のエンドポイントの 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 を取得します。たとえば、ユーザーを認証する場合、コードは 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 リクエスト オブジェクトを除く)。