TVおよび制限付き入力デバイスアプリケーション用のOAuth2.0

このドキュメントでは、テレビ、ゲーム機、プリンターなどのデバイスで実行されているアプリケーションを介してGoogleAPIにアクセスするためのOAuth2.0認証を実装する方法について説明します。より具体的には、このフローは、ブラウザにアクセスできないか、入力機能が制限されているデバイス向けに設計されています。

OAuth 2.0を使用すると、ユーザーはユーザー名、パスワード、その他の情報を非公開にしながら、特定のデータをアプリケーションと共有できます。たとえば、TVアプリケーションはOAuth 2.0を使用して、Googleドライブに保存されているファイルを選択する権限を取得できます。

このフローを使用するアプリケーションは個々のデバイスに配布されるため、アプリは秘密を保持できないと想定されます。ユーザーがアプリを使用しているとき、またはアプリがバックグラウンドで実行されているときに、GoogleAPIにアクセスできます。

代替案

Android、iOS、macOS、Linux、Windows(ユニバーサルWindowsプラットフォームを含む)などのプラットフォーム用のアプリを作成していて、ブラウザーと完全な入力機能にアクセスできる場合は、モバイルおよびデスクトップアプリケーションにOAuth2.0フローを使用します。 (アプリがグラフィカルインターフェイスのないコマンドラインツールであっても、このフローを使用する必要があります。)

Googleアカウントでユーザーにサインインし、 JWT IDトークンを使用して基本的なユーザープロファイル情報を取得する場合、「テレビと制限付き入力デバイスでのサインイン」を参照してください。

前提条件

プロジェクトのAPIを有効にする

Google APIを呼び出すアプリケーションはすべて、 API ConsoleでそれらのAPIを有効にする必要があります。

プロジェクトのAPIを有効にするには:

  1. Open the API Library の Google API Console。
  2. If prompted, select a project, or create a new one.
  3. API Library は、利用可能なすべてのAPIを、製品ファミリーと人気別にグループ化して一覧表示します。有効にするAPIがリストに表示されていない場合は、検索を使用してAPIを見つけるか、それが属する製品ファミリーの[すべて表示]をクリックします。
  4. 有効にするAPIを選択し、[有効]ボタンをクリックします。
  5. If prompted, enable billing.
  6. If prompted, read and accept the API's Terms of Service.

承認資格情報を作成する

OAuth2.0を使用してGoogleAPIにアクセスするアプリケーションには、GoogleのOAuth2.0サーバーに対してアプリケーションを識別する認証資格が必要です。次の手順では、プロジェクトのクレデンシャルを作成する方法について説明します。その後、アプリケーションは資格情報を使用して、そのプロジェクトで有効にしたAPIにアクセスできます。

  1. Go to the Credentials page.
  2. [資格情報の作成]> [OAuthクライアントID]をクリックします。
  3. TVおよび制限付き入力デバイスのアプリケーションタイプを選択します。
  4. OAuth 2.0クライアントに名前を付けて、[作成]をクリックします。

アクセス範囲を特定する

スコープを使用すると、アプリケーションは必要なリソースへのアクセスのみを要求できると同時に、ユーザーはアプリケーションに付与するアクセスの量を制御できます。したがって、要求されたスコープの数とユーザーの同意を得る可能性の間には反比例の関係がある可能性があります。

OAuth 2.0承認の実装を開始する前に、アプリがアクセスするためにアクセス許可を必要とするスコープを特定することをお勧めします。

インストールされているアプリまたはデバイスについては、許可されるスコープのリストを参照してください。

OAuth2.0アクセストークンの取得

