AzureのAPI Gateway(API Management)を用いてOpenID Connect Providerより発行されたJWTを検証

◆ Live配信スケジュール ◆
サイオステクノロジーでは、Microsoft MVPの武井による「わかりみの深いシリーズ」など、定期的なLive配信を行っています。
⇒ 詳細スケジュールはこちらから
⇒ 見逃してしまった方はYoutubeチャンネルをご覧ください
【4/18開催】VSCode Dev Containersで楽々開発環境構築祭り〜Python/Reactなどなど〜
Visual Studio Codeの拡張機能であるDev Containersを使ってReactとかPythonとかSpring Bootとかの開発環境をラクチンで構築する方法を紹介するイベントです。
https://tech-lab.connpass.com/event/311864/

こんにちは、サイオステクノロジー 技術部武井です。今回は、AzureのAPI Gateway(API Management)を用いてOpenID Connect Providerより発行されたJWTを検証してみます。

API Gatewayとは?

AzureのAPI Managementは、API Gatewayの製品です。プロダクトのWebサイトには以下のような説明がありました。

API Management を使用するには、管理者が API を作成します。 API はそれぞれ、少なくとも 1 つの操作で構成され、1 つまたは複数の成果物に追加することができます。 API を使用する開発者は、その API を含んだ成果物をサブスクライブしたうえで、使用ポリシーが適用されていればその範囲の中で、API の操作を呼び出すことができます。 

