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 リンクフローを実装します。サービスは、OAuth 2.0 準拠の認可エンドポイントとトークン交換エンドポイントをサポートする必要があります。
  • トークン交換エンドポイントは、JSON Web Token(JWT)アサーションをサポートし、checkcreateget インテントを実装する必要があります。

OAuth サーバーを実装する

トークン交換エンドポイントは、checkcreateget インテントをサポートする必要があります。以下の図は、アカウントのリンクフローで完了する手順と、さまざまなインテントの呼び出しタイミングを示しています。

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

处理自动链接(获取 intent)

在用户同意访问其 Google 个人资料后,Google 会发送 请求,其中包含 Google 用户身份的已签名断言。通过 断言包含的信息包括用户的 Google 账号 ID、 姓名和电子邮件地址为您的 Google Cloud 控制台配置的令牌交换端点 项目处理该请求。

如果您的身份验证中已有相应的 Google 账号 系统,您的令牌交换端点将为用户返回一个令牌。如果 Google 账号与现有用户不匹配,您的令牌交换端点 返回 linking_error 错误和可选的 login_hint

请求的格式如下:

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

您的令牌交换端点必须能够处理以下参数:

令牌端点参数
intent 对于这些请求,此参数的值为 get
grant_type 所交换的令牌的类型。对于这类请求 参数的值为 urn:ietf:params:oauth:grant-type:jwt-bearer
assertion 一个 JSON Web 令牌 (JWT),提供 Google 用户身份。JWT 包含的信息包括用户 Google 账号 ID、姓名和电子邮件地址。
scope 可选:您已将 Google 配置为向其请求访问权限的任何范围 用户。
client_id 您分配给 Google 的客户 ID。
client_secret 您分配给 Google 的客户端密钥。

如需响应 get intent 请求,您的令牌交换端点必须执行以下步骤:

  • 验证和解码 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 账号

请检查以下任一条件是否成立:

  • Google 账号 ID(可在断言的 sub 字段中找到)位于您的用户中 数据库。
  • 断言中的电子邮件地址与用户数据库中的用户匹配。

如果找到了用户的账号,请发出访问令牌,并在 HTTPS 响应正文的 JSON 对象中返回相应值,如以下示例所示:

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

在某些情况下,基于 ID 令牌的账号关联可能会失败。如果 因为任何原因,您的令牌交换端点都需要以 HTTP 响应 指定 error=linking_error 的 401 错误,如以下示例所示:

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

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

当 Google 收到包含 linking_error 的 401 错误响应时,会发送 使用 login_hint 作为参数将用户发送到您的授权端点。通过 用户在浏览器中使用 OAuth 关联流程完成账号关联。

Google ログインを介したアカウント作成の処理(インテントの作成)

ユーザーがニュース メディアのサービスでアカウントを作成する必要がある場合、Google は intent=create を指定するトークン交換エンドポイントに追加します。

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

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

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

トークン交換エンドポイントのパラメータ
intent これらのリクエストの場合、このパラメータの値は create です。
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 に割り当てたクライアント シークレット。

assertion パラメータ内の JWT には、ユーザーの Google アカウント ID が含まれます。 名前とメールアドレスです。これらの情報を使用して、 あります。

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

  • JWT アサーションを検証してデコードします。
  • ユーザー情報を確認し、新しいアカウントを作成する。
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 が最初に検証した ユーザーに付与できますが、サードパーティの所有権が付与されます。 アカウントが変更された可能性があります。

ユーザー情報を検証して新しいアカウントを作成する

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

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

いずれかの条件が true の場合、既存のアカウントをリンクするようユーザーに促す ログインする必要がありますそのためには、リクエストに対して HTTP 401 エラーを返します。 error=linking_error を指定し、ユーザーのメールアドレスを login_hint。レスポンスの例を次に示します。

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

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

Google は、linking_error で 401 エラー レスポンスを受信すると、 login_hint をパラメータとして使用して、ユーザーを認可エンドポイントに送信します。「 ユーザーがブラウザで OAuth リンクフローを使用してアカウントのリンクを完了します。

どちらの条件も当てはまらない場合は、その情報で新しいユーザー アカウントを作成します。 JWT で提供します。通常、新しいアカウントにはパスワードが設定されていません。です。 他のプラットフォームにも Google ログインを追加して、ユーザーが Google でログインできるようになります。または パスワードの再設定フローを開始するリンクをメールで送信できます。 ユーザーが他のプラットフォームにログインするためのパスワードを設定できるようにする必要があります。

作成が完了したら、アクセス トークンを発行します。 JSON オブジェクトで値を HTTPS レスポンスの本文に URL を付加します。

{
  "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. Google API プロジェクトを作成または選択します。

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

実装の検証

您可以使用 OAuth 2.0 Playground 工具验证您的实现。

在该工具中,执行以下步骤:

  1. 点击配置 以打开 OAuth 2.0 配置窗口。
  2. OAuth flow 字段中,选择 Client-side(客户端)。
  3. OAuth 端点字段中,选择自定义
  4. 在相应字段中指定您的 OAuth 2.0 端点和您分配给 Google 的客户端 ID。
  5. 第 1 步部分,不要选择任何 Google 范围。请将此字段留空或输入对服务器有效的范围(如果您不使用 OAuth 范围,则可以输入任意字符串)。完成后,点击授权 API
  6. Step 2Step 3 部分中,完成 OAuth 2.0 流程,并验证每个步骤是否按预期运行。

您可以使用 Google 账号关联演示版工具验证您的实现。

在该工具中,执行以下步骤:

  1. 点击使用 Google 账号登录按钮。
  2. 选择您要关联的账号。
  3. 输入服务 ID。
  4. (可选)输入您要请求访问权限的一个或多个范围。
  5. 点击开始演示
  6. 当系统提示时,请确认您同意或拒绝关联请求。
  7. 确认您已被重定向到您的平台。