リンクされたアカウントへのログイン

Google アカウントのリンクを使用すると、Google アカウントの所有者は迅速かつシームレス、かつ安全にサービスに接続し、Google とデータを共有できます。

リンクされたアカウントにログインすることで、すでに Google アカウントをサービスにリンクしているユーザーが Google でワンタップでログインできるようになります。これにより、ユーザー名とパスワードを再入力しなくてもワンクリックでログインできるようになるため、ユーザーの利便性が向上します。また、ユーザーがサービスで重複するアカウントを作成する可能性も減ります。

要件

リンクされたアカウントのログインを実装するには、次の要件を満たす必要があります。

  • OAuth 2.0 認可コードフローをサポートする Google アカウントの OAuth リンクを実装している。OAuth 実装には、次のエンドポイントを含める必要があります。
    • 認可エンドポイントを使用して認可リクエストを処理します。
    • トークン エンドポイントを使用して、アクセス トークンと更新トークンのリクエストを処理します。
    • userinfo エンドポイント: リンクされたユーザーに関する基本的なアカウント情報を取得します。これは、リンクされたアカウントのログイン プロセス中にユーザーに表示されます。
  • Android アプリを使用している。

仕組み

前提条件 : ユーザーが以前に Google のサービスで自分のアカウントに自分のアカウントをリンクしていること。

  1. ワンタップ ログインフローの際に、リンクされたアカウントを表示するように設定した。
  2. ユーザーには、リンクされたアカウントでサービスにログインするためのワンタップによるログイン プロンプトが表示されます。
  3. ユーザーがリンクされたアカウントで続行することを選択した場合、Google は認可コードを保存するリクエストをトークン エンドポイントに送信します。リクエストには、サービスによって発行されたユーザーのアクセス トークンと Google 認証コードが含まれます。
  4. Google の認証コードを Google ID トークンと交換します。Google ID トークンには、ユーザーの Google アカウントに関する情報が含まれています。
  5. フローの終了時にアプリは ID トークンも受け取り、ユーザーをアプリにログインするために、サーバーで受け取った ID トークンのユーザー ID と照合します。
リンクされたアカウントにログイン。
図 1.リンクされたアカウントのログインフロー。ユーザーがデバイスに複数のログイン アカウントを設定している場合は、Account Chooser が表示され、リンクされたアカウントを選択した場合にのみ [リンクされたアカウントのログイン] ビューが表示されます。

Android アプリにリンクされたアカウントへのログインを実装する

Android アプリでリンクされたアカウントのログインをサポートするには、Android 実装ガイドの手順に沿って操作します。

Google からの認可コード リクエストを処理する

Google はユーザーの ID トークンと交換する認可コードを保存するために、トークン エンドポイントに POST リクエストを作成します。リクエストには、ユーザーのアクセス トークンと Google が発行した OAuth2 認可コードが含まれます。

認可コードを保存する前に、アクセス トークンが client_id で識別される Google に付与されていることを確認する必要があります。

HTTP リクエスト

リクエストの例

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

code=GOOGLE_AUTHORIZATION_CODE
&grant_type=urn:ietf:params:oauth:grant-type:reciprocal
&client_id=CLIENT_ID
&client_secret=CLIENT_SECRET
&access_token=ACCESS_TOKEN

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

トークン交換エンドポイントのパラメータ
code 必須の Google OAuth2 認証コード
client_id Google に発行した必須のクライアント ID
client_secret Google に発行した必須のクライアント シークレット
access_token 必須。Google に発行したアクセス トークン。これを使用してユーザーのコンテキストを取得します。
grant_type 必須の値は urn:ietf:params:oauth:grant-type:reciprocal に設定する必要があります。

トークン交換エンドポイントは、次の方法で POST リクエストに応答する必要があります。

  • access_token が、client_id によって識別される Google に付与されていることを確認します。
  • リクエストが有効で、認証コードが Google ID トークンと正常に交換された場合は、HTTP 200(OK)レスポンスで応答します。リクエストが無効の場合は、HTTP エラーコードを返します。

HTTP レスポンス

成功

HTTP ステータス コード 200 OK を返す

