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

このページは ApigeeApigee ハイブリッドに適用されます。

Apigee Edge ドキュメントはこちらをご覧ください。

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

通常、Apigee は OAuth トークンを生成し、保存して、呼び出し元アプリケーションに返します。呼び出し元のアプリケーションは、サービスのリクエスト時にそのトークンを Apigee に返します。Apigee では Operation = VerifyAccessToken が設定された OAuthV2 ポリシーを介して、トークンが有効であることを確認します。このトピックでは、別の場所で生成された OAuth トークンを保存するように Apigee を構成する方法を説明します。ただし、トークンの検証部分についてはトークンが Apigee で生成された場合と同一の状態を保持します。

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

説明

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

背景

通常のケースでは、Apigee は文字と数字からなるランダムな文字列を生成して、トークンを作成します。Apigee はそのトークンに、トークンが発行された時刻、トークンの有効期限、トークンが有効な 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": "myorg",
  "refresh_token_expires_in": "0", //--in seconds
  "refresh_count": "0"
}

access_token 値は Apigee によってトークン メタデータを取得するために使用されます。たとえば、API プロキシ リクエストに署名なしトークン zBC90HhCGmGlaMBWeZAai2s3za5j が含まれているとします。Apigee ではそのトークン値を使用してトークン メタデータを取得し、トークンが有効かどうかを判断します。

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

{
  "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": "myorg",
  "refresh_token_expires_in": "0", //--in seconds
  "refresh_count": "0"
}

この場合、アプリが署名なしトークン TOKEN-1092837373654221 を保持する API プロキシにリクエストを行うと、Apigee がトークンを検証できます。認証コードとリフレッシュ トークンにも、これと同様のインポート パターンを適用できます。

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

トークンを生成する前提条件の 1 つは、リクエスト元のクライアントを検証することです。デフォルトでは、Apigee の OAuthV2/GenerateAccessToken ポリシーは暗黙的にクライアント認証情報を検証します。通常、OAuthV2 トークンのリクエストでは、client_idclient_secret が Authorization ヘッダーに渡され、HTTP 基本認証でエンコードされます(コロンで連結してから、base64 でエンコード)。Apigee の OAuthV2/GenerateAccessToken ポリシーは前述のヘッダーをデコードし、client_id を検索して、渡された client_secret がその client_id に対して有効であることを確認します。これは、認証情報が Apigee に認識されている(つまり特定の client_idclient_secret を含む認証情報を含む Apigee 内に格納されているデベロッパー アプリが存在する)場合に機能します。

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

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

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

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

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

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

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

  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 はクライアント認証情報の検証を試みません。この変数が設定されていないか、値が true でない場合、Apigee はクライアント認証情報の検証を試みます。

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

    たとえば OAuthV2 ポリシーを次のように構成すると、external_token というコンテキスト変数内でトークンを探すよう Apigee に指示されます。

    <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 ポリシーは、Apigee がフロー変数 external_access_token でトークン値を見つけた場合にアクセス トークンを生成します。

<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>
    <ExpiresIn ref='flow.variable'>2400000</ExpiresIn>
</OAuthV2>

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