アプリケーションが入力機能が制限されたデバイスで実行されている場合でも、この認証フローを完了するには、ユーザーはより豊富な入力機能を備えたデバイスに個別にアクセスできる必要があります。フローには次のステップがあります。

  1. アプリケーションは、アプリケーションがアクセス許可を要求するスコープを識別するリクエストをGoogleの承認サーバーに送信します。
  2. サーバーは、デバイスコードやユーザーコードなど、後続の手順で使用されるいくつかの情報で応答します。
  3. ユーザーがアプリを承認するために別のデバイスに入力できる情報を表示します。
  4. アプリケーションはGoogleの認証サーバーのポーリングを開始して、ユーザーがアプリを認証したかどうかを判断します。
  5. ユーザーは、より豊富な入力機能を備えたデバイスに切り替え、Webブラウザーを起動し、手順3で表示されたURLに移動し、手順3でも表示されたコードを入力します。ユーザーはアプリケーションへのアクセスを許可(または拒否)できます。
  6. ポーリングリクエストへの次の応答には、アプリがユーザーに代わってリクエストを承認するために必要なトークンが含まれています。 (ユーザーがアプリケーションへのアクセスを拒否した場合、応答にはトークンが含まれていません。)

次の画像は、このプロセスを示しています。

ユーザーは、ブラウザーを備えた別のデバイスにログインします

次のセクションでは、これらの手順について詳しく説明します。デバイスが持つ可能性のある機能とランタイム環境の範囲を考慮して、このドキュメントに示されている例では、 curlコマンドラインユーティリティを使用しています。これらの例は、さまざまな言語やランタイムに簡単に移植できるはずです。

ステップ1:デバイスとユーザーコードをリクエストする

