サードパーティ OAuth トークンの使用

このトピックでは、外部で生成されたアクセス トークン、リフレッシュ トークン、または認証コードを Edge トークンストアにインポートする方法について説明します。この方法は、Apigee Edge の外部で生成されたトークンを検証するよう Apigee Edge を構成する場合に使用できます。

通常、Apigee Edge は OAuth トークンを生成して保管し、そのトークンを呼び出し元アプリケーションに返します。その後、呼び出し元アプリケーションはサービスをリクエストする際に、そのトークンを Apigee Edge に提示します。Apigee Edge は、提示されたトークンが有効であることを(VerifyAccessToken オペレーションが設定された OAuthV2 ポリシーを使用して)検証します。このトピックでは、外部で生成された OAuth トークンを保管するように Apigee Edge を構成する一方で、トークンを検証する部分は Edge で生成されたトークンを検証する場合と同じように行われるようにする方法を説明します。

このトピックで説明する手法を示す実用例については、Apigee Delegated Token Management のサンプルをご覧ください。

概要

たとえば、既存の認可システムが整っていて、Edge で生成される OAuth2 トークンやコードの値の代わりに、その既存のシステムで生成されたトークンまたはコードの値を使用したいとします。その場合、代わりとなるトークンまたはコードを使用してセキュアな API プロキシ リクエストを行い、Edge に自身が生成したトークンまたはコードであるかのように検証させることが可能です。

背景

通常、Apigee Edge は文字と数字からなるランダムな文字列を生成して、トークンを生成します。Apigee Edge はそのトークンに他のデータ(トークンが発行された時刻、トークンの有効期限、トークンが有効な API プロダクトのリスト、スコープなど)を関連付けます。これらの情報すべてが、GenerateAccessToken オペレーションを設定して構成された OAuthV2 ポリシーによって、自動的にレスポンスに取り込まれて返されます。レスポンスは次のようになります。

{
  "issued_at": "1469735625687",
  "application_name": "06947a86-919e-4ca3-ac72-036723b18231",
  "scope": "urn://example.com/read",
  "status": "approved",
  "api_product_list": "[implicit-test]",
  "api_product_list_json": ["implicit-test"],
  "expires_in": "1799", //--in seconds
  "developer.email": "joe@weathersample.com",
  "token_type": "BearerToken",
  "client_id": "U9AC66e9YFyI1yqaXgUF8H6b9wUN1TLk",
  "access_token": "zBC90HhCGmGlaMBWeZAai2s3za5j",
  "organization_name": "wwitman",
  "refresh_token_expires_in": "0", //--in seconds
  "refresh_count": "0"
}

access_token 属性の値は、実質的にこのメタデータの他のすべてのデータの検索キーになります。あるアプリが Edge でホストされている API プロキシにリクエストを送信し、署名なしトークン zBC90HhCGmGlaMBWeZAai2s3za5j を伝達するとします。この場合、Edge は、VerifyAccessToken オペレーションが設定された OAuthV2 ポリシーを使用してトークンを検索し、すべての情報を取得して、この情報を使用してリクエストされた API プロキシに対しトークンが有効か否かを判断します。これをトークン検証と呼びます。トークンは、上記のすべての情報で構成されます。access_token の値は、それらの情報を調べる手段にすぎません。

一方、ここで説明する手順に従うと、トークンを保存してその access_token 値が外部サービスにより生成された値となるよう、Edge を構成できます。その他すべてのメタデータは同じである可能性があります。たとえば、「トークン - 16 個の乱数」という形式のトークンを生成する Apigee Edge の外部にシステムがあるとします。この場合、Apigee Edge が保管する完全なトークン メタデータは次のようになります。

{
  "issued_at": "1469735625687",
  "application_name": "06947a86-919e-4ca3-ac72-036723b18231",
  "scope": "urn://example.com/read",
  "status": "approved",
  "api_product_list": "[implicit-test]",
  "api_product_list_json": ["implicit-test"],
  "expires_in": "1799", //--in seconds
  "developer.email": "joe@weathersample.com",
  "token_type": "BearerToken",
  "client_id": "U9AC66e9YFyI1yqaXgUF8H6b9wUN1TLk",
  "access_token": "TOKEN-1092837373654221",
  "organization_name": "wwitman",
  "refresh_token_expires_in": "0", //--in seconds
  "refresh_count": "0"
}

