Data Plan Agent API 向けの OAuth

OAuth 2.0 は RFC 6749 として標準化されています。詳細は、https://oauth.net/2 をご覧ください。HTTP 基本認証は RFC 2617 のセクション 2 で定義されています。

概要

通常、サードパーティ アプリケーションにデータプランやウォレットの詳細などの制限付きリソースへのアクセス権を付与するには、エンドユーザー(リソース所有者)がサードパーティと認証情報を共有する必要があります。これにより、認証情報ストレージ、パスワード認証、エンドユーザーのリソースへの幅広いアクセス、パスワード漏洩など、いくつかの問題や制限が生じます。OAuth2.0 では、認証レイヤを導入することで、エンドユーザーの保護されるリソースへのアクセスを保護し、制限することで、これらの問題に対処しています。

GTAF は、エンドユーザーの認証情報を使用して、データプランの詳細などの保護されたリソースにアクセスする代わりに、アクセス トークンを取得します。アクセス トークンは、GTAF の認証情報の代わりに GTAF に対して発行されます。GTAF はアクセス トークンを使用して、DPA がホストするデータプランの詳細にアクセスします。

次の図は、情報の大まかな流れを示しています。

図 1. OAuth フローの抽象化

アクセス トークン

アクセス トークンは、携帯通信会社の DPA からデータプランの詳細にアクセスするために GTAF が使用する認証情報です。アクセス トークンは、GTAF に発行された承認を表す文字列です。通常、文字列は GTAF に対して不透明です。トークンは、特定のスコープとアクセス期間を表します。これは、エンドユーザーから携帯通信会社に付与され、DPA と携帯通信会社の OAuth サーバーによって適用されます。

アクセス トークンは抽象化レイヤを提供し、さまざまな認証構成(ユーザー名とパスワードなど)を DPA が理解する単一のトークンに置き換えます。この抽象化により、アクセス トークンの取得に使用する承認付与よりも制限の厳しいアクセス トークンを発行することや、さまざまな認証方法を理解する必要がある DPA を削除することが可能になります。

アクセス トークンには、携帯通信会社のセキュリティ要件に基づいて、さまざまな形式、構造、使用方法(暗号プロパティなど)があります。 GTAF は、[RFC6750] で定義された署名なし型アクセス トークンのみをサポートしています。

クライアント認証

GTAF は「機密クライアント」として機能し、パスワードを安全に保護します。GTAF は現在、DPA で認証するための HTTP Basic 認証のみをサポートしています。クライアント ID は「application/x-www-form-urlencoded"」エンコード アルゴリズムでエンコードされ、エンコードされた値がユーザー名として使用されます。パスワードは同じアルゴリズムでエンコードされ、パスワードとして使用されます。

クライアント認証情報を発行する GTAF などの機密性の高いクライアントは、トークン エンドポイントにリクエストを送信しながら、携帯通信会社の OAuth サーバーで認証を行います。クライアント認証は次の目的で使用されます: \

  • 不正使用されたクライアントからクライアントを無効にするか、その認証情報を変更して、攻撃者が盗まれた更新トークンを悪用するのを防ぎます。一連のクライアント トークンを変更するほうが、更新トークン全体を取り消すよりもはるかに高速です。
  • 認証管理のベスト プラクティスを実装する。定期的な認証情報のローテーションが必要。

GTAF は、>client_id" リクエスト パラメータを使用して、トークン エンドポイントにリクエストを送信するときに自身を識別します。

特に重要なのは、クライアント認証情報をローテーションできる機能です。OAuth サーバーは、ローテーション中に 2 つの認証情報ペアを同時にサポートできる必要があり、また認証情報を無効にできる必要があります。一般的な認証情報のローテーションでは、次のようになります。

  1. 携帯通信会社は、OAuth サーバーに新しい認証情報を作成し、その技術アカウントを安全な方法でテクニカル アカウント マネージャーに配信します。
  2. Google は新しい認証情報をテストし、新しい認証情報を使用するように GTAF 構成を変更します。
  3. Google は、古い認証情報が無効になる可能性があることを携帯通信会社に通知します。
  4. 携帯通信会社が認証情報を無効にして Google に通知する
  5. Google が古い認証情報を使用できなくなったことを確認

OAuth サーバーで、上記のローテーション プロセスがサポートされている必要があります。

トークン エンドポイント

トークン エンドポイントは、GTAF により、認証トークンまたは更新トークンを提示してアクセス トークンを取得するために使用されます。トークン エンドポイントは、暗黙的権限付与タイプを除くすべての承認権限付与で使用されます(アクセス トークンは直接発行されるため)。

