OAuth で API を保護する

演習内容

  • サンプル API プロキシをダウンロードしてデプロイします。
  • OAuth で保護された API プロキシを作成します。
  • プロダクト、デベロッパー、アプリを作成します。
  • 認証情報と引き換えに OAuth アクセス トークンを取得します。
  • アクセス トークンを使用して API を呼び出します。

このチュートリアルでは、OAuth 2.0 を使用して API を保護する方法について説明します。

OAuth は、ユーザーにユーザー名とパスワードの提供を求めることなく、アプリがユーザーに代わって情報にアクセスできるようにする認可プロトコルです。

OAuth では、セキュリティ認証情報(ユーザー名とパスワードまたはキーとシークレットの組み合わせ)と引き換えにアクセス トークンを取得します。例:

joe:joes_password(ユーザー名:パスワード)または
Nf2moHOASMJeUmXVdDhlMbPaXm2U7eMc:unUOXYpPe74ZfLEb(キー:シークレット)

これらと引き換えに次のようなトークンが返されます。

b0uiYwjRZLEo4lEu7ky2GGxHkanN

アクセス トークンはランダムな文字列であり、一時的なものです(比較的短時間で有効期限が切れます)。したがって、アプリ ワークフローでユーザーを認証する際には、実際の認証情報を渡すよりもアクセス トークンを渡すほうがはるかに安全です。

OAuth 2.0 仕様では、アプリのアクセス トークンを配布するために使用される、「権限付与タイプ」という各種メカニズムが定義されています。OAuth 2.0 で定義されている最も基本的な権限付与タイプは、「クライアント認証情報」です。この権限付与タイプでは、上の例のように、コンシューマ キーとコンシューマ シークレットのペアであるクライアント認証情報と引き換えに OAuth アクセス トークンが生成されます。

Edge のクライアント認証情報の権限付与タイプは、API プロキシでポリシーを使用して実装されます。一般的な OAuth フローには、次の 2 つのステップがあります。

  • API プロキシ 1 への呼び出しを行って、クライアント認証情報から OAuth アクセス トークンを生成します。この処理には、API プロキシの OAuth v2.0 ポリシーが使用されます。
  • API プロキシ 2 への呼び出しを行って、API 呼び出し内で OAuth アクセス トークンを送信します。API プロキシでは、OAuth v2.0 ポリシーを使用してアクセス トークンが検証されます。

必要なもの

  • Apigee Edge アカウント。まだお持ちでない場合は、Apigee Edge アカウントの作成の手順に沿って登録できます。
  • cURL。コマンドラインから API 呼び出しを行うために、マシン上にインストールされている必要があります。

トークンを生成する API プロキシをダウンロードしてデプロイする

このステップでは、API 呼び出しで送信されたコンシューマ キーとコンシューマ シークレットから OAuth アクセス トークンを生成する API プロキシを作成します。この処理を行うためのサンプル API プロキシが Apigee から提供されています。ここでは、そのプロキシをダウンロードしてデプロイし、以降のチュートリアルで使用できるようにします(この API プロキシはご自身で簡単に作成できます。このダウンロードとデプロイのステップは便宜上設けられたものであり、すでに作成されているプロキシの共有がいかに簡単かを示すものです)。

  1. ファイル システム上の任意のディレクトリに「oauth」というサンプル API プロキシの ZIP ファイルをダウンロードします
  2. https://apigee.com/edge に移動してログインします。
  3. 左側のナビゲーション バーで [Develop] > [API Proxies] を選択します。
  4. [+ Proxy] をクリックします。
    [Create proxy] ボタン
  5. [Create Proxy] ウィザードで [Proxy bundle] を選択して、[Next] をクリックします。
  6. ダウンロードした oauth.zip ファイルを選択し、[Next] をクリックします。
  7. [Build] をクリックします。
  8. ビルドが完了したら、[oauth] リンクをクリックして、API プロキシ エディタに新しいプロキシを表示します。
  9. API プロキシ エディタの [Overview ] ページで [Deployment] プルダウンをクリックし、[test] を選択します。これは組織内のテスト環境です。

    確認プロンプトで、[Deploy] をクリックします。
    [Deployment] プルダウンをもう一度クリックすると、プロキシがテスト環境にデプロイされていることが緑色のアイコンで示されます。