この場合、あるアプリが Edge にホストされた API プロキシに対しリクエストを行い、署名なしトークン TOKEN-1092837373654221 を伝達する場合があり、Edge は、VerifyAccessToken オペレーションが設定された OAuthV2 ポリシーを使用してトークンを検証できるようになります。認証コードとフレッシュ トークンにも、これと同様のインポート パターンを適用できます。

クライアント認証情報の検証について

トークンを生成する際の 1 つの前提条件として、リクエスト側クライアントを検証する必要があります。デフォルトでは、Apigee Edge に含まれる OAuthV2/GenerateAccessToken ポリシーは明示的にクライアント認証情報を検証します。通常、OAuthV2 トークンのリクエストでは、client_id と client_secret を含めた Authorization ヘッダーを HTTP 基本認証でエンコードして渡します(コロンで連結してから base64 でエンコードされます)。Apigee Edge に含まれる OAuthV2/GenerateAccessToken ポリシーがこのヘッダーをデコードして client_id を調べ、渡された client_secret に対してその client_id が有効なものであるかどうか検証します。このプロセスが有効なのは、Apigee Edge が認証情報を把握している場合、つまりデベロッパー アプリが保管されている Apigee Edge に認証情報が含まれていて、その認証情報自体に該当する client_id と client_secret が含まれている場合です。

クライアント認証情報が Apigee Edge で検証されない場合は、API プロキシがトークンを生成する前に、なんらかの手段でクライアントを検証するように設計する必要があります。多くの場合、これには、ネットワーク内のリモート エンドポイントに接続する ServiceCallout ポリシーを使用します。

明示的か暗黙的かのどちらにしても、トークンを生成する API プロキシが最初にクライアント認証情報を検証するようにする必要があります。注意する点として、クライアントの検証は、アクセス トークンの生成とは無関係です。この 2 つを両方とも行うように Apigee Edge を構成することも、いずれか、またはどちらも行わないように構成することもできます。

Apigee Edge の OAuthV2 ポリシーか GenerateAccessToken ポリシーを使用して Edge ストアとの比較でクライアント認証情報を検証する場合は、ポリシー設定内で <ExternalAuthorization> 要素を false に構成するか、完全に省略します。外部認証サービスを使用してクライアント認証情報を明示的に検証する場合は、<ExternalAuthorization>true に設定します。

Apigee Edge でクライアント認証情報を検証しないとしても、Apigee Edge が client_id を把握して管理する必要があります。Apigee Edge 内のすべての access_token は、Apigee Edge で生成される場合も、外部システムで生成して Apigee Edge にインポートする場合も、client_id で識別されるクライアント アプリケーションに関連付けられていなければなりません。したがって、Apigee Edge 内の OAuthV2/GenerateAccessToken ポリシーが client_id と client_secret の一致を検証するかどうかを問わず、このポリシーは有効な client_id が存在し、取り消されていないことを検証します。つまり、前提条件をセットアップするステップとして、Edge 管理 API を使用して client_id をインポートしなければならない場合があります。

サードパーティ OAuth の場合の Apigee でのポリシーフロー

サードパーティ OAuth システムで生成されたトークンを Apigee Edge 内で使用するには、アクセス トークンを生成するフローが、次のいずれかのパターンに従っている必要があります。

クライアント認証情報の外部検証

  1. ServiceCallout で、受信クライアントの認証情報を検証し、外部トークンを取得します。
  2. ExtractVariables または JavaScript ステップで、外部で生成されたトークンをレスポンスから抽出します。
  3. AssignMessage で、oauth_external_authorization_status という特別な既知の変数を設定します。この変数の値は、クライアント認証情報が有効であることを意味する true でなければなりません。
  4. OAuthV2 または GenerateAccessToken で、<ExternalAuthorization> 要素を true、および <ExternalAccessToken><ExternalRefreshToken><ExternalAuthorizationCode> のうち 1 つ以上に設定します。

