OAuth と Google でログインによるリンクの簡素化

概要

OAuth ベースの Google でログインの簡素化されたリンクでは、 OAuth リンクの上層に Google でログインを追加します。これにより、Google ユーザーはシームレスにリンクできるようになり、アカウント作成も可能になります。ユーザーは自分の Google アカウントを使用して、サービスで新しいアカウントを作成できます。

OAuth と Google でログインを使用してアカウント リンクを行うには、次の一般的な手順に従います。

  1. まず、ユーザーの Google プロフィールにアクセスすることについてユーザーに同意を求めます。
  2. プロフィール内の情報を使用して、ユーザー アカウントが存在するかどうかを確認します。
  3. 既存のユーザーの場合は、アカウントをリンクします。
  4. 認証システムで Google ユーザーの一致が見つからない場合は、Google から受信した ID トークンを検証します。その後、ID トークンに含まれているプロフィール情報に基づいてユーザー アカウントを作成できます。
この図は、ユーザーが簡素化されたリンクフローを使用して Google アカウントをリンクする手順を示しています。最初のスクリーンショットは、ユーザーがリンクするアプリをどのように選択できるかを示します。2 つ目のスクリーンショットでは、ユーザーがサービスに既存のアカウントがあるかどうかを確認できます。3 番目のスクリーンショットでは、リンクする Google アカウントを選択できます。4 番目のスクリーンショットは、ユーザーの Google アカウントをアプリにリンクするための確認画面を示します。5 番目のスクリーンショットは、Google アプリでユーザー アカウントが正常にリンクされたことを示します。
ユーザーのスマートフォンでの簡素化されたリンクによるアカウント リンク

図 1 。ユーザーのスマートフォンでの簡素化されたリンクによるアカウント リンク

簡素化されたリンク: OAuth + Google でログインのフロー

次のシーケンス図は、簡素化されたリンクにおけるユーザー、Google、トークン交換エンドポイント間のインタラクションの詳細を示しています。

ユーザー Google アプリ / サーバー トークン 交換エンドポイント API 1. ユーザーがリンクを開始 2. Google でログインをリクエスト 3. Google ログイン 4\. インテントを確認(JWT アサーション) 5\. account_found: true/false アカウントが見つかった場合: 6\. インテントを取得 アカウントがない場合: 6\. インテントを作成 7\. access_token, refresh_token 8\.ユーザー トークンを保存 9. ユーザー リソースにアクセス
図 2.簡素化されたリンクフローのイベントの順序。

役割と責任

次の表に、簡素化されたリンクフローにおけるアクターの役割と責任を示します。

アクター / コンポーネント GAL ロール 責任
Google アプリ / サーバー OAuth クライアント Google でログインのユーザーの同意を取得し、ID アサーション(JWT)をサーバーに渡し、結果のトークンを安全に保存します。
トークン交換エンドポイント アイデンティティ プロバイダ / 認可サーバー ID アサーションを検証し、既存のアカウントを確認し、 アカウント リンク インテント(checkgetcreate)を処理し、リクエストされた インテントに基づいてトークンを発行します。
サービス API リソース サーバー 有効なアクセス トークンが提示されたときに、ユーザーデータへのアクセスを提供します。

簡素化されたリンクの要件

  • 基本的な OAuth リンクフローを実装します。サービスは、OAuth 2.0 準拠の認可エンドポイントとトークン交換エンドポイントをサポートする必要があります。
  • トークン交換エンドポイントは、JSON ウェブトークン(JWT)アサーションをサポートし、checkcreategetインテントを実装する必要があります。

OAuth サーバーを実装する