ワケ(´・ω・`)ワカ(´ε`;)リマ( ;∀;)セン(ノД`)

多分こういうことだと思います。

APIに関わる横断的な処理を一手に引き受けてくれます。つまり、APIを開発する際、今までAPIの認証、ロギング、課金管理などはAPIごとに実装していました。しかし、そうではなく、全てのAPIへのアクセスは、一旦、API Gatewayなるものに全てアクセスさせて、そこで認証、ロギングなどを行い、それからAPIにその要求を引き渡すということをしてくれます。

API Gatewayがない場合は、こんな感じだったと思います。APIごとに認証やロギングを実装しています。

Screen Shot 2018-08-03 at 7.30.46

 

API Gatewayを使えば、こんなにハッピーになれます。認証やロギングをまず一手にAPI Gatewayで引き受けて、その処理が正常に完了したものだけ、バックエンドにあるAPIにその要求を引き渡します。

Screen Shot 2018-08-03 at 7.30.56

 

今回のゴール

今回は、このAPI Gatewayを使って、OpenID ConnectのProviderで発行されたID Token(JSON Web Token)を検証して、Open ID ConnectのProviderで認証を受けていないAPIは、その要求を拒否(HTTPステータスコード401を返す)ということをしたいのです。

つまり絵にすると、以下のようになります。

Screen Shot 2018-08-03 at 7.49.14

上図のとおりなのですが、今回はOpenID ConnectのプロバイダーとしてYahooを使います。Yahooが発行するID Tokenは、API Management(後述)で検証可能なJSON Web Tokenの仕様に準じているからです。

API GatewayにはAzureのAPI Managementを使います。OpenID Connectのプロバイダーが発行したID Token(JSON Web Token)の検証が行えます。

API Gatewayの背後に置くAPIについては、何でもよかったのですが、API ManagementからさくっとインポートできるAzure Functionsをチョイスしました。

実際にやってみましょう

では、早速いつもどおり実践してみます(๑•̀ㅂ•́)و✧

APIを作る

まずAPI Gatewayの背後に置くAPIを作ります。Azure Functionsでさっくり作ります。このあたりあまり今回の本質ではないので、説明はざっくりしてしまいます。もし、ご自分で公開されているAPIをお持ちであれば、そちらを使っていただいても構いません。

Azureポータルにログインして、「リソースの作成」をクリックして、「function」と入力してフィルターすると「Function App」が出てきますので、クリックします。

Screen Shot 2018-08-03 at 8.10.40

 

「作成」をクリックします。

Screen Shot 2018-08-03 at 8.10.52

「アプリ名」は任意の名称、「サブスリプション」「リソースグループ」「Storage」は環境に応じたものを、他は以下のように入力して、「作成」をクリックします。

Screen Shot 2018-08-03 at 8.11.53

 

しばらくすると、Azureポータルの上の通知アイコン(鈴みたいなやつ)に以下のように作成に成功した旨が表示されるので「リソースグループに移動」をクリックします(切れてますが)。

Screen Shot 2018-08-03 at 8.18.25

 

「関数」のとなりにある「+」をクリックします。

Screen Shot 2018-08-03 at 8.18.55

 

今回はRestAPIを作成しますので、「webhook + API」を選択して、言語は「JavaScript」を選択します。言語は何でもいいのですが、私がJavaな人間なので、JavaScriptにしました。最後に「この関数を作成する」をクリックします。

Screen Shot 2018-08-03 at 8.19.42

 

こんな感じでAPIが出来ます。Postでnameというパラメータに値を渡すと「Hello [名前]」というレスポンスが返ってくる単純なものです。実行してみましょう。「関数のURLの取得」をクリックしてください。

Screen Shot 2018-08-03 at 8.20.10

 

「コピー」をクリックします。

Screen Shot 2018-08-03 at 8.35.18

上記でコピーしたURLを元に以下のcurl文でリクエストを投げてみてください。

# curl -H 'Content-Type:application/json' -d "{\"name\":\"hoge\"}"  https://apim-test-api.azurewebsites.net/api/HttpTriggerJS1?code=XXXXXX

 

“Hello hoge”と返ってくれば成功です。

 

とりあえずAPI(Azure Functions)のところは終わりました。次は、YahooでOpenID ConnectのProviderを作ります。

Screen Shot 2018-08-03 at 17.17.35

 

OpenID ConnectのProviderを作る

以下のURLにアクセスしてください。

https://e.developer.yahoo.co.jp/dashboard/

 

「新しいアプリケーションを開発」をクリックします。

Screen Shot 2018-08-02 at 23.02.01

 

「サーバーサイド」の方をチェックします。

Screen Shot 2018-08-02 at 23.02.19

 

「アプリケーション名」に任意のアプリケーション名を入力します。あとはデフォルトのままでOKです。

Screen Shot 2018-08-03 at 17.29.57

 

「同意する」をチェックして「確認」をクリックします。

Screen Shot 2018-08-02 at 23.03.07

 

入力内容に問題ないことを確認して「登録」をクリックします。

Screen Shot 2018-08-03 at 17.33.32

 

「Client ID」「シークレット」をメモっておいてください。後で使います。

Screen Shot 2018-08-03 at 17.38.09

 

OpenID ConnectのProvider構築まで完了しました。

Screen Shot 2018-08-03 at 17.59.30

 

API Gatewayを作る

Azureポータルにアクセスして、「すべてのサービス」をクリックして、下記のように「api」と入力すると、「API Managementサービス」が表示されますので、クリックします。

Screen Shot 2018-08-02 at 23.14.34

 

「追加」をクリックします。

Screen Shot 2018-08-02 at 23.15.03

 

「名前」「組織名」に任意の名称、「サブスリプション」「リソースグループ」「場所」は環境に応じた値を、「管理者のメールアドレス」はAPI Managementサービスの作成が完了したときに通知されるメールアドレスを、「価格レベル」は「開発者(いいえ SLA)」を選択して、「作成」をクリックします。しばらくするとAPI Managementのサービスが作成されます。

Screen Shot 2018-08-03 at 6.56.47

 

そして、これからこのAPI Gatewayの背後に配置するAPIを設定します。それが先程Azure Functionsで作成したものになるわけですが、その前にもう一つやることがあります。API ManagementにAPIを配置するまえにAPIの定義を作成しなければなりません。これはOpen APIという仕様で定義されているのですが、このAPIがどのようなMethod(Post or Get or …)やどのようなパラメータを取るかを定義したものです。この定義を作成するために一旦、先程のAzure Functionsの画面に戻ります。以下の画面の右下の方にある「APIの定義」をクリックしてください。

Screen Shot 2018-08-03 at 18.18.23

 

「関数(プレビュー)」をクリックします。

Screen Shot 2018-08-03 at 18.19.06

 

「API定義テンプレートを生成する」→「保存」の順にクリックします。これでAPIの定義が出来上がりました。

Screen Shot 2018-08-03 at 18.19.40

 

では、API Managementの画面に戻りましょう。以下の画面で「API」をクリックします。

Screen Shot 2018-08-03 at 18.12.40

 

 

API Managementの背後に、先程作成したAzure Functionsを配置したいので「Function App」をクリックします。

Screen Shot 2018-08-03 at 18.12.55

 

「Browse」をクリックすると、Azure Functionsを選択する画面が表示されますので、先程作成したAzure Functionsをクリックします。また「Products」には「Unlimited」を選択して、「Create」をクリックします。

Screen Shot 2018-08-03 at 18.31.48

 

デフォルトではAzure Functionsはキーで保護されています。つまり、Azure Functionsを呼び出す際、URLのクエリパラメーターのcodeに、Azure Functionsを作成した際に発行されたキーを指定しないとAzure Functionsが呼び出せないのです。先程、以下のcurlコマンドを打って、Azure Functionsを試したと思います。

# curl -H 'Content-Type:application/json' -d "{\"name\":\"hoge\"}"  https://apim-test-api.azurewebsites.net/api/HttpTriggerJS1?code=XXXXXX

上記のcode=XXXXXXで指定されているXXXXXXの値をメモっておいてください。API ManagementからAPI、つまりAzure Functionsを呼び出すときにはこのcodeを渡さないといけないので、これからこのcodeの定義を行います。以下の画面の「名前付きの値」をクリックします。

Screen Shot 2018-08-03 at 18.54.16

 

リストに表示されているAzure Functionsをクリックします。

Screen Shot 2018-08-03 at 18.54.16

 

「値の表示」をクリックすると、テキストボックスが表示されますので、その中に先程のcodeの値を入力します。これでAPI ManagementからAPI(Azure Functions)を呼び出したときに

codeの値がクエリパラメーターとして渡されるようになります。

Screen Shot 2018-08-03 at 18.54.27

 

これからOpenID ConnectのProviderから発行されるID Token(JSON Web Token)を検証するためのポリシーを設定します。「API」→「api-test-api.azurewebsite…(先ほどインポートしたAzure Functions)」→「Post ・・・」の順にクリックします(ちなみにここにGETやらPUTやらいろんなメソッドのAPIのインターフェースが表示されていますが、これは先程作成したAPIの定義に基づくものです)。

Screen Shot 2018-08-03 at 18.55.56

 

 

「Inbound processing」の鉛筆マークをクリックします。

Screen Shot 2018-08-03 at 18.56.13

 

「</> Code View」をクリックします。

Screen Shot 2018-08-03 at 18.56.19

 

右のメニューから「Validate JWT」をクリックして、以下のようなXMLを作成します。

Screen Shot 2018-08-03 at 19.55.18

 

先程のXMLを整形して、<validate-jwt>~</validate-jwt>を以下のようなXMLにします。最後に「Save」をクリックします。

これで設定は全て終わりです。

Screen Shot 2018-08-03 at 21.19.17

試してみる

では、早速試してみたいと思います。OpenID ConnectのProviderで発行されるID Tokenを取得します。以下のURLをブラウザのURL入力欄に入力します。

https://auth.login.yahoo.co.jp/yconnect/v2/authorization?client_id=[Yahooの設定画面で取得したClient ID]
&response_type=id_token&redirect_uri=https://developer.yahoo.co.jp/start/&scope=openid&state=hoge&nonce=hoge

※stateとnonceは適当です(´・ω・`)