クライアント認証情報の内部検証

  • ServiceCallout で外部トークンを取得します。
  • ExtractVariables または JavaScript ステップで、外部で生成されたトークンをレスポンスから抽出します。
  • OAuthV2 または GenerateAccessToken で、<ExternalAuthorization> 要素を false、および <ExternalAccessToken><ExternalRefreshToken><ExternalAuthorizationCode> のうち 1 つ以上に設定します。

フローとポリシー構成に関する注意事項

  • 外部システムを使用してクライアント認証情報を検証する場合、必要な処理を行うポリシーフローを任意に開発できます。通常は、ServiceCallout ポリシーを使用して、外部で認識された認証情報を外部認証サービスに送信することになります。一般に、外部認証システムはレスポンスを返し、認証情報が有効な場合はアクセス トークンも返します。

  • ServiceCallout の後は、API プロキシがレスポンスを解析して、有効なステータスとあわせて外部で生成された access_token、そして場合によっては refresh_token を抽出する必要があります。

  • OAuthV2 ポリシーまたは GenerateAccessToken ポリシーで、<StoreToken> 要素を true に設定し、<ExternalAuthorization> 要素を true または false に適宜設定します。

    OAuthV2 ポリシーまたは GenerateAccessToken ポリシーが実行されると、ポリシーにより変数 oauth_external_authorization_status が読み取られます。変数が設定されていて、その値が true であれば、Apigee Edge はクライアント認証情報の検証を試みません。この変数が設定されていないか、値が true でない場合、Apigee Edge はクライアント認証情報の検証を試みます。

  • OAuthV2 ポリシーには、インポートする外部データの指定を許可する 3 つの要素、<ExternalAccessToken><ExternalRefreshToken><ExternalAuthorizationCode> があります。これらの各要素は、フロー変数 を受け入れます。Edge ポリシーはその変数を読み取って、外部で生成されたアクセス トークン、リフレッシュ トークン、または認証コードを検出します。外部トークンまたはコードを適切な変数に格納するためのポリシーとロジックは任意に実装できます。

    たとえば、OAuthV2 ポリシーを次のように構成すると、Edge は external_token という名前のコンテキスト変数内でトークンを探します。

    <ExternalAccessToken>external_token</ExternalAccessToken>

    前のステップでも、この変数を設定する必要があります。

  • oauth_external_authorization_status 変数の設定に関して、この変数を設定する一般的な方法として、以下のとおり AssignVariable 要素と AssignMessage ポリシーを併用します。

    <AssignMessage name="AssignMessage-SetVariable">
        <DisplayName>Assign Message - Set Variable</DisplayName>
        <AssignVariable>
            <Name>oauth_external_authorization_status</Name>
            <Value>true</Value>
        </AssignVariable>
        <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
    </AssignMessage>

    注意する点として、このポリシーは GenerateAccessToken オペレーションを設定した OAuthV2 ポリシーの前に適用される必要があります。

OAuthV2 ポリシーの例

次の OAuthV2 ポリシーは、Edge がフロー変数 external_access_token でトークン値を見つけた場合に Apigee Edge アクセス トークンを生成します。

<OAuthV2 name="OAuth-v20-Store-External-Token">
    <DisplayName>OAuth v2.0 1</DisplayName>
    <Attributes/>
    <ExternalAccessToken>external_access_token</ExternalAccessToken>
    <ExternalAuthorization>true</ExternalAuthorization>
    <Operation>GenerateAccessToken</Operation>
    <GenerateResponse enabled="true">
        <Format>FORM_PARAM</Format>
    </GenerateResponse>
    <ReuseRefreshToken>false</ReuseRefreshToken>
    <StoreToken>true</StoreToken>
    <SupportedGrantTypes>
        <GrantType>client_credentials</GrantType>
    </SupportedGrantTypes>
    <Tokens/>
</OAuthV2>

理論上は、このパターンを任意のサードパーティ OAuth2 認可サービスを使用して適用できます。