トークン交換エンドポイントは、checkcreateget インテントをサポートする必要があります。 アカウント リンクフローを完了し、さまざまなインテントが使用されるタイミングを確認するには、次の手順を行います。

  1. ユーザーは認証システムにアカウントを持っていますか?(ユーザーが [はい] または [いいえ] を選択して決定)
    1. [はい]: ユーザーは Google アカウントに関連付けられたメールアドレスを使用してプラットフォームにログインしますか?(ユーザーが [はい] または [いいえ] を選択して決定)
      1. [はい]: ユーザーは認証システムに一致するアカウントを持っていますか?(check intent が呼び出されて確認されます)
        1. [はい]: get intent が呼び出され、get intent が正常に返された場合はアカウントがリンクされます。
        2. [いいえ]: 新しいアカウントを作成しますか?(ユーザーが [はい] または [いいえ] を選択して決定)
          1. [はい]: create intent が呼び出され、create intent が正常に返された場合はアカウントがリンクされます。
          2. [いいえ]: OAuth リンクフローがトリガーされ、ユーザーはブラウザにリダイレクトされ、別のメールアドレスでリンクするオプションが表示されます。
      2. [いいえ]: OAuth リンクフローがトリガーされ、ユーザーはブラウザにリダイレクトされ、別のメールアドレスでリンクするオプションが表示されます。
    2. [いいえ]: ユーザーは認証システムに一致するアカウントを持っていますか?(check intent が呼び出されて確認されます)
      1. [はい]: get intent が呼び出され、get intent が正常に返された場合はアカウントがリンクされます。
      2. [いいえ]: create intent が呼び出され、create intent が正常に返された場合はアカウントがリンクされます。

既存のユーザー アカウントを確認する(インテントを確認する)

ユーザーが Google プロフィールへのアクセスに同意すると、 Google ユーザーの ID に関する署名付きアサーションを含むリクエスト。「 アサーションには、ユーザーの Google アカウント ID、 表示されます。アプリケーション用に構成されたトークン交換エンドポイント プロジェクトがリクエストを処理できます

対応する Google アカウントが認証にすでに存在する場合 トークン交換エンドポイントは account_found=true を返します。もし Google アカウントが既存のユーザーと一致しません。トークン交換エンドポイントがあります account_found=false で HTTP 404 Not Found エラーを返す。

リクエストは次のようになります。

POST /token HTTP/1.1
Host: oauth2.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&intent=check&assertion=JWT&scope=SCOPES&client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET

トークン交換エンドポイントでは、以下のパラメータを処理する必要があります。

トークン交換エンドポイントのパラメータ
intent これらのリクエストでは、このパラメータの値は check
grant_type 交換されるトークンの種類。これらのリクエストでは、 パラメータの値は urn:ietf:params:oauth:grant-type:jwt-bearer です。
assertion Google ユーザー ID の署名付きアサーションを提供する JSON Web Token(JWT)。この JWT には、ユーザーの認証情報、 Google アカウント ID、名前、メールアドレス。
client_id Google に割り当てたクライアント ID。
client_secret Google に割り当てたクライアント シークレット。

check インテント リクエストに応答するには、トークン交換エンドポイントで次の手順を行う必要があります。

  • JWT アサーションを検証してデコードします。
  • Google アカウントが認証システムにすでに存在するかどうかを確認します。
JWT アサーションを検証してデコードする

JWT アサーションの検証とデコードは、 ご使用の言語に対応した JWT デコード ライブラリ。使用 Google の公開鍵は、Google Cloud で提供されている JWK または PEM 形式を使用しており、 トークンの署名。

デコードされた場合、JWT アサーションは次の例のようになります。

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

トークンの署名を検証するだけでなく、アサーションの 発行者(iss フィールド)が https://accounts.google.com の場合、 (aud フィールド)は、割り当てられたクライアント ID で、トークンの有効期限が切れていないことを確認します。 (exp フィールド)。

emailemail_verifiedhd フィールドを使用すると、 Google はメールアドレスをホストし、その権威があります。Google が そのユーザーが現在正当なアカウント所有者であることが判明している場合 パスワードやその他の本人確認の方法をスキップすることもできます。それ以外の場合、これらのメソッドは を使用して、リンクする前にアカウントを確認できます。

Google が信頼できるケース:

  • email には @gmail.com という接尾辞が付いています。これは Gmail アカウントです。
  • email_verified は true で、hd が設定されています。これは G Suite アカウントです。