成功のレスポンスの例
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache
{}

エラー

無効な HTTP リクエストが発生した場合は、次のいずれかの HTTP エラーコードで応答します。

HTTP ステータス コード 本文 説明
400 {"error": "invalid_request"} リクエストにパラメータが指定されていないため、サーバーでリクエストを処理できません。リクエストにサポートされていないパラメータが含まれている場合や、パラメータが繰り返されている場合にも返されることがあります
401 {"error": "invalid_request"} クライアント認証の失敗(リクエストに無効なクライアント ID またはシークレットが含まれているなど)
401 {"error": "invalid_token"}

レスポンス ヘッダーに「WWW-Authentication: Bearer」認証チャレンジを含める

パートナーのアクセス トークンが無効です。
403 {"error": "insufficient_permission"}

レスポンス ヘッダーに「WWW-Authentication: Bearer」認証チャレンジを含める

パートナー アクセス トークンに Reciprocal OAuth の実行に必要なスコープが含まれていません
500 {"error": "internal_error"} サーバーエラー

エラー レスポンスには次のフィールドが含まれます。

エラー レスポンス フィールド
error 必須 エラー文字列
error_description 人が読める形式のエラー説明
error_uri エラーの詳細を示す URI
エラー 400 のレスポンスの例
HTTP/1.1 400 Bad Request
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache

{
  "error": "invalid_request",
  "error_description": "Request was missing the 'access_token' parameter."
}

ID トークンの認証コードを交換

受け取った認証コードを Google ID トークンと交換する必要があります。Google ID トークンには、ユーザーの Google アカウントに関する情報が含まれています。

認可コードを Google ID トークンと交換するには、https://oauth2.googleapis.com/token エンドポイントを呼び出して、次のパラメータを設定します。

リクエスト フィールド
client_id 必須。API Console の [認証情報] ページから取得したクライアント ID。通常は「New Actions on Google App」という名前の認証情報です。
client_secret 必須。API Console の [認証情報] ページから取得したクライアント シークレット。
code 必須。最初のリクエストで送信される認証コード。
grant_type 必須OAuth 2.0 仕様で定義されているとおり、このフィールドの値は authorization_code に設定する必要があります。
リクエストの例
POST /oauth2/v4/token HTTP/1.1
Host: www.googleapis.com
Content-Type: application/x-www-form-urlencoded

code=GOOGLE_AUTHORIZATION_CODE
&grant_type=authorization_code
&client_id=GOOGLE_CLIENT_ID
&client_secret=GOOGLE_CLIENT_SECRET

Google はこのリクエストに応答して、有効期間の短いアクセス トークンと更新トークンを含む JSON オブジェクトを返します。

レスポンスには、次のフィールドが含まれます。

レスポンスのフィールド
access_token Google が発行したアクセス トークン。Google API リクエストを認可するためにアプリケーションが送信します。
id_token ID トークンにはユーザーの Google アカウント情報が含まれています。レスポンスの検証セクションには、ID トークンのレスポンスをデコードして検証する方法について詳しく記載されています。
expires_in アクセス トークンの残りの存続期間(秒)
refresh_token 新しいアクセス トークンの取得に使用できるトークン。更新トークンは、ユーザーがアクセス権を取り消すまで有効です
scope リンクされたアカウント ログインのユースケースでは、このフィールドの値は常に openid に設定されます
token_type 返されるトークンのタイプ。現在、このフィールドの値は常に Bearer に設定されます。
レスポンスの例
HTTP/1.1 200 OK
Content-type: application/json; charset=utf-8

{
  "access_token": "Google-access-token",
  "id_token": "Google-ID-token",
  "expires_in": 3599,
  "token_type": "Bearer",
  "scope": "openid",
  "refresh_token": "Google-refresh-token"
}


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

code=Google authorization code
&grant_type=authorization_code
&client_id=Google client id
&client_secret=Google client secret

ID トークンのレスポンスを検証する

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フィールド)。

emailemail_verifiedhdフィールドを使用して、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になることもありますが、サードパーティの電子メールアカウントの所有権が変更された可能性があります。