TV および入力制限のあるデバイス アプリケーション用の OAuth 2.0

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

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

このフローを使用するアプリは個々のデバイスに分散されるため、アプリがシークレットを保持できないことを前提としています。ユーザーがアプリを開いているときや、アプリがバックグラウンドで実行されているときに、Google API にアクセスできます。

代替手段

Android、iOS、macOS、Linux、Windows(Universal Windows Platform を含む)などのプラットフォーム用に、ブラウザにアクセスして完全な入力機能を持つアプリを作成する場合は、モバイルおよびデスクトップ アプリケーション用の OAuth 2.0 フローを使用します。(アプリがグラフィカル インターフェースのないコマンドライン ツールであっても、このフローを使用してください)。

Google アカウントでのユーザーのログインのみを行い、JWT ID トークンを使用して基本的なユーザー プロフィール情報を取得する場合は、テレビと制限付き入力デバイスでのログインをご覧ください。

前提条件

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

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

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

  1. Google API Console内のOpen the API Library
  2. If prompted, select a project, or create a new one.
  3. [ライブラリ] ページで YouTube Data API を見つけて有効にします。アプリケーションで使用する他の API を見つけて、それらも有効にします。

承認認証情報を作成する

OAuth 2.0 を使用して Google API にアクセスするアプリケーションには、Google の OAuth 2.0 サーバーに対してアプリケーションを識別するための認証情報が必要です。プロジェクトの認証情報を作成する手順は次のとおりです。これにより、アプリケーションは認証情報を使用して、そのプロジェクトで有効にした API にアクセスできるようになります。

  1. Go to the Credentials page.
  2. [認証情報を作成] > [OAuth クライアント ID] をクリックします。
  3. アプリケーション タイプとして [テレビと入力が制限されているデバイス] を選択します。
  4. OAuth 2.0 クライアントに名前を付けて [作成] をクリックします。

アクセス スコープを特定する

スコープを使用すると、アプリケーションは必要なリソースへのアクセスのみをリクエストできると同時に、ユーザーはアプリケーションに付与するアクセス権の量を制御できるようになります。そのため、リクエストされるスコープの数とユーザーの同意を得る可能性の間には逆の関係になる場合があります。

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

YouTube Data API v3 では、次のスコープを使用します。

スコープ
https://www.googleapis.com/auth/youtubeYouTube アカウントの管理
https://www.googleapis.com/auth/youtube.channel-memberships.creator現在アクティブなチャンネル メンバー、メンバーの現在のレベル、いつメンバーになったかをリストで確認する
https://www.googleapis.com/auth/youtube.force-sslYouTube 動画、評価、コメント、字幕の表示、編集、完全削除
https://www.googleapis.com/auth/youtube.readonlyYouTube アカウントの表示
https://www.googleapis.com/auth/youtube.uploadYouTube 動画の管理
https://www.googleapis.com/auth/youtubepartnerYouTube のアセットや関連するコンテンツの表示と管理
https://www.googleapis.com/auth/youtubepartner-channel-auditYouTube パートナーの監査プロセス時に関連する YouTube チャンネルの個人情報の表示

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

OAuth 2.0 アクセス トークンの取得

入力機能が制限されたデバイス上でアプリが動作していても、この承認フローを完了するには、入力機能が豊富なデバイスにユーザーが別途アクセスする必要があります。このフローは次のステップで構成されます。

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

次の図に、このプロセスを示します。

ブラウザを備えた別のデバイスでユーザーがログインする

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

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