ユーザーは Gmail や G Suite を使用せずに Google アカウントを登録できます。日時 email@gmail.com という接尾辞がなく、hd が存在しない場合、Google には含まれません。 認証には、信頼できる認証方法、パスワード、その他の本人確認方法を使用することが推奨されます。 できます。email_verified も、Google が最初に検証した ユーザーに付与できますが、サードパーティの所有権が付与されます。 アカウントが変更された可能性があります。

Google アカウントが認証システムに存在するかどうかの確認

次のいずれかの条件を満たしていることを確認します。

  • アサーションの sub フィールドにある Google アカウント ID がユーザーのものである データベースです
  • アサーションに含まれているメールアドレスが、ユーザーのデータベースに登録されているユーザーと一致している。

いずれかの条件が true の場合、ユーザーは登録済みです。その場合、 次のようなレスポンスが返されます。

HTTP/1.1 200 Success
Content-Type: application/json;charset=UTF-8

{
  "account_found":"true",
}

Google アカウント ID もメールアドレスも アサーションがデータベース内のユーザーと一致した場合、ユーザーはまだ登録されていません。イン この場合、トークン交換エンドポイントは HTTP 404 エラーを返す必要があります。 "account_found": "false" を指定します。次に例を示します。

HTTP/1.1 404 Not found
Content-Type: application/json;charset=UTF-8

{
  "account_found":"false",
}

Handle automatic linking (get intent)

After the user gives consent to access their Google profile, Google sends a request that contains a signed assertion of the Google user's identity. The assertion contains information that includes the user's Google Account ID, name, and email address. The token exchange endpoint configured for your project handles that request.

If the corresponding Google Account is already present in your authentication system, your token exchange endpoint returns a token for the user. If the Google Account doesn't match an existing user, your token exchange endpoint returns a linking_error error and optional login_hint.

The request has the following form:

POST /token HTTP/1.1
Host: oauth2.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&intent=get&assertion=JWT&scope=SCOPES&client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET

Your token exchange endpoint must be able to handle the following parameters:

Token endpoint parameters
intent For these requests, the value of this parameter is get.
grant_type The type of token being exchanged. For these requests, this parameter has the value urn:ietf:params:oauth:grant-type:jwt-bearer.
assertion A JSON Web Token (JWT) that provides a signed assertion of the Google user's identity. The JWT contains information that includes the user's Google Account ID, name, and email address.
scope Optional: Any scopes that you've configured Google to request from users.
client_id The client ID you assigned to Google.
client_secret The client secret you assigned to Google.

To respond to the get intent requests, your token exchange endpoint must perform the following steps:

  • Validate and decode the JWT assertion.
  • Check if the Google account is already present in your authentication system.
JWT アサーションを検証してデコードする

JWT アサーションの検証とデコードは、 ご使用の言語に対応した JWT デコード ライブラリ。使用 Google の公開鍵は、Google Cloud で提供されている JWK または PEM 形式を使用しており、 トークンの署名。

デコードされた場合、JWT アサーションは次の例のようになります。

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

トークンの署名を検証するだけでなく、アサーションの 発行者(iss フィールド)が https://accounts.google.com の場合、 (aud フィールド)は、割り当てられたクライアント ID で、トークンの有効期限が切れていないことを確認します。 (exp フィールド)。

emailemail_verifiedhd フィールドを使用すると、 Google はメールアドレスをホストし、その権威があります。Google が そのユーザーが現在正当なアカウント所有者であることが判明している場合 パスワードやその他の本人確認の方法をスキップすることもできます。それ以外の場合、これらのメソッドは を使用して、リンクする前にアカウントを確認できます。

Google が信頼できるケース:

  • email には @gmail.com という接尾辞が付いています。これは Gmail アカウントです。
  • email_verified は true で、hd が設定されています。これは G Suite アカウントです。

ユーザーは Gmail や G Suite を使用せずに Google アカウントを登録できます。日時 email@gmail.com という接尾辞がなく、hd が存在しない場合、Google には含まれません。 認証には、信頼できる認証方法、パスワード、その他の本人確認方法を使用することが推奨されます。 できます。email_verified も、Google が最初に検証した ユーザーに付与できますが、サードパーティの所有権が付与されます。 アカウントが変更された可能性があります。