トークン エンドポイントを構成する際に考慮すべきポイントがいくつかあります。

  • トークン エンドポイントの場所は、サービスのドキュメントで指定する必要があります。
  • エンドポイント URI にはクエリ アプリケーションを追加するときに保持する必要がある「application/x-www-form-urlencoded"」形式のクエリ コンポーネントが含まれる場合があります。エンドポイント URI には、フラグメント コンポーネントを含めないでください。
  • トークン エンドポイントへのリクエストにより、HTTP リクエストとレスポンスでクリアテキストの認証情報が送信されるため、携帯通信会社の OAuth サーバーはトークン エンドポイントにリクエストを送信するときに TLS を使用する必要があります。
  • GTAF は、アクセス トークンのリクエスト時に HTTP の「POST」メソッドを使用します。
  • 値なしで送信されるパラメータは、リクエストから省略されたものとして扱う必要があります。OAuth サーバーで、認識できないリクエスト パラメータは無視されます。リクエスト パラメータとレスポンス パラメータを複数回含めることはできません。
  • GTAF は、署名なし型アクセス トークンのみをサポートしています。

アクセス トークンのスコープ

承認エンドポイントとトークン エンドポイントを使用すると、クライアントは「スコープ」リクエスト パラメータを使用してアクセス リクエストのスコープを指定できます。次に、認可サーバーは「scope」レスポンス パラメータを使用して、発行されたアクセス トークンのスコープをクライアントに通知します。

scope パラメータの値は、スペースで区切られた大文字と小文字を区別する文字列のリストとして表されます。文字列は認証サーバーによって定義されます。値にスペースで区切られた複数の文字列が含まれている場合、それらの順序は重要ではなく、各文字列は要求されたスコープに別のアクセス範囲を追加します。

 scope = scope-token *( SP scope-token )
 scope-token = 1*( %x21 / %x23-5B / %x5D-7E )

GTAF はスコープの実装を必要としませんが、この機能をサポートしています。詳細については、RFC 6749セクション 3.3 をご覧ください。

アクセス トークンの発行

GTAF によって送信されたアクセス トークン リクエストが有効で承認済みである場合、OAuth サーバーはアクセス トークンと任意の更新トークンを発行します。リクエストがクライアント認証に失敗するか無効な場合、次のセクションで説明するように OAuth サーバーはエラー レスポンスを返します。

成功したレスポンス

GTAF がリクエストを送信すると、OAuth サーバーはアクセス トークンと任意の更新トークンを発行し、200(OK)ステータス コードで HTTP レスポンスのエンティティ本文に次のパラメータを追加してレスポンスを作成します。 \

  • access_token: 必須。OAuth サーバーによって発行されたアクセス トークン。GTAF では、トークン エンドポイントが署名なしトークンを返すことを想定しています。
  • expires_in: 必須。アクセス トークンの有効期間(秒単位)。たとえば、値 3600 は、アクセス トークンがレスポンスの生成から 1 時間で期限切れになります。省略した場合は、OAuth サーバーで他の方法で有効期限を指定するか、デフォルト値を文書化します。
  • token_type: 必須。発行されたトークンのタイプ。さまざまな種類のトークンの詳細については、RFC 6749セクション 7.1 をご覧ください。この値では大文字と小文字が区別されません。GTAF は、この記事の執筆時点で署名されていないトークンのみをサポートしています。
  • refresh_token: 省略可。更新トークン。同じ権限付与を使用して新しいアクセス トークンを取得できます。
  • スコープ: 任意。実装され、GTAF で要求されたスコープと同一。それ以外の場合は必須。

パラメータは、HTTP レスポンスのエンティティ本体に "application/json" を使用して含まれています。パラメータは、各パラメータを最上位の構造レベルで追加することで、JavaScript Object Notation(JSON)構造にシリアル化されます。パラメータ名と文字列値は JSON 文字列として含まれます。数値は JSON 数値として含まれます。パラメータの順序は重要ではなく、さまざまです。

認可サーバーは、トークン、認証情報、その他の機密情報を含むレスポンスに、HTTP の「Cache-Control」レスポンス ヘッダー フィールド、および値に「no-cache」が含まれている必要があります。

例:

     HTTP/1.1 200 OK
     Content-Type: application/json;charset=UTF-8
     Cache-Control: no-store
     Pragma: no-cache

     {
       "access_token":"2YotnFZFEjr1zCsicMWpAA",
       "token_type":"Bearer",
       "expires_in":3600,
       "refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
       "example_parameter":"example_value"
     }


留意点は以下のとおりです。

  • GTAF は、レスポンス内の認識されない値名を無視します。
  • OAuth サーバーから受信したトークンや他の値のサイズは未定義のままです。
  • GTAF では、値のサイズを推測しないでください。OAuth サーバーは、発行する値のサイズを記録する必要があります。

