このドキュメントでは、テレビ、ゲーム機、プリンタなどのデバイスで実行されるアプリを介して Google API にアクセスするための OAuth 2.0 認可を実装する方法について説明します。具体的には、このフローは、ブラウザにアクセスできないデバイス、または入力機能が制限されているデバイスを対象としています。
OAuth 2.0 では、ユーザー名やパスワードなどの情報を秘密にしたまま、ユーザーが特定のデータをアプリケーションと共有できます。たとえば、テレビ アプリケーションは OAuth 2.0 を使用して、Google ドライブに保存されているファイルを選択する権限を取得できます。
このフローを使用するアプリケーションは個々のデバイスに配布されるため、アプリは秘密を保持できないと想定されます。ユーザーがアプリを使用している間や、アプリがバックグラウンドで実行されているときに、Google API にアクセスできます。
代替手段
Android、iOS、macOS、Linux、Windows(ユニバーサル Windows プラットフォームを含む)などのプラットフォーム向けに、ブラウザと完全な入力機能にアクセスできるアプリを作成している場合は、モバイルアプリとデスクトップ アプリ用の OAuth 2.0 フローを使用します。(アプリがグラフィカル インターフェースのないコマンドライン ツールであっても、このフローを使用する必要があります)。
ユーザーが Google アカウントでログインし、JWT ID トークンを使用して基本的なユーザー プロフィール情報を取得するのみの場合は、テレビと入力制限のあるデバイスでのログインをご覧ください。
前提条件
プロジェクトでAPI を有効にする
Google API を呼び出すアプリケーションは、 でこれらの API を有効にする必要があります。
プロジェクトで API を有効にするには:
- の 。
- には、利用可能なすべての API がプロダクト ファミリーと人気度に応じて分類されて表示されます。有効にする API がリストで見当たらない場合は、検索して見つけるか、その API が属するプロダクト ファミリーの [すべて表示] をクリックします。
- 有効にする API を選択し、[有効にする] ボタンをクリックします。
承認認証情報を作成する
OAuth 2.0 を使用して Google API にアクセスするアプリケーションは、Google の OAuth 2.0 サーバーに対して自身の身元を示す認証情報を持つ必要があります。次の手順では、プロジェクトの認証情報を作成する方法について説明します。アプリケーションは、その認証情報を使用して、そのプロジェクトで有効にした API にアクセスできます。
- [認証情報を作成] > [OAuth クライアント ID] をクリックします。
- アプリケーションの種類として [テレビと入力が限られたデバイス] を選択します。
- OAuth 2.0 クライアントに名前を付けて、[作成] をクリックします。
アクセス スコープを特定する
スコープを指定すると、アプリケーションからのアクセス要求は必要なリソースのみに限定されるようになり、ユーザーはアプリケーションに付与するアクセスレベルを制御できます。そのため、リクエストするスコープの数とユーザーの同意を得られる可能性との間には逆相関関係がある可能性があります。
OAuth 2.0 認証の実装を開始する前に、アプリがアクセス権限を必要とするスコープを設定しておくことをおすすめします。
インストールされているアプリまたはデバイスの許可されたスコープのリストをご覧ください。
OAuth 2.0 アクセス トークンの取得
入力機能が制限されているデバイスでアプリケーションが実行されている場合でも、この認可フローを完了するには、ユーザーが入力機能が豊富なデバイスに別途アクセスできる必要があります。フローの手順は次のとおりです。
- アプリケーションは、アプリケーションがアクセス権をリクエストするスコープを識別するリクエストを Google の認可サーバーに送信します。
- サーバーは、後続のステップで使用されるデバイスコードやユーザーコードなどの情報を返します。
- ユーザーが別のデバイスで入力してアプリを承認できる情報を表示します。
- アプリは Google の認可サーバーをポーリングし、ユーザーがアプリを承認したかどうかを判断します。
- ユーザーは、入力機能が豊富なデバイスに切り替え、ウェブブラウザを起動して、ステップ 3 に表示された URL に移動し、ステップ 3 にも表示されたコードを入力します。ユーザーはアプリケーションへのアクセス権を付与(または拒否)できます。
- ポーリング リクエストに対する次のレスポンスには、ユーザーに代わってリクエストを承認するためにアプリが必要とするトークンが含まれています。(ユーザーがアプリへのアクセスを拒否した場合、レスポンスにはトークンが含まれません)。
次の図は、このプロセスを示しています。
以降のセクションでは、これらの手順について詳しく説明します。デバイスに搭載されている機能とランタイム環境の範囲を考慮して、このドキュメントの例では curl
コマンドライン ユーティリティを使用しています。これらのサンプルは、さまざまな言語やランタイムに簡単に移植できます。
ステップ 1: デバイスコードとユーザーコードをリクエストする
このステップでは、デバイスが Google の認可サーバーに HTTP POST リクエストを送信します。このリクエストには、アプリと、アプリがユーザーに代わってアクセスするアクセス スコープが含まれます。https://oauth2.googleapis.com/device/code
この URL は、device_authorization_endpoint
メタデータ値を使用してディスカバリ ドキュメントから取得する必要があります。次の HTTP リクエスト パラメータを含めます。
パラメータ | |
---|---|
client_id |
必須
アプリケーションのクライアント ID。この値は、 にあります。 |
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 はテレビを識別します。
このコードにより、アプリを実行しているデバイスは、ユーザーがアクセスを許可したかどうかを安全に判断できます。 |
expires_in |
device_code と user_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_url
と user_code
をユーザーに表示します。どちらの値にも、US-ASCII 文字セットの印刷可能な文字を含めることができます。ユーザーに表示するコンテンツには、別のデバイスで verification_url
に移動して user_code
を入力するよう指示する必要があります。
ユーザー インターフェース(UI)を設計する際は、次のルールを念頭に置いてください。
user_code
user_code
は、15 個の「W」サイズの文字を処理できるフィールドに表示する必要があります。つまり、コードWWWWWWWWWWWWWWW
を正しく表示できる場合、UI は有効です。UI にuser_code
を表示する方法のテストでは、その文字列値を使用することをおすすめします。user_code
では大文字と小文字が区別されるため、大文字と小文字の変更や他の書式文字の挿入など、いかなる方法でも変更しないでください。
verification_url
verification_url
を表示するスペースは、40 文字の URL 文字列を処理できるだけの幅が必要です。verification_url
は、表示用のスキーマを必要に応じて削除する場合を除き、いかなる方法でも変更しないでください。表示上の理由で URL からスキーム(https://
など)を削除する場合は、アプリがhttp
とhttps
の両方のバリエーションを処理できることを確認してください。
ステップ 4: Google の認可サーバーをポーリングする
ユーザーは別のデバイスを使用して verification_url
に移動し、アクセスを許可(または拒否)するため、ユーザーがアクセス リクエストに応答しても、リクエスト元のデバイスには自動的に通知されません。そのため、リクエスト元のデバイスは、Google の認可サーバーをポーリングして、ユーザーがリクエストに応答したタイミングを判断する必要があります。
リクエスト元のデバイスは、ユーザーがアクセス リクエストに応答したことを示すレスポンスを受信するか、
ステップ 2 で取得した device_code
と user_code
が期限切れになるまで、ポーリング リクエストの送信を続けます。ステップ 2 で返された interval
には、リクエスト間の待機時間を秒単位で指定します。
ポーリングするエンドポイントの URL は https://oauth2.googleapis.com/token
です。ポーリング リクエストには、次のパラメータが含まれます。
パラメータ | |
---|---|
client_id |
アプリケーションのクライアント ID。この値は、 にあります。 |
client_secret |
指定された client_id のクライアント シークレット。この値は、
にあります。 |
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" }
その他のエラー
また、ポーリング リクエストに必須パラメータが含まれていない場合や、パラメータ値が正しくない場合には、認可サーバーはエラーを返します。通常、これらのリクエストには 400
(Bad Request
)または 401
(Unauthorized
)の HTTP レスポンス ステータス コードが付いています。たとえば次のようなエラーです。
エラー | HTTP ステータス コード | 説明 |
---|---|---|
admin_policy_enforced |
400 |
Google Workspace 管理者のポリシーにより、リクエストされた 1 つ以上のスコープを Google アカウントが承認できません。OAuth クライアント ID にアクセスが明示的に付与されるまで、管理者がスコープへのアクセスを制限する方法については、Google Workspace 管理者向けヘルプ記事の Google Workspace のデータにアクセスできるサードパーティ製アプリと内部アプリを制御するをご覧ください。 |
invalid_client |
401 |
OAuth クライアントが見つかりません。たとえば、 OAuth クライアントの種類が正しくありません。クライアント ID のアプリケーション タイプが [テレビと入力機能が制限されたデバイス] に設定されていることを確認します。 |
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 への呼び出しを設定できます(Drive Files API を呼び出す場合など)。
すべての Google API を試して、そのスコープを確認するには、OAuth 2.0 Playground をご覧ください。
HTTP GET の例
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 リクエストに対して無効な認証情報になります。トークンに関連付けられたスコープへのオフライン アクセスをリクエストした場合は、ユーザーに権限を求めることなくアクセス トークンを更新できます(ユーザーが不在の場合を含めて)。
アクセス トークンを更新するには、アプリケーションが Google の認可サーバーに HTTPS POST
リクエストを送信します。このリクエストには、次のパラメータが含まれます。https://oauth2.googleapis.com/token
フィールド | |
---|---|
client_id |
から取得したクライアント ID。 |
client_secret |
から取得したクライアント シークレット。 |
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 https://www.googleapis.com/auth/calendar.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 Connect、Google ログイン
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
クロスアカウント保護機能の実装
ユーザーのアカウントを保護するために、Google のクロスアカウント保護サービスを利用したクロスアカウント保護を実装することもおすすめします。このサービスを使用すると、セキュリティ イベント通知を定期購読して、ユーザー アカウントの大きな変更に関する情報をアプリに提供できます。その後、イベントへの対応方法に応じて、この情報に基づいてアクションを実行できます。
Google のクロスアカウント保護サービスからアプリに送信されるイベントの種類には、次のものがあります。
-
https://schemas.openid.net/secevent/risc/event-type/sessions-revoked
-
https://schemas.openid.net/secevent/oauth/event-type/token-revoked
-
https://schemas.openid.net/secevent/risc/event-type/account-disabled
クロスアカウント保護の実装方法と利用可能なイベントの一覧については、 クロスアカウント保護でユーザー アカウントを保護する をご覧ください。