Check if the Google account is already present in your authentication system

Check whether either of the following conditions are true:

  • The Google Account ID, found in the assertion's sub field, is in your user database.
  • The email address in the assertion matches a user in your user database.

If an account is found for the user, issue an access token and return the values in a JSON object in the body of your HTTPS response, like in the following example:

{
  "token_type": "Bearer",
  "access_token": "ACCESS_TOKEN",
  "refresh_token": "REFRESH_TOKEN",
  "expires_in": SECONDS_TO_EXPIRATION
}

In some cases, account linking based on ID token might fail for the user. If it does so for any reason, your token exchange endpoint needs to reply with a HTTP 401 error that specifies error=linking_error, as the following example shows:

HTTP/1.1 401 Unauthorized
Content-Type: application/json;charset=UTF-8

{
  "error":"linking_error",
  "login_hint":"foo@bar.com"
}

When Google receives a 401 error response with linking_error, Google sends the user to your authorization endpoint with login_hint as a parameter. The user completes account linking using the OAuth linking flow in their browser.

Handle account creation using Sign in with Google (create intent)

When a user needs to create an account on your service, Google makes a request to your token exchange endpoint that specifies intent=create.

The request has the following form:

POST /token HTTP/1.1
Host: oauth2.example.com
Content-Type: application/x-www-form-urlencoded

response_type=token&grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&scope=SCOPES&intent=create&assertion=JWT&client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET

Your token exchange endpoint must able to handle the following parameters:

Token endpoint parameters
intent For these requests, the value of this parameter is create.
grant_type The type of token being exchanged. For these requests, this parameter has the value urn:ietf:params:oauth:grant-type:jwt-bearer.
assertion A JSON Web Token (JWT) that provides a signed assertion of the Google user's identity. The JWT contains information that includes the user's Google Account ID, name, and email address.
client_id The client ID you assigned to Google.
client_secret The client secret you assigned to Google.

The JWT within the assertion parameter contains the user's Google Account ID, name, and email address, which you can use to create a new account on your service.

To respond to the create intent requests, your token exchange endpoint must perform the following steps:

  • Validate and decode the JWT assertion.
  • Validate user information and create new account.
JWT アサーションを検証してデコードする

JWT アサーションの検証とデコードは、 ご使用の言語に対応した JWT デコード ライブラリ。使用 Google の公開鍵は、Google Cloud で提供されている JWK または PEM 形式を使用しており、 トークンの署名。

デコードされた場合、JWT アサーションは次の例のようになります。

{
  "sub": "1234567890",      // The unique ID of the user's Google Account
  "iss": "https://accounts.google.com",        // The assertion's issuer
  "aud": "123-abc.apps.googleusercontent.com", // Your server's client ID
  "iat": 233366400,         // Unix timestamp of the assertion's creation time
  "exp": 233370000,         // Unix timestamp of the assertion's expiration time
  "name": "Jan Jansen",
  "given_name": "Jan",
  "family_name": "Jansen",
  "email": "jan@gmail.com", // If present, the user's email address
  "email_verified": true,   // true, if Google has verified the email address
  "hd": "example.com",      // If present, the host domain of the user's GSuite email address
                            // If present, a URL to user's profile picture
  "picture": "https://lh3.googleusercontent.com/a-/AOh14GjlTnZKHAeb94A-FmEbwZv7uJD986VOF1mJGb2YYQ",
  "locale": "en_US"         // User's locale, from browser or phone settings
}

トークンの署名を検証するだけでなく、アサーションの 発行者(iss フィールド)が https://accounts.google.com の場合、 (aud フィールド)は、割り当てられたクライアント ID で、トークンの有効期限が切れていないことを確認します。 (exp フィールド)。