エラー レスポンス

リダイレクト URI が欠落している、無効である、または一致しないなどの理由で承認リクエストが失敗した場合、またはクライアント ID が存在しないか無効である場合、OAuth サーバーは HTTP 400(Bad Request)ステータス コード(特に指定のない限り)で応答し、エラー レスポンスとコードのセクションに記載されているパラメータを 1 つ以上含める必要があります。

GTAF での承認

認証権限付与は、アクセス トークンの取得のために GTAF が使用する、エンドユーザーの承認(データ残高情報などの保護されたリソースにアクセス)を表す認証情報です。

GTAF は、client_credentials 権限付与タイプを使用します。client_credentials 権限付与タイプでは、GTAF は HTTP POST リクエストと HTTP 基本認証を使用してトークンをリクエストします。すべてのリクエストは TLS を介して送信されます(つまり、HTTPS など)と有効な TLS 証明書がないと、GTAF は OAuth サーバーと統合できません。GTAF は、構成可能なトークン スコープを渡すことができます。構成されていないトークン スコープは、渡されます。

GTAF は、アクセス トークンが「expires_in」の値(有効期間)とともに返されることを想定しています。expires_in の値は 900 秒以上、数時間以内でなければなりません。新しいトークンをリクエストしても、既存のトークンが期限切れにならないようにしてください。

さまざまな権限付与タイプの詳細については、RFC 6749セクション 1.3 をご覧ください。

リクエストとレスポンスの例

GTAF が OAuth サーバー用に次の構成を行っているとします。

URL: https://www.example.com/gettoken/
Client ID: gtaf
Client secret: password
Scope: dpa

注: 実際の DPA のクライアント シークレットは、ここに示したものよりもはるかに安全である必要があります。

認証文字列を生成するために、クライアント ID、':'、パスワードは連結され、Base64 でエンコードされます。これは、次のようにコマンドライン インターフェースで複製できます。

$ echo -n gtaf:password | base64
Z3RhZjpwYXNzd29yZA==

GTAF は、これらの認証情報、client_credentials 権限付与タイプ、構成されたスコープを使用して、OAuth サーバーに対して HTTPS POST リクエストを行います。たとえば、GTAF のリクエストは、以下によって生成されるリクエストに似ています。

$ curl -H 'Authorization: Basic Z3RhZjpwYXNzd29yZA==' -X POST \
-d 'grant_type=client_credentials&scope=dpa' 'https://www.example.com/gettoken/'

GTAF で使用されるヘッダーは、curl によって送信されるヘッダーと一致しませんが、認証ヘッダーは同じです。

GTAF は、以下の形式の回答を期待しています。

{
"access_token":"<token>",
"token_type": "Bearer",
"expires_in":<expiration time>
}

有効なレスポンスの例を次に示します。

{
"access_token":"YXRudWhhZXVoLGFodWFoaGF1aG9zaHVvYWV1Cg",
"token_type": "Bearer",
"expires_in":3600
}

注: レスポンスは有効な JSON である必要があります。

エラー レスポンスとコード

[エラー レスポンス] セクションで説明されている理由により、GTAF からの認証リクエストが失敗した場合は、OAuth サーバーは HTTP 400(Bad Request)ステータス コード(特に指定のない限り)で応答し、レスポンスに次のいずれかのパラメータを含める必要があります。

例: \

     HTTP/1.1 400 Bad Request
     Content-Type: application/json;charset=UTF-8
     Cache-Control: no-store
     Pragma: no-cache

     {
       "error":"invalid_request"
     }

GTAF は、OAuth サーバーが次のエラー レスポンスをサポートすることを想定しています。

エラーコード レスポンス 理由
HTTP 400 invalid_request リクエストに必須パラメータがない、サポート対象外のパラメータ値が含まれている(権限付与タイプを除く)、パラメータの繰り返し、複数の認証情報を含む、GTAF での認証に複数のメカニズムを利用する、または他の形式が正しくない場合。
HTTP 401 Invalid_client クライアント認証が失敗しました(不明なクライアント、クライアント認証が含まれていない、または認証方法がサポートされていないなど)。OAuth サーバーから HTTP 401(未承認)ステータス コードが返され、サポートされている HTTP 認証スキームを示すことができます。クライアントが「承認」リクエスト ヘッダー フィールドを介して認証を試みた場合、OAuth サーバーは HTTP 401(未承認)のステータス コードで応答し、クライアントが使用する認証スキームに一致する「WWW-Authenticate」認証ヘッダー フィールドを含める必要があります。
HTTP 500 OAuth サーバー障害

デバッグに使用できるその他のレスポンスの詳細については、RFC 6749セクション 5.2 をご覧ください。