OpenIDコネクト

GoogleのOpenIDConnectエンドポイントはOpenID認定済みです。

GoogleのOAuth2.0 APIは、認証と承認の両方に使用できます。このドキュメントでは、 OpenID Connect仕様に準拠し、 OpenID認定を受けている認証用のOAuth2.0実装について説明します。 OAuth2.0使用したGoogleAPIへのアクセスにあるドキュメントもこのサービスに適用されます。このプロトコルをインタラクティブに探索したい場合は、 Google OAuth 2.0Playgroundをお勧めしますStack Overflowのヘルプを表示するには、質問に「google-oauth」のタグを付けてください。

OAuth2.0のセットアップ

アプリケーションがユーザーログインにGoogleのOAuth2.0認証システムを使用する前に、Google API Consoleでプロジェクトを設定して、OAuth 2.0クレデンシャルを取得し、リダイレクトURIを設定し、(オプションで)ユーザーに表示されるブランド情報をカスタマイズする必要があります-同意画面。 API Consoleを使用して、サービスアカウントの作成、請求の有効化、フィルタリングの設定、およびその他のタスクを実行することもできます。詳細については、 Google API Consoleヘルプを参照してください。

OAuth2.0クレデンシャルを取得する

ユーザーを認証してGoogleのAPIにアクセスするには、クライアントIDとクライアントシークレットを含むOAuth2.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パラメータを使用して、この情報へのアクセスをリクエストします。スコープを使用して、他のGoogleAPIへのアクセスをリクエストすることもできます。

ユーザー同意画面には、製品名、ロゴ、ホームページのURLなどのブランド情報も表示されます。 API Consoleでブランド情報を管理します。

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

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

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

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

サービスへのアクセス

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

ライブラリを使用しないことを選択した場合は、このドキュメントの残りの部分の指示に従ってください。このドキュメントでは、使用可能なライブラリの基礎となるHTTP要求フローについて説明しています。

ユーザーの認証

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

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

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

サーバーフロー

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

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

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

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

状態トークンの適切な選択の1つは、高品質の乱数ジェネレーターを使用して作成された30文字程度の文字列です。もう1つは、バックエンドで秘密にされているキーを使用して、セッション状態変数の一部に署名することによって生成されるハッシュです。

次のコードは、一意のセッショントークンの生成を示しています。

PHP

このサンプルを使用するには、PHP用のGoogleAPIクライアントライブラリをダウンロードする必要があります。

// 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用のGoogleAPIクライアントライブラリをダウンロードする必要があります。

// 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用のGoogleAPIクライアントライブラリをダウンロードする必要があります。

# 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パラメーターを使用してGET要求を作成することです。このプロセスのすべてのステップで、HTTPではなくHTTPSを使用していることに注意してください。 HTTP接続は拒否されます。 authorization_endpointメタデータ値を使用して、 DiscoveryドキュメントからベースURIを取得する必要があります。以下の説明では、ベースURIがhttps://accounts.google.com/o/oauth2/v2/authことを前提としていhttps://accounts.google.com/o/oauth2/v2/auth

基本的なリクエストの場合、次のパラメータを指定します。

  • client_id 、API ConsoleCredentials pageから取得します。
  • response_type 。これは、基本認証コードフロー要求ではcode必要がありcode 。 (詳しくはresponse_typeをご覧ください。)
  • scope 。基本的なリクエストではopenid email必要がopenid email 。 ( scope詳細をお読みください。)
  • redirect_uriは、Googleからの応答を受信するサーバー上のHTTPエンドポイントである必要があります。値は、API ConsoleCredentials pageで構成したOAuth2.0クライアントの許可されたリダイレクトURIの1つと正確に一致する必要があります。この値が許可されたURIと一致しない場合、リクエストはredirect_uri_mismatchエラーで失敗します。
  • stateは、偽造防止の一意のセッショントークンの値と、ユーザーがアプリケーションに戻ったときにコンテキストを回復するために必要なその他の情報(開始URLなど)を含める必要があります。 (詳細については、 stateをご覧ください。)
  • nonceは、アプリによって生成されるランダムな値であり、存在する場合にリプレイ保護を有効にします。
  • login_hintは、ユーザーのメールアドレスまたはsub文字列にすることができます。これは、ユーザーのlogin_hint相当します。 login_hintを指定せず、ユーザーが現在ログインしている場合、同意画面には、ユーザーのメールアドレスをアプリにリリースするための承認リクエストが含まれます。 (詳細については、 login_hintしてlogin_hint 。)
  • hdパラメーターを使用して、特定のGSuiteドメインのユーザー向けにOpenIDConnectフローを最適化します。 (詳細はhdをご覧hd 。)

