サードパーティ 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 属性の値は事実上、このメタデータに含まれるその他すべてのデータを参照するルックアップ キーです。アプリはこの署名なしトークン zBC90HhCGmGlaMBWeZAai2s3za5j を使用して、Edge でホストされている API に対してリクエストを行うことができます。Edge は(VerifyAccessToken オペレーションが設定された OAuthV2 ポリシーを使用して)リクエストに含まれるトークンを調べ、そのすべての情報を取得します。こうして取得した情報を使用し、リクエストされた API プロキシに対してそのトークンが有効であるかどうかを判別します。これが、「トークン検証」と呼ばれるプロセスです。 トークンは、上記のすべての情報で構成されます。access_token の値は、それらの情報を調べる手段にすぎません。

一方、以下に説明する手順を行うことで、トークンを保管するよう Edge を構成し、その access_token が外部サービスによって生成された値になるようにできます。その他すべてのメタデータは同じである可能性があります。例として、Apigee Edge の外部に、「TOKEN-<16 random numbers>」の形式でトークンを生成するシステムがあるとします。この場合、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 ポリシーには、外部データをインポートするために使用できる要素として <ExternalAccessToken><ExternalRefreshToken><ExternalAuthorizationCode> の 3 つがあります。これらの要素のそれぞれが、フロー変数を受け入れます。Edge ポリシーはその変数を読み取って、外部で生成されたアクセス トークン、リフレッシュ トークン、または認証コードを検出します。外部トークンまたはコードを適切な変数に格納するためのポリシーとロジックは任意に実装できます。

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

        <ExternalAccessToken>external_token</ExternalAccessToken>
        

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

  • oauth_external_authorization_status 変数の設定に関して、この変数をコンマを使用して設定できるようにするには、AssignMessage ポリシーで次のような AssignVariable 要素を使用します。

        <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 認可サービスを使用して適用できます。