成功です。アクセス トークンを生成する API プロキシをダウンロードして、Edge 組織に正常にデプロイできました。

OAuth フローとポリシーを表示する

ここでは、API プロキシの内容を詳しく確認します。

  1. API プロキシ エディタで、[Develop] タブをクリックします。左側の [Navigator] ペインに 2 つのポリシーが表示されます。また、[Proxy Endpoints] セクションには、2 つの POST フローが表示されます。
  2. [Proxy Endpoints] で [AccessTokenClientCredential] をクリックします。

    XML コードビューに AccessTokenClientCredential という Flow が表示されます。

    <Flow name="AccessTokenClientCredential">
        <Description/>
        <Request>
            <Step>
                <Name>GenerateAccessTokenClient</Name>
            </Step>
        </Request>
        <Response/>
        <Condition>(proxy.pathsuffix MatchesPath "/accesstoken") and (request.verb = "POST")</Condition>
    </Flow>
    

    フローとは、API プロキシの処理ステップです。この場合、フローは特定の条件を満たす場合にトリガーされます(「条件付きフロー」と呼ばれます)。<Condition> 要素には、/accesstoken リソースに対して API プロキシ呼び出しが行われ、かつリクエスト動詞が POST である場合に、GenerateAccessTokenClient ポリシーを実行してアクセス トークンが生成されるという条件が定義されています。

  3. 次に、条件付きフローによってトリガーされるポリシーを確認します。フロー図の [GenerateAccessTokenClient] ポリシー アイコンをクリックします。

    次の XML 構成がコードビューに読み込まれます。

    <OAuthV2 name="GenerateAccessTokenClient">
        <!-- This policy generates an OAuth 2.0 access token using the client_credentials grant type -->
        <Operation>GenerateAccessToken</Operation>
        <!-- This is in millseconds, so expire in an hour -->
        <ExpiresIn>3600000</ExpiresIn>
        <SupportedGrantTypes>
            <!-- This part is very important: most real OAuth 2.0 apps will want to use other
             grant types. In this case it is important to NOT include the "client_credentials"
             type because it allows a client to get access to a token with no user authentication -->
            <GrantType>client_credentials</GrantType>
        </SupportedGrantTypes>
        <GrantType>request.queryparam.grant_type</GrantType>
        <GenerateResponse/>
    </OAuthV2>
    

    構成の内容は次のとおりです。

    • <Operation>(事前定義された値のいずれか)により、ポリシーの処理内容が定義されます。この場合はアクセス トークンが生成されます。
    • トークンの有効期限は、生成後 1 時間(3,600,000 ミリ秒)です。
    • <SupportedGrantTypes> では、使用する OAuth <GrantType> として client_credentials が指定されています(コンシューマ キーとコンシューマ シークレットと引き換えに OAuth トークンが取得されます)。
    • 2 番目の <GrantType> 要素では、OAuth 2.0 仕様によって要求されている権限付与タイプ パラメータを API 呼び出しのどこで検索するかをポリシーに指示します(API 呼び出しのこの部分については、後で確認します)。権限付与タイプは、HTTP ヘッダー(request.header.grant_type)で送信することも、フォーム パラメータ(request.formparam.grant_type)として送信することも可能です。

現時点では、API プロキシに対してその他の処理を実行する必要はありません。後のステップで、この API プロキシを使用して OAuth アクセス トークンを生成します。ただし、事前に次の作業を行う必要があります。

  • OAuth で実際に保護する API プロキシを作成する。
  • アクセス トークンを取得する際に引き換えとして必要になるコンシューマ キーとコンシューマ シークレットの生成に使用されるいくつかのアーティファクトを作成する。