読みやすくするために改行とスペースを含む完全なOpenIDConnect認証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送信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用のGoogleAPIクライアントライブラリをダウンロードする必要があります。

// 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用のGoogleAPIクライアントライブラリをダウンロードする必要があります。

// 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用のGoogleAPIクライアントライブラリをダウンロードする必要があります。

# 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.アクセストークンとIDトークンのcodeを交換します

応答には、 codeパラメータ、サーバーがアクセストークンとIDトークンと交換できる1回限りの認証コードが含まれます。サーバーは、 POSTリクエストを送信してこの交換を行います。 POSTリクエストはトークンエンドポイントに送信されます。トークンエンドポイントは、 token_endpointメタデータ値を使用してDiscoveryドキュメントから取得する必要があります。以下の説明では、エンドポイントがhttps://oauth2.googleapis.com/tokenことを前提としています。リクエストには、 POST本文に次のパラメータを含める必要があります。

田畑
code最初の要求から返される認証コード。
client_id OAuth 2.0クレデンシャルの取得で説明されているように、API ConsoleCredentials pageから取得するクライアントID。
client_secret OAuth 2.0資格情報の取得で説明されているように、API ConsoleCredentials pageから取得するクライアントシークレット。
redirect_uriリダイレクトURIの設定で説明されているように、API ConsoleCredentials pageで指定された特定のclient_idの許可されたリダイレクト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 GoogleAPIに送信できるトークン。
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トークンの対象となるオーディエンス。これは、アプリケーションのOAuth2.0クライアントIDの1つである必要があります。
exp常にIDトークンを受け入れてはならない有効期限以降。 Unix時間(整数秒)で表されます。
iat常にIDトークンが発行された時刻。 Unix時間(整数秒)で表されます。
iss常に応答の発行者の発行者識別子。 Google IDトークンaccounts.google.com 、常にhttps://accounts.google.comまたはaccounts.google.com
sub常にユーザーの識別子。すべてのGoogleアカウントで一意であり、再利用されることはありません。 Googleアカウントは、異なる時点で複数のメールアドレスを持つことができますが、 sub値は変更されません。アプリケーション内でsubをユーザーの一意の識別子キーとして使用します。大文字と小文字を区別するASCII文字の最大長は255です。
at_hashトークンハッシュにアクセスします。アクセストークンがIDトークンに関連付けられていることの検証を提供します。サーバーフローでaccess_token値を使用してIDトークンが発行された場合、このクレームは常に含まれます。このクレームは、クロスサイトリクエストフォージェリ攻撃から保護するための代替メカニズムとして使用できますが、手順1手順3に従う場合は、アクセストークンを確認する必要はありません。
azp許可されたプレゼンターのclient_id 。この主張は、IDトークンを要求する当事者がIDトークンの対象者と同じでない場合にのみ必要です。これは、ウェブアプリケーションとAndroidアプリが異なるOAuth 2.0 client_id持っているが、同じclient_idプロジェクトを共有しているハイブリッドアプリの場合にGoogleで当てはまる可能性があります。
emailユーザーのメールアドレス。この値はこのユーザーに固有ではない可能性があり、主キーとしての使用には適していません。スコープにemailスコープの値が含まれている場合にのみ提供されます。
email_verifiedユーザーの電子メールアドレスが確認されている場合はTrue。それ以外の場合はfalse。
family_nameユーザーの名前または姓。 name主張が存在する場合に提供される場合があります。
given_nameユーザーの名または名。 name主張が存在する場合に提供される場合があります。
hdユーザーのホストされたGSuiteドメイン。ユーザーがホストされたドメインに属している場合にのみ提供されます。
locale BCP47言語タグで表されるユーザーのロケール。 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.0APIについて詳しく説明します。この情報は、認証と承認に関する高度な要件を持つ開発者を対象としています。

