概要
OAuth ベースの Google ログインを効率化するリンクにより、OAuth リンクの上に Google ログインが追加されます。これにより、Google ユーザーはシームレスなリンクを設定できるようになります。また、アカウントの作成も可能になり、ユーザーは自身の Google アカウントを使用してサービス上で新しいアカウントを作成できるようになります。
OAuth と Google ログインを使用してアカウント リンクを行うには、次の一般的な手順に従います。
- まず、ユーザーの Google プロフィールにアクセスすることについてユーザーに同意を求めます。
- プロフィールの情報を使って、ユーザー アカウントが存在するかどうかを確認します。
- 既存のユーザーの場合は、アカウントをリンクします。
- 認証システムで Google ユーザーと一致するユーザーが見つからない場合は、Google から受け取った ID トークンを検証します。その後、ID トークンに含まれるプロファイル情報に基づいてユーザーを作成できます。
![この図は、ユーザーが簡素化されたリンクフローを使用して Google アカウントをリンクするための手順を示しています。最初のスクリーンショットは、ユーザーがリンク対象のアプリを選択する方法を示しています。2 枚目のスクリーンショットでは、ユーザーがそのサービスの既存のアカウントを使用しているかどうかを確認できます。3 つ目のスクリーンショットでは、ユーザーはリンクする Google アカウントを選択できます。4 つ目のスクリーンショットは、Google アカウントとアプリをリンクした際の確認画面を示しています。5 つ目のスクリーンショットは、Google アプリで適切にリンクされたユーザー アカウントを示しています。](https://developers.google.cn/static/identity/account-linking/images/streamlined-linking-flow.png?authuser=7&hl=ja)
図 1. ユーザーのスマートフォンでのアカウントのリンクの簡素化
リンクを合理化するための要件
- 基本的なウェブ OAuth リンクのフローを実装するサービスが OAuth 2.0 準拠の承認エンドポイントとトークン交換エンドポイントをサポートしている必要があります。
- トークン交換エンドポイントは、JSON ウェブトークン(JWT)アサーションをサポートし、
check
、create
、get
インテントを実装する必要があります。
OAuth サーバーを実装する
トークン交換エンドポイントは、check
、create
、get
インテントをサポートしている必要があります。以下に、アカウント リンクのフローに従って完了した手順と、さまざまなインテントが呼び出されたタイミングを示します。
- ユーザーの認証システムにアカウントはありますか?(ユーザーが「はい」または「いいえ」を選択したとき)。
- はい : ユーザーが Google アカウントに関連付けられているメールアドレスを使用してプラットフォームにログインしていますか?(ユーザーが「はい」または「いいえ」を選択したとき)。
- はい : お客様の認証システムに一致するアカウントはありますか?(確認のために
check intent
が呼び出されます)- YES :
get intent
が呼び出され、get インテントが正常に返された場合、アカウントはリンクされています。 - いいえ : 新しいアカウントを作成しますか?(ユーザーが「はい」または「いいえ」を選択したとき)。
- YES:
create intent
が呼び出され、作成インテントが正常に返された場合、アカウントはリンクされています。 - いいえ : ウェブ OAuth フローがトリガーされ、ユーザーはブラウザにリダイレクトされます。別のメールにリンクするオプションがユーザーに表示されます。
- YES:
- YES :
- いいえ : ウェブの OAuth フローがトリガーされ、ユーザーはブラウザにリダイレクトされます。別のメールにリンクするオプションがユーザーに表示されます。
- はい : お客様の認証システムに一致するアカウントはありますか?(確認のために
- いいえ : 認証システムに登録されているユーザーと一致するアカウントはありますか?(確認のために
check intent
が呼び出されます)- YES:
get intent
が呼び出され、get インテントが正常に返された場合、アカウントはリンクされています。 - × :
create intent
が呼び出され、作成インテントが正常に返された場合、アカウントはリンクされています。
- YES:
- はい : ユーザーが Google アカウントに関連付けられているメールアドレスを使用してプラットフォームにログインしていますか?(ユーザーが「はい」または「いいえ」を選択したとき)。
既存のユーザー アカウントを確認する(インテントを確認する)
ユーザーが Google プロフィールへのアクセスに同意すると、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アサーションを検証およびデコードできます。 JWKまたはPEM形式で利用可能なGoogleの公開鍵を使用して、トークンの署名を確認します。
デコードすると、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
フィールド)。
email
、 email_verified
、 hd
フィールドを使用して、Googleがメールアドレスをホストしていて権限があるかどうかを判断できます。 Googleが信頼できる場合、ユーザーは現在正当なアカウント所有者であることがわかっており、パスワードやその他のチャレンジ方法をスキップできます。それ以外の場合は、これらの方法を使用して、リンクする前にアカウントを確認できます。
Googleが権威を持っている場合:
-
email
には@gmail.com
サフィックスが付いています。これはGmailアカウントです。 -
email_verified
がtrueで、hd
が設定されている場合、これはemail_verified
アカウントです。
ユーザーはGmailやGSuiteを使用せずにGoogleアカウントに登録できます。 email
@gmail.com
サフィックスが含まれておらず、 hd
がない場合、Googleは信頼できません。ユーザーを確認するには、パスワードまたはその他のチャレンジ方法をお勧めします。 email_verfied
は、Googleアカウントが作成されたときにGoogleが最初にユーザーを確認したため、trueになることもありますが、サードパーティの電子メールアカウントの所有権が変更された可能性があります。
Google アカウントが認証システムに存在するかどうかの確認
次のいずれかの条件を満たしていることを確認します。
- アサーションの
sub
フィールドにある Google アカウント ID が、ユーザー データベースにあります。 - アサーションに含まれているメールアドレスが、ユーザーのデータベースに登録されているユーザーと一致している。
いずれかの条件を満たしていれば、ユーザーはすでに登録しています。その場合、次のようなレスポンスが返されます。
HTTP/1.1 200 Success Content-Type: application/json;charset=UTF-8 { "account_found":"true", }
Google アカウント ID とアサーションで指定されたメールアドレスのいずれもデータベース内のユーザーと一致しない場合、ユーザーはまだ登録していません。その場合、トークン交換エンドポイントは "account_found": "false"
を指定する HTTP 404 エラーを返す必要があります。次に例を示します。
HTTP/1.1 404 Not found Content-Type: application/json;charset=UTF-8 { "account_found":"false", }
自動リンクを処理する(インテントを取得)
ユーザーが Google プロフィールへのアクセスに同意すると、Google は、Google ユーザー ID の署名付きアサーションを含むリクエストを送信します。アサーションには、ユーザーの Google アカウント ID、名前、メールアドレスなどの情報が含まれます。リクエストは、プロジェクト用に構成されたトークン交換エンドポイントによって処理されます。
対応する 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 |
Google ユーザー ID の署名付きアサーションを提供する JSON Web Token(JWT)。JWT には、ユーザーの Google アカウント ID、名前、メールアドレスなどの情報が含まれています。 |
scope |
省略可: ユーザーにリクエストするように Google が構成したスコープ。 |
client_id |
Google に割り当てたクライアント ID。 |
client_secret |
Google に割り当てたクライアント シークレット。 |
get
インテント リクエストに応答するには、トークン交換エンドポイントで次の手順を行う必要があります。
- JWT アサーションを検証してデコードします。
- 認証システムに Google アカウントがすでに存在するかどうかを確認します。
JWTアサーションを検証してデコードします
言語のJWTデコードライブラリを使用して、JWTアサーションを検証およびデコードできます。 JWKまたはPEM形式で利用可能なGoogleの公開鍵を使用して、トークンの署名を確認します。
デコードすると、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
フィールド)。
email
、 email_verified
、 hd
フィールドを使用して、Googleがメールアドレスをホストしていて権限があるかどうかを判断できます。 Googleが信頼できる場合、ユーザーは現在正当なアカウント所有者であることがわかっており、パスワードやその他のチャレンジ方法をスキップできます。それ以外の場合は、これらの方法を使用して、リンクする前にアカウントを確認できます。
Googleが権威を持っている場合:
-
email
には@gmail.com
サフィックスが付いています。これはGmailアカウントです。 -
email_verified
がtrueで、hd
が設定されている場合、これはemail_verified
アカウントです。
ユーザーはGmailやGSuiteを使用せずにGoogleアカウントに登録できます。 email
@gmail.com
サフィックスが含まれておらず、 hd
がない場合、Googleは信頼できません。ユーザーを確認するには、パスワードまたはその他のチャレンジ方法をお勧めします。 email_verfied
は、Googleアカウントが作成されたときにGoogleが最初にユーザーを確認したため、trueになることもありますが、サードパーティの電子メールアカウントの所有権が変更された可能性があります。
Google アカウントが認証システムに存在するかどうかの確認
次のいずれかの条件を満たしていることを確認します。
- アサーションの
sub
フィールドにある Google アカウント ID が、ユーザー データベースにあります。 - アサーションに含まれているメールアドレスが、ユーザーのデータベースに登録されているユーザーと一致している。
ユーザーのアカウントが見つかった場合は、アクセス トークンを発行して、HTTPS レスポンス本文の JSON オブジェクトに値を返します(例:
{ "token_type": "Bearer", "access_token": "ACCESS_TOKEN", "expires_in": SECONDS_TO_EXPIRATION })。
場合によっては、ID トークンに基づくアカウントのリンクが失敗することがあります。なんらかの理由で存在する場合、トークン交換エンドポイントは error=linking_error
を指定する HTTP 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 登录功能创建帐号(创建 intent)
当用户需要在您的服务上创建帐号时,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 |
一个 JSON Web 令牌 (JWT),用于提供 Google 用户身份的签名断言。JWT 包含用户的 Google 帐号 ID、姓名和电子邮件地址等信息。 |
client_id |
您分配给 Google 的客户端 ID。 |
client_secret |
您分配给 Google 的客户端密钥。 |
assertion
参数中的 JWT 包含用户的 Google 帐号 ID、名称和电子邮件地址,您可以使用这些信息在服务中创建新帐号。
为了响应 create
intent 请求,您的令牌交换端点必须执行以下步骤:
- 验证并解码 JWT 断言。
- 验证用户信息并创建新帐号。
JWTアサーションを検証してデコードします
言語のJWTデコードライブラリを使用して、JWTアサーションを検証およびデコードできます。 JWKまたはPEM形式で利用可能なGoogleの公開鍵を使用して、トークンの署名を確認します。
デコードすると、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
フィールド)。
email
、 email_verified
、 hd
フィールドを使用して、Googleがメールアドレスをホストしていて権限があるかどうかを判断できます。 Googleが信頼できる場合、ユーザーは現在正当なアカウント所有者であることがわかっており、パスワードやその他のチャレンジ方法をスキップできます。それ以外の場合は、これらの方法を使用して、リンクする前にアカウントを確認できます。
Googleが権威を持っている場合:
-
email
には@gmail.com
サフィックスが付いています。これはGmailアカウントです。 -
email_verified
がtrueで、hd
が設定されている場合、これはemail_verified
アカウントです。
ユーザーはGmailやGSuiteを使用せずにGoogleアカウントに登録できます。 email
@gmail.com
サフィックスが含まれておらず、 hd
がない場合、Googleは信頼できません。ユーザーを確認するには、パスワードまたはその他のチャレンジ方法をお勧めします。 email_verfied
は、Googleアカウントが作成されたときにGoogleが最初にユーザーを確認したため、trueになることもありますが、サードパーティの電子メールアカウントの所有権が変更された可能性があります。
验证用户信息并创建新帐号
检查是否满足以下任一条件:
- Google 帐号 ID 可在用户的数据库中找到,可在断言的
sub
字段找到。 - 断言中的电子邮件地址与您的用户数据库中的用户匹配。
如果任一条件为 true,请提示用户将其现有帐号与其 Google 帐号相关联。为此,请对请求进行响应,并提供指定 error=linking_error
并将用户的电子邮件地址作为 login_hint
的 HTTP 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 关联流程完成帐号关联。
如果两个条件都不满足,请使用 JWT 中提供的信息创建新的用户帐号。新帐号通常不会设置密码。建议您将 Google 登录功能添加到其他平台,以便用户能够在应用界面使用 Google 帐号登录。或者,您也可以通过电子邮件向用户发送一个启动密码恢复流程的链接,以便用户设置密码以在其他平台上登录。
创建完成后,发出访问令牌 ,并在 HTTPS 响应的正文中以 JSON 对象形式返回值,如以下示例所示:
{ "token_type": "Bearer", "access_token": "ACCESS_TOKEN", "expires_in": SECONDS_TO_EXPIRATION }
Google API クライアント ID を取得する
アカウントのリンク登録プロセス中に、Google API クライアント ID を入力する必要があります。
OAuth リンクの手順を実行する際に作成したプロジェクトを使用して、API クライアント ID を取得すること。そのための手順は次のとおりです。
- Google API Console の [認証情報] ページを開きます。
Google API プロジェクトを作成または選択します。
プロジェクトにウェブ アプリケーション タイプのクライアント ID がない場合は、[認証情報を作成 & OAuth クライアント ID] をクリックして作成します。[承認済みの JavaScript 生成元] ボックスにサイトのドメインを含めてください。ローカルテストまたは開発を行う場合は、
http://localhost
とhttp://localhost:<port_number>
の両方を [承認済みの JavaScript 生成元] フィールドに追加する必要があります。
実装の検証
您可以通过使用验证实现的OAuth 2.0游乐场工具。
在工具中,执行以下步骤:
- 单击配置 打开的OAuth 2.0配置窗口。
- 在OAuth流场中,选择客户端。
- 在OAuth端点字段中,选择自定义。
- 在相应字段中指定您的 OAuth 2.0 端点和您分配给 Google 的客户端 ID。
- 在步骤1部分,不要选择任何谷歌范围。相反,将此字段留空或键入对您的服务器有效的范围(如果不使用 OAuth 范围,则输入任意字符串)。当您完成后,单击授权的API。
- 在步骤2和步骤3段,完成OAuth 2.0流程和验证每个步骤按预期工作。
您可以通过验证您的实现谷歌帐户链接演示工具。
在工具中,执行以下步骤:
- 点击登录在与谷歌按钮。
- 选择您要关联的帐户。
- 输入服务标识。
- (可选)输入您将请求访问的一个或多个范围。
- 单击开始演示。
- 出现提示时,确认您可以同意并拒绝链接请求。
- 确认您被重定向到您的平台。