OAuth で保護された API プロキシを作成する

mocktarget について

mocktarget サービスは Apigee でホストされており、単純なデータを返します。実際、ウェブブラウザでアクセスできます。次をクリックして、試してみましょう。

http://mocktarget.apigee.net/ip

返される内容は、最終的にこの API プロキシを呼び出したときに表示される情報と同じです。

mocktarget で使用可能なその他の API リソースについては、http://mocktarget.apigee.net/help をご覧ください。

これから、保護する API プロキシの作成に進みます。この API 呼び出しを通じて目的の情報が返されるようにします。この場合、API プロキシで Apigee の mocktarget サービスを呼び出すことによって、IP アドレスが返されるようにします。ただし、この情報が表示されるのは、API 呼び出しで有効な OAuth アクセス トークンを渡した場合のみです。

ここで作成する API プロキシには、リクエスト内の OAuth トークンを検査するポリシーを組み込みます。

  1. 左側のナビゲーション バーで [Develop] > [API Proxies] を選択します。
  2. [+ Proxy] をクリックします。
    [Create proxy] ボタン
  3. [Build a Proxy] ウィザードで [Reverse proxy (most common)] を選択し、[Next] をクリックします。
  4. 次のようにプロキシを構成します。
    フィールド 操作内容
    Proxy Name helloworld_oauth2」と入力します。
    Project Base Path

    /hellooauth2 に変更します。

    [Project Base Path] は、API プロキシに対してリクエストを行うために使用される URL の一部です。

    Existing API

    https://mocktarget.apigee.net/ip」と入力します。

    ここでは、API プロキシへのリクエストで Apigee Edge によって呼び出されるターゲット URL を定義します。

    Description hello world protected by OAuth」と入力します。
  5. [Next] をクリックします。
  6. [Security] ページで次の操作を行います。
    フィールド 操作内容
    Authorization 次を選択します。
    • OAuth 2.0
    • Publish API Product

    これらのオプションはとても便利です。2 つのポリシーが API プロキシに自動的に追加され、API プロダクトが作成されます。

  7. [Next] をクリックします。
  8. [Virtual Hosts] ページで、[Next] をクリックします。
  9. [Build] ページで test 環境が選択されていることを確認してから、[Build and Deploy] をクリックします。
  10. [Summary] ページで、新しい API プロキシと API プロダクトが正常に作成され、テスト環境にデプロイされたことを示す確認情報が表示されます。
  11. [View helloworld_oauth2 proxy in the editor] をクリックして、API プロキシの [Overview] ページを表示します。
    今回は API プロキシが自動的にデプロイされていることを確認します。[Deployment] プルダウンをクリックして、デプロイ済みであることを示す緑色のドットが「test」環境の横に表示されていることを確認します。

API プロダクトについて

このチュートリアルでは詳しく説明しませんが、Edge の便利な機能の 1 つである API プロダクトによって、デベロッパー用(正確に言うとデベロッパーが Edge に登録するアプリ用)のコンシューマ キーとコンシューマ シークレットが生成されます。

興味がある方は、API プロキシが生成される際に自動的に作成された API プロダクトを確認できます。UI で、[Publish] > [API Products] > [helloworld_oauth2-Product] の順に選択します。

[Request Approval] が [Automatic] になっていることに注意してください。これは、手動でキーを承認した後でキーをデベロッパーに与えるのではなく、デベロッパーがアプリを登録すると自動的に API キーがデベロッパーに与えられることを意味します。

ポリシーの表示