他のGoogleAPIへのアクセス

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

トークンを更新する

APIアクセスのリクエストでは、 code交換中に返される更新トークンをリクエストできます。更新トークンは、ユーザーがアプリケーションに存在しない間、アプリにGoogleAPIへの継続的なアクセスを提供します。更新トークンをリクエストするには、認証リクエストaccess_typeパラメーターをofflineに設定します。

考慮事項:

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

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

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

promptパラメータの詳細については、認証URIパラメータテーブルのpromptを参照してください。

認証URIパラメーター

次の表に、GoogleのOAuth2.0認証APIで受け入れられるパラメーターの詳細を示します。

パラメータ必須説明
client_id (必須) OAuth 2.0クレデンシャルの取得で説明されているように、API ConsoleCredentials pageから取得するクライアントID文字列。
nonce (必須)リプレイ保護を有効にする、アプリによって生成されたランダムな値。
response_type (必須)値がcode場合、基本認証コードフローを起動し、トークンを取得するためにトークンエンドポイントへのPOSTを要求します。値がtoken id_tokenまたはid_token token場合、 暗黙的なフローを起動し、リダイレクトURIでJavaScriptを使用して、 URI #fragment識別子からトークンを取得する#fragmentます
redirect_uri (必須)応答の送信先を決定します。このパラメーターの値は、API Console Credentials pageで設定した許可されたリダイレクト値の1つと正確に一致する必要があります(HTTPまたはHTTPSスキーム、大文字と小文字、および末尾の「/」(存在する場合)を含む)。
scope (必須)

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

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

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

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

使用可能なスコープについては、 GoogleAPIのOAuth2.0スコープまたは使用するGoogleAPIのドキュメントを参照してください。

state (オプションですが、強くお勧めします)

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

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

access_type (オプション)許可される値はofflineonlineです。効果はオフラインアクセスに記載されています。アクセストークンが要求されている場合、 offline値が指定されていない限り、クライアントは更新トークンを受け取りません。
display (オプション)許可サーバーが認証および同意のユーザーインターフェースページを表示する方法を指定するためのASCII文字列値。次の値が指定され、Googleサーバーによって受け入れられますが、その動作には影響しません: pagepopuptouch 、およびwap
hd (オプション)

hd (ホストドメイン)パラメーターは、GSuiteホストアカウントのログインプロセスを合理化します。 G Suiteユーザーのドメイン( mycollege.edu )をmycollege.eduことで、アカウント選択UIをそのドメインのアカウント用に最適化する必要があることを示すことができます。 1つのドメインだけでなく、一般的にG Suiteアカウントを最適化するには、アスタリスク( * )の値を設定します: hd=*

クライアント側のリクエストは変更される可能性があるため、このUI最適化に依存してアプリにアクセスできるユーザーを制御しないでください。必ず検証することを返されたIDトークンを持っているhdあなたが(例えば期待するものと一致することを主張値をmycolledge.edu )。 requestパラメータとは異なり、IDトークンのhdクレームはGoogleのセキュリティトークンに含まれているため、値を信頼できます。

include_granted_scopes (オプション)このパラメーターに値trueが指定され、許可要求が許可されている場合、許可には、他のスコープのこのユーザー/アプリケーションの組み合わせに付与された以前の許可が含まれます。増分認証を参照してください。

インストール済みアプリフローでは増分認証を実行できないことに注意してください。

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

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

  • consent

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

  • select_account

    許可サーバーは、ユーザーにユーザー・アカウントを選択するように促します。これにより、承認サーバーに複数のアカウントを持つユーザーは、現在のセッションを持つ可能性のある複数のアカウントの中から選択できます。

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

IDトークンの検証

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

以下は、IDトークンをサーバーに送信する可能性のある一般的な状況です。

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

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