このステップでは、デバイスから Google の承認サーバー(https://oauth2.googleapis.com/device/code)に HTTP POST リクエストを送信します。これにより、アプリケーションだけでなく、アプリケーションがユーザーの代わりにアクセスする必要のあるアクセス スコープも特定されます。この URL は、device_authorization_endpoint メタデータ値を使用して、ディスカバリ ドキュメントから取得する必要があります。次の HTTP リクエスト パラメータを含めます。

パラメータ
client_id 必須

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

scope 必須

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

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

YouTube Data API v3 では、次のスコープを使用します。

スコープ
https://www.googleapis.com/auth/youtubeYouTube アカウントの管理
https://www.googleapis.com/auth/youtube.channel-memberships.creator現在アクティブなチャンネル メンバー、メンバーの現在のレベル、いつメンバーになったかをリストで確認する
https://www.googleapis.com/auth/youtube.force-sslYouTube 動画、評価、コメント、字幕の表示、編集、完全削除
https://www.googleapis.com/auth/youtube.readonlyYouTube アカウントの表示
https://www.googleapis.com/auth/youtube.uploadYouTube 動画の管理
https://www.googleapis.com/auth/youtubepartnerYouTube のアセットや関連するコンテンツの表示と管理
https://www.googleapis.com/auth/youtubepartner-channel-auditYouTube パートナーの監査プロセス時に関連する YouTube チャンネルの個人情報の表示

Google API へのアクセスに使用できるスコープの一覧については、OAuth 2.0 API スコープのドキュメントをご覧ください。

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

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

client_id=client_id&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.force-ssl

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

curl -d "client_id=client_id&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fyoutube.force-ssl" \
     https://oauth2.googleapis.com/device/code

ステップ 2: 認可サーバーのレスポンスを処理する

認可サーバーは次のいずれかのレスポンスを返します。

成功のレスポンス

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

プロパティ
device_code 承認をリクエストしているアプリを実行するデバイスを識別するために Google が一意に割り当てる値。ユーザーは、豊富な入力機能を備えた別のデバイスからそのデバイスを承認します。たとえば、ユーザーがノートパソコンやスマートフォンを使用して、テレビで動作しているアプリを承認します。この場合、device_code がテレビを識別します。

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

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:// など)を削除する場合は、アプリが http バリアントと https バリアントの両方を処理できることを確認してください。

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

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

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

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

パラメータ
client_id アプリケーションのクライアント ID。この値は API Console Credentials pageにあります。
client_secret 指定された client_id のクライアント シークレット。この値は API Console Credentials 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" \
         https://oauth2.googleapis.com/token

ステップ 5: ユーザーがアクセス リクエストに応答する

次の図は、ステップ 3 で表示された verification_url に移動したときにユーザーに表示されるのと同様のページを示しています。

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

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

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

ステップ 6: ポーリング リクエストへのレスポンスを処理する

Google の承認サーバーは、各ポーリング リクエストに対して次のいずれかのレスポンスを返します。

アクセスを許可しました

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

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

フィールド
access_token Google API リクエストを承認するためにアプリケーションが送信するトークン。
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 Status Code 説明
admin_policy_enforced 400 Google Workspace 管理者のポリシーにより、Google アカウントでリクエストされた 1 つ以上のスコープを承認できません。OAuth クライアント ID にアクセス権が明示的に付与されるまで、管理者がスコープへのアクセスを制限する方法の詳細については、Google Workspace 管理者用ヘルプ記事の Google Workspace のデータにアクセスできるサードパーティ製アプリと内部アプリを制御するをご覧ください。
invalid_client 401

OAuth クライアントが見つかりませんでした。たとえば、このエラーは client_id パラメータ値が無効な場合に発生します。

OAuth クライアント タイプが正しくありません。クライアント ID のアプリケーション タイプが [TV and Limited Input devices] に設定されていることを確認します。

invalid_grant 400 code パラメータの値が無効であるか、すでに申請されているか、解析できません。
unsupported_grant_type 400 grant_type パラメータ値が無効です。
org_internal 403 リクエスト内の OAuth クライアント ID は、特定の Google Cloud 組織の Google アカウントへのアクセスを制限するプロジェクトの一部です。OAuth アプリケーションのユーザータイプの構成を確認します。

Google API の呼び出し

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

YouTube Live Streaming API は、サービス アカウントのフローをサポートしていません。サービス アカウントを YouTube アカウントにリンクする方法はないため、このフローでリクエストを承認しようとすると、NoLinkedYouTubeAccount エラーが発生します。

OAuth 2.0 Playground ですべての Google API を試し、スコープを確認できます。

HTTP GET の例

Authorization: Bearer HTTP ヘッダーを使用した liveBroadcasts.list エンドポイント(YouTube Live Streaming API)への呼び出しは次のようになります。独自のアクセス トークンを指定する必要があります。

GET /youtube/v3/liveBroadcasts?part=id%2Csnippet&mine=true HTTP/1.1
Host: www.googleapis.com
Authorization: Bearer access_token

access_token クエリ文字列パラメータを使用した、認証されたユーザーに対して同じ API の呼び出しの例を次に示します。

GET https://www.googleapis.com/youtube/v3/liveBroadcasts?access_token=access_token&part=id%2Csnippet&mine=true

curl の例

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

curl -H "Authorization: Bearer access_token" https://www.googleapis.com/youtube/v3/liveBroadcasts?part=id%2Csnippet&mine=true

または、クエリ文字列パラメータ オプションを使用します。

curl https://www.googleapis.com/youtube/v3/liveBroadcasts?access_token=access_token&part=id%2Csnippet&mine=true

アクセス トークンをリフレッシュする

アクセス トークンは定期的に期限切れになり、関連する 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 つ、すべてのクライアントでユーザーごとに 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 がエラーコードとともに返されます。

許可されるスコープ

デバイスの OAuth 2.0 フローは、次のスコープでのみサポートされています。

OpenID ConnectGoogle ログイン

  • email
  • openid
  • profile

Drive 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