ここでは、作成した内容を詳しく確認します。

  1. API プロキシ エディタで、[Develop] タブをクリックします。API プロキシのリクエスト フローに次の 2 つのポリシーが追加されていることを確認します。
    • Verify OAuth v2.0 Access Token - API 呼び出しを調べて有効な OAuth トークンが存在することを確認します。
    • Remove Header Authorization – ターゲット サービスに渡されないように、検査後のアクセス トークンを削除する Assign Message ポリシーです(ターゲット サービスが OAuth アクセス トークンを必要とする場合は、このポリシーは使用しません)。
  2. フロービューで [Verify OAuth v2.0 Access Token] アイコンをクリックし、コードペインでその下の XML を確認します。

    <OAuthV2 async="false" continueOnError="false" enabled="true" name="verify-oauth-v2-access-token">
        <DisplayName>Verify OAuth v2.0 Access Token</DisplayName>
        <Operation>VerifyAccessToken</Operation>
    </OAuthV2>
    

    <Operation>VerifyAccessToken になっていることに注意してください。Operation ではポリシーの処理内容が定義されます。この場合は、リクエスト内に有効な OAuth トークンが存在するかどうかが確認されます。

デベロッパーとアプリを組織に追加する

次に、デベロッパーが API の使用登録を行うためのワークフローをシミュレートします。デベロッパーは自分自身と自分のアプリをデベロッパー ポータル経由で登録するのが理想的です。ただしこのステップでは、管理者としてデベロッパーとアプリを追加します。

デベロッパーは API を呼び出す 1 つ以上のアプリを所有し、各アプリにはそれぞれ一意のコンシューマ キーとコンシューマ シークレットが割り当てられます。このように Key-Secret をアプリごとに使用すると、デベロッパーとアプリがどの OAuth トークンに属しているかを Edge で認識できるようになるため、API プロバイダは、API へのアクセスをより細かに制御したり、API トラフィックに関するより詳細な分析レポートを行ったりできます。

デベロッパーを作成する

ここでは、Nigel Tufnel というデベロッパーを作成します。

  1. メニューで [Publish] > [Developers] を選択します。
  2. [+ Developer] をクリックします。
  3. [New Developer] ウィンドウで次のように入力します。
    フィールド 入力
    First Name Nigel
    Last Name Tufnel
    Username nigel
    Email nigel@example.com
  4. [Save] をクリックします。

アプリを登録する

ここでは、Nigel 用のアプリを作成します。

  1. [Publish] > [Apps] を選択します。
  2. [+ App] をクリックします。
  3. [New App] ウィンドウで、次のように入力します。
    フィールド 操作内容
    NameDisplay Name nigel_app」と入力します。
    Developer [Developer] をクリックし、Nigel Tufnel (nigel@example.com) を選択します。
    Callback URLNotes 空白のままにします。
  4. [Products] で [Add Product] をクリックします。
  5. [helloworld_oauth2-Product] を選択します。
  6. [Create] をクリックします。

コンシューマ キーとコンシューマ シークレットを取得する

ここでは、OAuth アクセス トークンを取得する際に引き換えとして必要になるコンシューマ キーとコンシューマ シークレットを取得します。

  1. [nigel_app] ページが表示されていることを確認します。表示されていない場合は、[Apps] ページ([Publish] > [Apps])で [nigel_app] をクリックします。
  2. [nigel_app] ページで、[Key] 列と [Secret] 列の [Show] をクリックします。前に自動的に作成された [helloworld_oauth2 Product] に Key-Secret が関連付けられていることに注目してください。

  3. キーとシークレットを選択してコピーします。一時的なテキスト ファイルに貼り付けます。これらの認証情報は後のステップで使用します。つまり、API プロキシを呼び出すと、これらの認証情報と引き換えに OAuth アクセス トークンが取得されます。

API を呼び出して IP アドレスを取得できるか試す(失敗)

保護された API プロキシを呼び出して、IP アドレスが想定どおりに返されるかどうか試してみましょう。ターミナル ウィンドウで次の cURL コマンドを実行します。該当する部分を実際の Edge 組織名に置き換えてください(中かっこは削除してください)。URL 内の単語 test は、プロキシがデプロイされている組織のテスト環境を表します。プロキシのベースパスは /hellooauth2 です。プロキシの作成時に指定したベースパスと同じです。呼び出しでは OAuth アクセス トークンを渡していないことに注目してください。

