すべての smart home アクションには、ユーザーを認証するメカニズムが含まれている必要があります。
認証を使用すると、ユーザーの Google アカウントを認証システムのユーザー アカウントにリンクできます。これにより、フルフィルメントでスマートホーム インテントを受け取ったときにユーザーを識別できます。Google スマートホームは、認証コードフローを使用した OAuth のみをサポートします。
このページでは、smart home アクションと連携するように OAuth 2.0 サーバーを設定する方法について説明します。
認可コードフロー
認証コードフローの OAuth 2.0 サーバー実装は 2 つのエンドポイントで構成され、サービスは HTTPS で利用可能です。最初のエンドポイントは承認エンドポイントです。このエンドポイントは、データアクセスについて、ユーザーに対する同意を取得または取得します。認可エンドポイントは、まだログインしていないユーザーにログイン UI を表示し、リクエストされたアクセスへの同意を記録します。2 つ目のエンドポイントはトークン交換エンドポイントです。トークンは、ユーザーがサービスにアクセスすることを承認する暗号化された文字列(トークン)を取得するために使用されます。
Google アプリケーションがサービスの API の 1 つを呼び出す必要がある場合、Google はこれらのエンドポイントを一緒に使用して、ユーザーに代わってユーザーにこれらの API を呼び出す権限を与えます。
Google によって開始される OAuth 2.0 認証コードフローのセッションは、次のようなフローになります。
- Google がユーザーのブラウザで認可エンドポイントを開きます。アクションの音声操作専用デバイスでフローが開始された場合、Google は実行をスマートフォンに転送します。
- ユーザーが(まだログインしていない場合は)ログインし、API を使用してデータにアクセスする権限を Google に付与します(権限がまだ付与されていない場合)。
- サービスにより認証コードが作成され、Google に返されます。これを行うには、リクエストに添付された認証コードを使用して、ユーザーのブラウザを Google にリダイレクトします。
- Google が認証コードをトークン交換エンドポイントに送信します。トークン交換エンドポイントはコードの信頼性を検証し、アクセス トークンと更新トークンを返します。アクセス トークンは有効期間が短いトークンで、API にアクセスするための認証情報として承認されます。更新トークンは有効期間の長いトークンです。トークンを保管すると、有効期限が切れたときに新しいアクセス トークンを取得するために使用できます。
- ユーザーがアカウント リンクのフローを完了すると、それ以降に Google から送信されるすべてのリクエストにアクセス トークンが含まれるようになります。
認可リクエストの処理
OAuth 2.0 認証コードフローを使用してアカウントのリンクを行う必要がある場合、Google は以下のパラメータを含むリクエストによってユーザーを認証エンドポイントに送信します。
認可エンドポイントのパラメータ | |
---|---|
client_id |
Google に割り当てられたクライアント ID。 |
redirect_uri |
このリクエストに対するレスポンスを送信する宛先 URL。 |
state |
リダイレクト URL で変更されずに Google に返される会計上の値。 |
scope |
省略可: Google が承認をリクエストするデータを指定するためのスコープ文字列のセット。スペースで区切ります。 |
response_type |
レスポンスで返される値のタイプ。OAuth 2.0 認証コードフローの場合、レスポンス タイプは常に code です。 |
user_locale |
Google アカウントの言語設定(RFC5646 形式)。ユーザーの好みの言語にコンテンツをローカライズするために使用されます。 |
たとえば、https://myservice.example.com/auth
で認証エンドポイントが使用できる場合、リクエストは次のようになります。
GET https://myservice.example.com/auth?client_id=GOOGLE_CLIENT_ID&redirect_uri=REDIRECT_URI&state=STATE_STRING&scope=REQUESTED_SCOPES&response_type=code&user_locale=LOCALE
認証エンドポイントがログイン リクエストを処理するには、次の手順を行います。
client_id
が Google に割り当てたクライアント ID と一致し、redirect_uri
が Google から提供されたサービス用のリダイレクト URL と一致することを確認します。これらのチェックは、意図しないクライアント アプリまたは誤って構成されたクライアント アプリへのアクセスを許可しないようにするために重要です。複数の OAuth 2.0 フローをサポートしている場合は、response_type
がcode
かどうかも確認します。- ユーザーがサービスにログインしているかどうか確認します。ユーザーがログインしていない場合は、サービスのログインまたは登録フローを完了します。
- Google が API へのアクセスに使用する認証コードを生成します。認証コードには任意の文字列値を指定できますが、ユーザー、トークンの対象であるクライアント、コードの有効期限をそれぞれ一意に表す必要があります。また、推測できないコードにする必要があります。通常、約 10 分後に期限切れになる認可コードを発行します。
redirect_uri
パラメータで指定された URL がhttps://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID https://oauth-redirect-sandbox.googleusercontent.com/r/YOUR_PROJECT_ID
形式になっていることを確認します。- ユーザーのブラウザを
redirect_uri
パラメータで指定された URL にリダイレクトします。リダイレクト時にcode
パラメータとstate
パラメータを追加して、生成した認証コードと元の変更されていない状態値を含めます。結果の URL の例を次に示します。https://oauth-redirect.googleusercontent.com/r/YOUR_PROJECT_ID?code=AUTHORIZATION_CODE&state=STATE_STRING
トークン交換リクエストの処理
サービスのトークン交換エンドポイントは、次の 2 種類のトークン交換を処理します。
- 認可コードとアクセス トークンおよび更新トークンとの交換
- 更新トークンとアクセス トークンの交換
トークン交換リクエストには、次のパラメータを使用します。
トークン交換エンドポイントのパラメータ | |
---|---|
client_id |
リクエスト元を Google として識別する文字列。この文字列は、Google の一意の識別子としてシステムに登録されている必要があります。 |
client_secret |
Google に登録したサービスのシークレット文字列。 |
grant_type |
交換されるトークンの種類。authorization_code または refresh_token のいずれかです。 |
code |
grant_type=authorization_code の場合、このパラメータは、Google がログイン エンドポイントまたはトークン交換エンドポイントから受け取ったコードです。 |
redirect_uri |
grant_type=authorization_code の場合、このパラメータは最初の承認リクエストで使用される URL です。 |
refresh_token |
grant_type=refresh_token の場合、このパラメータは、Google がトークン交換エンドポイントから受け取った更新トークンです。 |
認可コードとアクセス トークンおよび更新トークンとの交換
ユーザーがログインし、認証エンドポイントから有効期間の短い認証コードが Google に返されると、Google がトークン交換エンドポイントにリクエストを送信し、認証コードをアクセス トークンと更新トークンと交換します。
これらのリクエストの場合、grant_type
の値は authorization_code
で、code
の値は以前に Google に付与した認証コードの値になります。認証トークンをアクセス トークンと更新トークンに交換するためのリクエストの例を次に示します。
POST /token HTTP/1.1 Host: oauth2.example.com Content-Type: application/x-www-form-urlencoded client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET&grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=REDIRECT_URI
アクセス トークンと更新トークンの認証コードを交換するために、トークン交換エンドポイントは次の手順を実行して POST
リクエストに応答します。
client_id
がリクエスト送信元を承認済みの送信元として識別し、client_secret
が期待値と一致することを確認します。- 認証コードが有効で期限切れになっていないことと、リクエストで指定されたクライアント ID が認証コードに関連付けられているクライアント ID と一致していることを確認します。
redirect_uri
パラメータで指定された URL が最初の承認リクエストで使用される値と同じであることを確認します。- 上記の条件をすべて確認できない場合は、本文に
{"error": "invalid_grant"}
を含む HTTP 400 Bad Request エラーを返します。 - それ以外の場合は、認証コードのユーザー ID を使用して、更新トークンとアクセス トークンを生成します。これらのトークンには任意の文字列値を使用できますが、ユーザーとトークンの対象となるクライアントを一意に表したものでなければならず、推測できない必要があります。アクセス トークンの場合は、トークンの有効期限(通常はトークンを発行してから 1 時間)も記録します。更新トークンに有効期限はありません。
- HTTPS レスポンスの本文で JSON オブジェクト
{ "token_type": "Bearer", "access_token": "ACCESS_TOKEN", "refresh_token": "REFRESH_TOKEN", "expires_in": SECONDS_TO_EXPIRATION }
を返します。
Google がユーザーのアクセス トークンと更新トークンを保存し、アクセス トークンの有効期限を記録します。アクセス トークンが期限切れになると、Google は更新トークンを使用してトークン交換エンドポイントから新しいアクセス トークンを取得します。
更新トークンとアクセス トークンの交換
アクセス トークンが期限切れになると、Google はトークン交換エンドポイントにリクエストを送信し、更新トークンを新しいアクセス トークンと交換します。
これらのリクエストの場合、grant_type
の値は refresh_token
で、refresh_token
の値は Google に以前に付与した更新トークンの値です。更新トークンをアクセス トークンに交換するリクエストの例を次に示します。
POST /token HTTP/1.1 Host: oauth2.example.com Content-Type: application/x-www-form-urlencoded client_id=GOOGLE_CLIENT_ID&client_secret=GOOGLE_CLIENT_SECRET&grant_type=refresh_token&refresh_token=REFRESH_TOKEN
更新トークンをアクセス トークンと交換するため、トークン交換エンドポイントは次の手順を実行して POST
リクエストに応答します。
client_id
によってリクエストの送信元が Google として識別され、client_secret
が期待値と一致することを確認します。- 更新トークンが有効で、リクエストで指定されたクライアント ID が更新に関連付けられたクライアント ID と一致していることを確認します。
- 上記の条件をすべて確認できない場合は、
{"error": "invalid_grant"}
を本文とする HTTP 400 Bad Request エラーを返します。 - それ以外の場合は、更新トークンのユーザー ID を使用してアクセス トークンを生成します。これらのトークンには任意の文字列値を使用できますが、ユーザーとトークンの対象となるユーザーを一意に表すことができ、推測可能なものであってはなりません。アクセス トークンの場合は、トークンの有効期限(通常はトークンの発行後 1 時間)も記録します。
- HTTPS レスポンスの本文で次の JSON オブジェクトを返します。
{ "token_type": "Bearer", "access_token": "ACCESS_TOKEN", "expires_in":SECONDS_TO_EXPIRATION }
userinfo リクエストの処理
userinfo エンドポイントは OAuth 2.0 で保護されたリソースであり、リンクされたユーザーに関するクレームが返されます。userinfo エンドポイントの実装とホスティングは、以下のユースケースを除き、任意です。
- Google One Tap でのリンクされたアカウントへのログイン
- Android TV のスムーズな定期購入。
トークン エンドポイントからアクセス トークンが正常に取得されると、Google は userinfo エンドポイントにリクエストを送信し、リンクされたユーザーに関する基本的なプロフィール情報を取得します。
userinfo エンドポイント リクエスト ヘッダー | |
---|---|
Authorization header |
Bearer タイプのアクセス トークン。 |
たとえば、userinfo エンドポイントが https://myservice.example.com/userinfo
で使用可能な場合、リクエストは次のようになります。
GET /userinfo HTTP/1.1 Host: myservice.example.com Authorization: Bearer ACCESS_TOKEN
userinfo エンドポイントでリクエストを処理するには、次の手順を行います。
- Authorization ヘッダーからアクセス トークンを抽出し、そのアクセス トークンに関連付けられているユーザーの情報を返します。
- アクセス トークンが無効な場合は、
WWW-Authenticate
レスポンス ヘッダーを使用して HTTP 401 Unauthorized エラーを返します。以下に、userinfo エラー レスポンスの例を示します。HTTP/1.1 401 Unauthorized WWW-Authenticate: error="invalid_token", error_description="The Access Token expired"
リンク処理中に 401 Unauthorized レスポンスまたは失敗エラーその他のレスポンスが返された場合、エラーは回復不能です。取得したトークンは破棄されるため、ユーザーはリンクプロセスを再度開始する必要があります。 アクセス トークンが有効な場合、HTTPS レスポンスの本文に次の JSON オブジェクトを含むレスポンスが返され、HTTP 200 が返されます。
{ "sub": "USER_UUID", "email": "EMAIL_ADDRESS", "given_name": "FIRST_NAME", "family_name": "LAST_NAME", "name": "FULL_NAME", "picture": "PROFILE_PICTURE", }
userinfo エンドポイントが HTTP 200 の成功レスポンスを返した場合、取得したトークンとクレームはユーザーの Google アカウントに登録されます。userinfo エンドポイント レスポンス sub
システム内のユーザーを識別する一意の ID。 email
ユーザーのメールアドレス。 given_name
省略可: ユーザーの名。 family_name
省略可: ユーザーの姓。 name
省略可: ユーザーの氏名 picture
省略可: ユーザーのプロフィール写真。