この手順では、デバイスがHTTP POSTリクエストをGoogleの承認サーバー( https://oauth2.googleapis.com/device/code )に送信します。このサーバーは、アプリケーションと、アプリケーションがユーザーのアクセスを希望するアクセススコープを識別します。に代わって。このURLは、 device_authorization_endpointメタデータ値を使用してDiscoveryドキュメントから取得する必要があります。次のHTTPリクエストパラメータを含めます。

パラメーター
client_id必須

アプリケーションのクライアントID。この値は、 API ConsoleCredentials pageにあります。

scope必須

アプリケーションがユーザーに代わってアクセスできるリソースを識別するスコープのスペース区切りのリスト。これらの値は、Googleがユーザーに表示する同意画面に通知します。インストールされているアプリまたはデバイスについては、許可されるスコープのリストを参照してください。

スコープを使用すると、アプリケーションは必要なリソースへのアクセスのみを要求できると同時に、ユーザーはアプリケーションに付与するアクセスの量を制御できます。したがって、要求されたスコープの数とユーザーの同意を得る可能性の間には反比例の関係があります。

次のスニペットは、サンプルリクエストを示しています。

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

client_id=client_id&scope=email%20profile

この例は、同じリクエストを送信するためのcurlコマンドを示しています。

curl -d "client_id=client_id&scope=email%20profile" \
     https://oauth2.googleapis.com/device/code

ステップ2:許可サーバーの応答を処理する

許可サーバーは、次のいずれかの応答を返します。

成功への対応

リクエストが有効な場合、レスポンスは次のプロパティを含むJSONオブジェクトになります。

プロパティ
device_code承認をリクエストするアプリを実行するデバイスを識別するためにGoogleが一意に割り当てる値。ユーザーは、より豊富な入力機能を備えた別のデバイスからそのデバイスを承認します。たとえば、ユーザーはラップトップや携帯電話を使用して、テレビで実行されているアプリを承認する場合があります。この場合、 device_codeはTVを識別します。

このコードにより、アプリを実行しているデバイスは、ユーザーがアクセスを許可したか拒否したかを安全に判断できます。

expires_in device_codeuser_codeが有効である時間の長さ(秒単位)。その間に、ユーザーが認証フローを完了せず、デバイスがユーザーの決定に関する情報を取得するためにポーリングも行わない場合は、手順1からこのプロセスを再開する必要があります。
intervalデバイスがポーリング要求間で待機する時間の長さ(秒単位)。たとえば、値が5の場合、デバイスは5秒ごとにポーリングリクエストをGoogleの認証サーバーに送信する必要があります。詳細については、手順3を参照してください。
user_codeアプリケーションがアクセスを要求しているスコープをGoogleに識別する大文字と小文字を区別する値。ユーザーインターフェイスは、より豊富な入力機能を備えた別のデバイスにこの値を入力するようにユーザーに指示します。次に、Googleはその値を使用して、アプリケーションへのアクセスを許可するようにユーザーに求めるときに、正しいスコープのセットを表示します。
verification_urlユーザーが別のデバイスでuser_codeを入力し、アプリケーションへのアクセスを許可または拒否するために移動する必要があるURL。ユーザーインターフェイスにもこの値が表示されます。

次のスニペットは、サンプルの応答を示しています。

{
  "device_code": "4/4-GMMhmHCXhWEzkobqIHGG_EnNYYsAkukHspeYUk9E8",
  "user_code": "GQVQ-JKEC",
  "verification_url": "https://www.google.com/device",
  "expires_in": 1800,
  "interval": 5
}

クォータが応答を超えました

デバイスコードリクエストがクライアントIDに関連付けられたクォータを超えた場合、次のエラーを含む403レスポンスを受け取ります。

{
  "error_code": "rate_limit_exceeded"
}

その場合は、バックオフ戦略を使用してリクエストの割合を減らします。

ステップ3:ユーザーコードを表示する

手順2で取得したverification_urluser_codeをユーザーに表示します。どちらの値にも、US-ASCII文字セットの印刷可能な文字を含めることができます。ユーザーに表示するコンテンツは、別のデバイスでverification_urlに移動し、 user_codeを入力するようにユーザーに指示する必要があります。

次のルールを念頭に置いて、ユーザーインターフェイス(UI)を設計します。

  • user_code
    • user_codeは、15'W 'サイズの文字を処理できるフィールドに表示する必要があります。つまり、コードWWWWWWWWWWWWWWWを正しく表示できる場合、UIは有効であり、 user_codeがUIに表示される方法をテストするときに、その文字列値を使用することをお勧めします。
    • user_codeでは大文字と小文字が区別されるため、大文字と小文字を変更したり、他の書式設定文字を挿入したりするなど、いかなる方法でも変更しないでください。
  • verification_url
    • verification_urlを表示するスペースは、40文字の長さのURL文字列を処理するのに十分な幅である必要があります。
    • オプションで表示用のスキームを削除する場合を除いて、 verification_urlを変更しないでください。表示上の理由でURLからスキーム( https://など)を削除する予定がある場合は、アプリがhttphttpsの両方のバリアントを処理できることを確認してください。

ステップ4:Googleの認証サーバーをポーリングする

ユーザーは別のデバイスを使用してverification_urlに移動し、アクセスを許可(または拒否)するため、ユーザーがアクセス要求に応答しても、要求元のデバイスは自動的に通知されません。そのため、リクエスト元のデバイスは、ユーザーがリクエストに応答したタイミングを判断するために、Googleの認証サーバーをポーリングする必要があります。

要求元のデバイスは、ユーザーがアクセス要求に応答したことを示す応答を受信するまで、またはステップ2で取得したdevice_codeuser_codeの有効期限が切れるまで、ポーリング要求を送信し続ける必要があります。手順2で返されるintervalは、リクエスト間で待機する時間を秒単位で指定します。

ポーリングするエンドポイントのURLはhttps://oauth2.googleapis.com/tokenです。ポーリング要求には、次のパラメーターが含まれています。

パラメーター
client_idアプリケーションのクライアントID。この値は、 API ConsoleCredentials pageにあります。
client_secret提供されたclient_idのクライアントシークレット。この値は、 API ConsoleCredentials pageにあります。
device_code手順2で認証サーバーから返されたdevice_code
grant_typeこの値をurn:ietf:params:oauth:grant-type:device_codeに設定します。

次のスニペットは、サンプルリクエストを示しています。

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

client_id=client_id&
client_secret=client_secret&
device_code=device_code&
grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code

この例は、同じリクエストを送信するためのcurlコマンドを示しています。

curl -d "client_id=client_id&client_secret=client_secret& \
         device_code=device_code& \
         grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code" \
         -H "Content-Type: application/x-www-form-urlencoded" \
         /token

ステップ5:ユーザーがアクセス要求に応答する

次の画像は、手順3で表示したverification_urlにユーザーが移動したときに表示されるページと同様のページを示しています。

コードを入力してデバイスを接続します

user_codeを入力し、まだログインしていない場合はGoogleにログインすると、次のような同意画面が表示されます。

デバイスクライアントの同意画面の例

ステップ6:ポーリング要求への応答を処理する

Googleの認証サーバーは、次のいずれかの応答で各ポーリング要求に応答します。

アクセスが許可されました

ユーザーが(同意画面で[ Allowをクリックして)デバイスへのアクセスを許可した場合、応答にはアクセストークンと更新トークンが含まれます。トークンを使用すると、デバイスはユーザーに代わってGoogleAPIにアクセスできます。 (応答のscopeプロパティによって、デバイスがアクセスできるAPIが決まります。)

この場合、API応答には次のフィールドが含まれます。

田畑
access_tokenアプリケーションがGoogleAPIリクエストを承認するために送信するトークン。
expires_inアクセストークンの残りの有効期間(秒単位)。
refresh_token新しいアクセストークンを取得するために使用できるトークン。更新トークンは、ユーザーがアクセスを取り消すまで有効です。更新トークンは常にデバイスに対して返されることに注意してください。
scope access_tokenによって付与されるアクセスのスコープは、スペースで区切られた大文字と小文字を区別する文字列のリストとして表されます。
token_type返されるトークンのタイプ。このとき、このフィールドの値は常にBearerに設定されます。

次のスニペットは、サンプルの応答を示しています。

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "scope": "openid https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
  "token_type": "Bearer",
  "refresh_token": "1/xEoDL4iW3cxlI7yDbSRFYNG01kVKM2C-259HOF2aQbI"
}

アクセストークンの有効期間は限られています。アプリケーションが長期間にわたってAPIにアクセスする必要がある場合は、更新トークンを使用して新しいアクセストークンを取得できます。アプリケーションでこのタイプのアクセスが必要な場合は、後で使用できるように更新トークンを保存する必要があります。

アクセス拒否

ユーザーがデバイスへのアクセスを許可することを拒否した場合、サーバーの応答には403 HTTP応答ステータスコード( Forbidden )が含まれます。応答には次のエラーが含まれています。

{
  "error": "access_denied",
  "error_description": "Forbidden"
}

承認待ち

ユーザーがまだ認証フローを完了していない場合、サーバーは428 HTTP応答ステータスコードを返します( Precondition Required )。応答には次のエラーが含まれています。

{
  "error": "authorization_pending",
  "error_description": "Precondition Required"
}

ポーリングが多すぎる

デバイスがポーリング要求を頻繁に送信する場合、サーバーは403 HTTP応答ステータスコード( Forbidden )を返します。応答には次のエラーが含まれています。

{
  "error": "slow_down",
  "error_description": "Forbidden"
}

その他のエラー

ポーリング要求に必要なパラメーターがないか、パラメーター値が正しくない場合にも、許可サーバーはエラーを返します。これらのリクエストには通常、 400Bad Request )または401Unauthorized )のHTTP応答ステータスコードがあります。これらのエラーは次のとおりです。