curl https://{org-name}-test.apigee.net/hellooauth2

リクエスト内に有効な OAuth トークンが存在するかどうかを検査する Verify OAuth v2.0 Access Token ポリシーが API プロキシに組み込まれているため、呼び出しは失敗し、次のメッセージが表示されます。

{"fault":{"faultstring":"Invalid access token","detail":{"errorcode":"oauth.v2.InvalidAccessToken"}}}

この場合は、失敗するのが正常です。つまり、API プロキシは厳格に保護されています。この API を正常に呼び出すことができるのは、有効な OAuth アクセス トークンを持つ信頼できるアプリのみです。

OAuth アクセス トークンを取得する

成功は目の前です。次は、コピーしてテキスト ファイルに貼り付けたキーとシークレットと引き換えに OAuth アクセス トークンを取得します。ここでは、インポートした API サンプル プロキシ oauth に対して API 呼び出しを実行し、API アクセス トークンを生成します。

キーとシークレットを使用して、次の cURL 呼び出しを行います(プロトコルは https です)。該当する部分を実際の Edge 組織名、キー、シークレットにそれぞれ置き換えてください(中かっこは削除してください)。

curl -X POST -H "Content-Type: application/x-www-form-urlencoded" \
"https://{org-name}-test.apigee.net/oauth/client_credential/accesstoken?grant_type=client_credentials" \
-d "client_id={key}&client_secret={secret}"

Postman などのクライアントを使用して呼び出しを行う場合は、リクエストの本文に client_idclient_secretx-www-form-urlencoded の形式で入ります。

次のようなレスポンスが得られるはずです。

{
  "issued_at" : "1466025769306",
  "application_name" : "716bbe61-f14a-4d85-9b56-a62ff8e0d347",
  "scope" : "",
  "status" : "approved",
  "api_product_list" : "[helloworld_oauth2-Product]",
  "expires_in" : "3599", //--in seconds
  "developer.email" : "nigel@example.com",
  "token_type" : "BearerToken",
  "client_id" : "xNnREu1DNGfiwzQZ5HUN8IAUwZSW1GZW",
  "access_token" : "GTPY9VUHCqKVMRB0cHxnmAp0RXc0",
  "organization_name" : "myOrg",
  "refresh_token_expires_in" : "0", //--in seconds
  "refresh_count" : "0"
}

これで、OAuth アクセス トークンを取得できました。access_token の値(引用符は不要)をコピーし、テキスト ファイルに貼り付けます。これはすぐに使用します。

ここでは、何が行われたのでしょうか。

前に確認した OAuth プロキシの「条件付きフロー」によると、リソース URI が /accesstoken でリクエスト動詞が POST である場合に、GenerateAccessTokenClient OAuth ポリシーが実行されアクセス トークンが生成されます。使用した cURL コマンドはこの条件を満たすため、OAuth ポリシーが実行されました。そして、コンシューマ キーとコンシューマ シークレットが検証され、これらと引き換えに OAuth トークンが取得されました。このトークンの有効期限は 1 時間です。

アクセス トークンを使用して API を呼び出す(成功)

アクセス トークンを取得したら、それを使用して API プロキシを呼び出すことができます。次の cURL 呼び出しを実行します。該当する部分を実際の Edge 組織名とアクセス トークンにそれぞれ置き換えてください(中かっこは削除してください)。

curl https://{org-name}-test.apigee.net/hellooauth2 -H "Authorization: Bearer {access-token}"

今回は、API プロキシに対する呼び出しが成功し、IP アドレスが返されるはずです。例:

{"ip":"::ffff:192.168.14.136"}

アクセス トークンの有効期限が切れる 1 時間後までは、同じ API 呼び出しを繰り返すことができます。1 時間後に呼び出しを実行するには、上記の手順に従って新しいアクセス トークンを生成する必要があります。

これで完了です。API プロキシが作成され、有効な OAuth アクセス トークンを呼び出しに含めるよう要求することでプロキシが保護されるようになりました。

関連トピック