IDトークンを便利にする1つの点は、アプリのさまざまなコンポーネントにIDトークンを渡すことができるという事実です。これらのコンポーネントは、アプリとユーザーを認証する軽量の認証メカニズムとしてIDトークンを使用できます。ただし、IDトークンの情報を使用したり、ユーザーが認証したことをアサーションとして信頼したりする前に、それを検証する必要あります。

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

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

手順2から5は、文字列と日付の比較のみを含むため、ここでは詳しく説明しません。

最初のステップはより複雑で、暗号署名のチェックが含まれます。デバッグの目的で、Googleのtokeninfoエンドポイントを使用して、サーバーまたはデバイスに実装されているローカル処理と比較できます。 IDトークンの値がXYZ123あるとします。次に、 https://oauth2.googleapis.com/tokeninfo?id_token= XYZ123を逆参照しhttps://oauth2.googleapis.com/tokeninfo?id_token= XYZ123 。トークンの署名が有効な場合、応答はデコードされたJSONオブジェクト形式のJWTペイロードになります。

tokeninfoエンドポイントはデバッグに役立ちますが、 tokeninfoは、キーエンドポイントからGoogleの公開鍵を取得し、ローカルで検証を実行します。 jwks_uriメタデータ値を使用して、検出ドキュメントからキーURIを取得する必要があります。デバッグエンドポイントへの要求は抑制されるか、断続的なエラーが発生する可能性があります。

Googleが公開鍵を変更することはめったにないため、HTTP応答のキャッシュディレクティブを使用して公開鍵をキャッシュでき、ほとんどの場合、 tokeninfoエンドポイントを使用するよりもはるかに効率的にローカル検証を実行tokeninfoます。この検証では、証明書を取得して解析し、適切な暗号化呼び出しを行って署名を確認する必要があります。幸い、これを実現するために、さまざまな言語で利用できる十分にデバッグされたライブラリがあります( jwt.ioを参照)。

ユーザープロファイル情報の取得

ユーザーに関する追加のプロファイル情報を取得するには、アクセストークン(アプリケーションが認証フロー中に受信する)とOpenIDConnect標準を使用できます。

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

    ユーザーの電子メールアドレスを含める場合は、 email追加のスコープ値を指定できます。 profileemail両方を指定するには、認証要求URIに次のパラメーターを含めることができます。

    scope=openid%20profile%20email
  2. アクセストークンを認証ヘッダーに追加し、userinfoエンドポイントにHTTPS GETリクエストを送信します。これは、 userinfo_endpointメタデータ値を使用してDiscoveryドキュメントから取得する必要があります。 userinfo応答には、 OpenID Connect Standard ClaimsおよびDiscoveryドキュメントのclaims_supportedメタデータ値で説明されているように、ユーザーに関する情報が含まれます。ユーザーまたはその組織は、特定のフィールドを提供または保留することを選択する場合があるため、許可されたアクセス範囲のすべてのフィールドの情報を取得できない場合があります。

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

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

実装を簡素化し、柔軟性を高めるために、OpenID Connectでは、「検出ドキュメント」を使用できます。これは、承認のURIなど、OpenIDConnectプロバイダーの構成に関する詳細を提供するキーと値のペアを含む既知の場所にあるJSONドキュメントです。 、トークン、失効、userinfo、および公開鍵エンドポイント。 GoogleのOpenIDConnectサービスの検出ドキュメントは、次の場所から取得できます。

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

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

このようなドキュメントの例を次に示します。フィールド名は、 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"
  ]
}

Discoveryドキュメントの値をキャッシュすることで、HTTPラウンドトリップを回避できる場合があります。標準のHTTPキャッシングヘッダーが使用され、尊重する必要があります。

クライアントライブラリ

次のクライアントライブラリは、一般的なフレームワークと統合することで、OAuth2.0の実装を簡単にします。

OpenIDConnectコンプライアンス

GoogleのOAuth2.0認証システムは、 OpenID ConnectCore仕様の 必要な機能をサポートしています。 OpenID Connectで動作するように設計されたクライアントは、このサービスと相互運用する必要があります( OpenIDリクエストオブジェクトを除く)。