エラーHTTPステータスコード説明
invalid_client 401 OAuthクライアントが見つかりませんでした。たとえば、このエラーは、 client_idパラメータ値が無効な場合に発生します。
invalid_grant 400 codeパラメータ値が無効です。
unsupported_grant_type 400 grant_typeパラメーター値が無効です。

GoogleAPIの呼び出し

アプリケーションがアクセストークンを取得した後、APIに必要なアクセス範囲が許可されている場合は、トークンを使用して、特定のユーザーアカウントに代わってGoogleAPIを呼び出すことができます。これを行うには、 access_tokenクエリパラメーターまたはAuthorization HTTPヘッダーBearer値のいずれかを含めて、APIへのリクエストにアクセストークンを含めます。クエリ文字列はサーバーログに表示される傾向があるため、可能な場合はHTTPヘッダーを使用することをお勧めします。ほとんどの場合、クライアントライブラリを使用してGoogle APIへの呼び出しを設定できます(たとえば、 Drive Files APIを呼び出す場合)。

OAuth 2.0PlaygroundですべてのGoogleAPIを試して、そのスコープを表示できます。

HTTPGETの例

Authorization: Bearer HTTPヘッダーを使用したdrive.filesエンドポイント(Drive Files API)の呼び出しは、次のようになります。独自のアクセストークンを指定する必要があることに注意してください。

GET /drive/v2/files HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