emailemail_verifiedhd フィールドを使用すると、 Google はメールアドレスをホストし、その権威があります。Google が そのユーザーが現在正当なアカウント所有者であることが判明している場合 パスワードやその他の本人確認の方法をスキップすることもできます。それ以外の場合、これらのメソッドは を使用して、リンクする前にアカウントを確認できます。

Google が信頼できるケース:

  • email には @gmail.com という接尾辞が付いています。これは Gmail アカウントです。
  • email_verified は true で、hd が設定されています。これは G Suite アカウントです。

ユーザーは Gmail や G Suite を使用せずに Google アカウントを登録できます。日時 email@gmail.com という接尾辞がなく、hd が存在しない場合、Google には含まれません。 認証には、信頼できる認証方法、パスワード、その他の本人確認方法を使用することが推奨されます。 できます。email_verified も、Google が最初に検証した ユーザーに付与できますが、サードパーティの所有権が付与されます。 アカウントが変更された可能性があります。

Validate user information and create new account

Check whether either of the following conditions are true:

  • The Google Account ID, found in the assertion's sub field, is in your user database.
  • The email address in the assertion matches a user in your user database.

If either condition is true, prompt the user to link their existing account with their Google Account. To do so, respond to the request with an HTTP 401 error that specifies error=linking_error and gives the user's email address as the login_hint. The following is a sample response:

HTTP/1.1 401 Unauthorized
Content-Type: application/json;charset=UTF-8

{
  "error":"linking_error",
  "login_hint":"foo@bar.com"
}

When Google receives a 401 error response with linking_error, Google sends the user to your authorization endpoint with login_hint as a parameter. The user completes account linking using the OAuth linking flow in their browser.

If neither condition is true, create a new user account with the information provided in the JWT. New accounts don't typically have a password set. It's recommended that you add Sign in with Google to other platforms to enable users to sign in with Google across the surfaces of your application. Alternatively, you can email the user a link that starts your password recovery flow to allow the user to set a password to sign in on other platforms.

When the creation is completed, issue an access token and refresh token and return the values in a JSON object in the body of your HTTPS response, like in the following example:

{
  "token_type": "Bearer",
  "access_token": "ACCESS_TOKEN",
  "refresh_token": "REFRESH_TOKEN",
  "expires_in": SECONDS_TO_EXPIRATION
}

Google API クライアント ID を取得する

アカウント リンクの登録プロセスでは、Google API クライアント ID を指定する必要があります。OAuth リンクの手順を完了する際に作成したプロジェクトを使用して API クライアント ID を取得するには、次の手順を行います。

  1. [クライアント] ページに移動します
  2. Google API プロジェクトを作成または選択します。

    プロジェクトにウェブ アプリケーション タイプのクライアント ID がない場合は、[クライアントを作成] をクリックして作成します。[承認済みの JavaScript 生成元] ボックスにサイトのドメインを含めるようにしてください。ローカルテストまたは開発を行う場合は、http://localhosthttp://localhost:<port_number>の両方を [承認済みの JavaScript 生成元]フィールドに追加する必要があります。

実装を検証する

You can validate your implementation by using the OAuth 2.0 Playground tool.

In the tool, do the following steps:

  1. Click Configuration to open the OAuth 2.0 Configuration window.
  2. In the OAuth flow field, select Client-side.
  3. In the OAuth Endpoints field, select Custom.
  4. Specify your OAuth 2.0 endpoint and the client ID you assigned to Google in the corresponding fields.
  5. In the Step 1 section, don't select any Google scopes. Instead, leave this field blank or type a scope valid for your server (or an arbitrary string if you don't use OAuth scopes). When you're done, click Authorize APIs.
  6. In the Step 2 and Step 3 sections, go through the OAuth 2.0 flow and verify that each step works as intended.

You can validate your implementation by using the Google Account Linking Demo tool.

In the tool, do the following steps:

  1. Click the Sign in with Google button.
  2. Choose the account you'd like to link.
  3. Enter the service ID.
  4. Optionally enter one or more scopes that you will request access for.
  5. Click Start Demo.
  6. When prompted, confirm that you may consent and deny the linking request.
  7. Confirm that you are redirected to your platform.