OAuth で API を保護する

演習内容

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

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

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

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

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 つをとります。この場合は、アクセス トークンの生成を行います。
    • トークンの有効期限は、生成後 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. [Virtual Hosts] ページで、[Next] をクリックします。
  8. [Build] ページで、test 環境が選択されていることを確認し、[Build and Deploy] をクリックします。
  9. [Summary] ページで、新しい API プロキシと API プロダクトが正常に作成され、その API プロキシが test 環境にデプロイされたことを示す確認情報が表示されます。
  10. [View the helloworld_oauth2 proxy in the editor] をクリックして、API プロキシの [Overview] ページを表示します。
    今回は API プロキシが自動的にデプロイされていることを確認します。[Deployment] プルダウンをクリックして、デプロイ済みであることを示す緑色のドットが [test] 環境の横に表示されていることを確認します。

API プロダクトについて

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

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

[Key Approval Type] が [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」と入力します。
    Email nigel@example.com」と入力します。
    Username nigel」と入力します。
  4. [Save] をクリックします。

アプリを登録する

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

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

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

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

  1. [Developer Apps] ページ([Publish] > [Developer Apps])で、[nigel_app] をクリックします。
  2. [nigel_app] ページで、[Consumer Key] 列と [Consumer 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 プロキシが厳格に保護されていることを意味します。有効な OAuth アクセス トークンを持つ信頼できるアプリのみがこの API を正常に呼び出すことができます。

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={consumer-key}&client_secret={consumer-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 アクセス トークンを呼び出しに含めるよう要求することでプロキシが保護されるようになりました。

関連トピック