response_typeはOAuthでいうところのフローを選択する項目なのですが、ここではid_tokenつまりImplicit Flowを選択してます。

以下のURLにリダイレクトされます。

https://developer.yahoo.co.jp/start/#state=hoge&id_token=[ID Token]

id_tokenのクエリパラメータで指定されている値がID Tokenになります。ペイロードの部分をBase64エンコードしてみます。

{
"iss":"https://auth.login.yahoo.co.jp/yconnec/v2",
"sub":"LBHNLYCPWDV3UTO5HVVBFIXTMA",
"aud":[Yahooの設定画面で取得したClient ID],
"exp":1535714821,
"iat":1533295621,
"amr":["pwd"],
"nonce":"hoge"
}

おおっ。JSON Web Tokenっぽい(๑•̀ㅂ•́)و✧

そして次はAPI Managementで定義されたAPIを叩いてみましょう。まずその前にAPIのURLを取得します。

「API」→「api-test-api.azurewebsite…(先ほどインポートしたAzure Functions)」→「Settings」の順にクリックして表示される「Web Service URL」がAPIのURLになりますので、メモします。
Screen Shot 2018-08-03 at 21.34.13

 

次にそのまま「Test」のタブをクリックします。「Ocp-Apim-Subscription-Key」の値をメモします(目のマークをクリックすると表示されます)。

Screen Shot 2018-08-03 at 21.36.59

 

以下のcurlコマンドを実行します。

curl -D - -H 'Content-Type:application/json' -H 'Ocp-Apim-Subscription-Key:[先程メモしたOcp-Apim-Subscription-Keyの値]' -H 'Authorization:Bearer [先程メモしたID Token]' -d "{\"name\":\"hoge\"}" [先程メモしたAPIのURL]/api/HttpTriggerJS1

すると・・・

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Length: 12
Content-Type: application/json; charset=utf-8
Expires: -1
X-Powered-By: ASP.NET
Date: Fri, 03 Aug 2018 11:35:42 GMT

"Hello hoge"

おおヮ(゚д゚)ォ!

API Managementの背後に置いてあるAzure Functionsが実行されました(๑•̀ㅂ•́)و✧

最後に

今までは、ID Tokenの検証はアプリケーションの中で実装してたのですが、API Managementがあればそんな実装は不要ですね。Azureバンザイ٩(๑´3`๑)۶

アバター画像
About 武井 宜行 269 Articles
Microsoft MVP for Azure🌟「最新の技術を楽しくわかりやすく」をモットーにブログtech-lab.sios.jp)で情報を発信🎤得意分野はAzureによるクラウドネイティブな開発(Javaなど)💻「世界一わかりみの深いクラウドネイティブ on Azure」の動画を配信中📹 https://t.co/OMaJYb3pRN
ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

2人がこの投稿は役に立ったと言っています。


ご覧いただきありがとうございます。
ブログの最新情報はSNSでも発信しております。
ぜひTwitterのフォロー&Facebookページにいいねをお願い致します!



>> 雑誌等の執筆依頼を受付しております。
   ご希望の方はお気軽にお問い合わせください!

Be the first to comment

Leave a Reply

Your email address will not be published.


*


質問はこちら 閉じる