access_tokenクエリ文字列パラメーターを使用した認証済みユーザーの同じAPIの呼び出しは次のとおりです。

GET https://www.googleapis.com/drive/v2/files?access_token=access_token

curlの例

これらのコマンドは、 curlコマンドラインアプリケーションを使用してテストできます。 HTTPヘッダーオプションを使用する例を次に示します(推奨)。

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/drive/v2/files

または、代わりに、クエリ文字列パラメータオプション:

curl https://www.googleapis.com/drive/v2/files?access_token=access_token

アクセストークンを更新する

アクセストークンは定期的に期限切れになり、関連するAPIリクエストの無効なクレデンシャルになります。トークンに関連付けられたスコープへのオフラインアクセスを要求した場合は、ユーザーに許可を求めるプロンプトを表示せずに(ユーザーが存在しない場合を含めて)アクセストークンを更新できます。

アクセストークンを更新するために、アプリケーションは次のパラメータを含むHTTPS POSTリクエストをGoogleの認証サーバー( https://oauth2.googleapis.com/token )に送信します。

田畑
client_id API Consoleから取得したクライアントID。
client_secret API Consoleから取得したクライアントシークレット。
grant_type OAuth 2.0仕様で定義されているように、このフィールドの値はrefresh_tokenに設定する必要があります。
refresh_token認証コード交換から返された更新トークン。

次のスニペットは、サンプルリクエストを示しています。

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

client_id=your_client_id&
client_secret=your_client_secret&
refresh_token=refresh_token&
grant_type=refresh_token

ユーザーがアプリケーションに付与されたアクセスを取り消していない限り、トークンサーバーは新しいアクセストークンを含むJSONオブジェクトを返します。次のスニペットは、サンプルの応答を示しています。

{
  "access_token": "1/fFAGRNJru1FTz70BzhT3Zg",
  "expires_in": 3920,
  "scope": "https://www.googleapis.com/auth/drive.metadata.readonly",
  "token_type": "Bearer"
}

発行される更新トークンの数には制限があることに注意してください。クライアント/ユーザーの組み合わせごとに1つの制限、およびすべてのクライアントにわたるユーザーごとに別の制限。更新トークンは長期保存に保存し、有効である限り使用し続ける必要があります。アプリケーションが要求する更新トークンが多すぎると、これらの制限に達する可能性があります。その場合、古い更新トークンは機能しなくなります。

トークンを取り消す

場合によっては、ユーザーはアプリケーションに与えられたアクセスを取り消すことができます。ユーザーは、アカウント設定にアクセスしてアクセスを取り消すことができます。詳細については、アカウントサポートドキュメントにアクセスできるサードパーティのサイトとアプリの[サイトまたはアプリへのアクセスの削除]セクションを参照してください。

アプリケーションが、与えられたアクセスをプログラムで取り消すことも可能です。プログラムによる失効は、ユーザーが登録を解除したり、アプリケーションを削除したり、アプリに必要なAPIリソースが大幅に変更されたりした場合に重要です。つまり、削除プロセスの一部にAPIリクエストを含めて、アプリケーションに以前に付与された権限が確実に削除されるようにすることができます。

プログラムでトークンを取り消すには、アプリケーションがhttps://oauth2.googleapis.com/revokeにリクエストを送信し、パラメータとしてトークンを含めます。

curl -d -X -POST --header "Content-type:application/x-www-form-urlencoded" \
        https://oauth2.googleapis.com/revoke?token={token}

トークンは、アクセストークンまたは更新トークンにすることができます。トークンがアクセストークンであり、対応する更新トークンがある場合、更新トークンも取り消されます。

失効が正常に処理された場合、応答のHTTPステータスコードは200です。エラー状態の場合、HTTPステータスコード400がエラーコードとともに返されます。

許可されたスコープ

デバイスのOAuth2.0フローは、次のスコープでのみサポートされます。

OpenID ConnectGoogleサインイン

  • email
  • openid
  • profile

ドライブAPI

  • https://www.googleapis.com/auth/drive.appdata
  • https://www.googleapis.com/auth/drive.file

YouTube API

  • https://www.googleapis.com/auth/youtube
  • https://www.googleapis.com/auth/youtube.readonly