【OCI】API Gatewayに認証を実装してみる

# はじめに

今回はOracle Cloud Infrastructure（OCI）のAPI Gatewayに手っ取り早く
認証をかけるために、Auth0を利用してOAuth2.0を基盤としたJWT認証を
実装する方法を紹介したいと思います。

そもそもの話、API Gatewayを使ってAPIを公開するのは比較的簡単ですが、
認証の実装についてはかなり面倒な作業とお感じではないでしょうか？
Functionsの中に認証の仕組みを入れることもできますが、
それだとセキュリティ的に問題があると思うので、
ここはやはりトークンを発行し、そのトークンを使用してAPIをコールできる仕組みを
取り入れるのが良いのではないかと思います。

そこでJWT認証です。
JWT（Json Web Token）とは、API認証でよく使用されるトークンの形式のことで
OAuth2.0に基づく認証プロセスを簡単に実現できます。
この仕組みを使えば、認証機能を自前で実装することなく、
API Gatewayに認証を組み込むことが可能です。

JWTの仕組みを簡単に利用できるサービスとして無償プランを
提供しているAuth0があります。
今回はこのサービスを利用してJWT認証の仕組みを設定する方法を
説明したいと思います。

■Auth0の公式サイト
https://auth0.com/jp

■API GatewayでJWT認証を使うまでの簡単な流れ
①Auth0でトークン発行用APIを作成
②Auth0でApplicationを作成し、①で作成したのAPIと紐づける
③OCI API Gatewayでトークンを検証する設定を入れる
④Auth0のAPIでトークン発行
⑤OCI API Gatewayを④のトークンを使ってコールする

今回の構成を図にすると次のようなイメージとなります。

■構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/dacae03f-cc08-f84d-e622-567b970343d3.png)

今回使用するAPI Gateway（Functions）については過去のQiitaに
簡単にまとめていますので、こちら参考にしてください。

■【OCI】API Gateway経由でFunctionsのAPIを呼び出してみる
https://qiita.com/atwits/items/f9dcc82f6a552c3df390

※API Gateway（Functions）の細かい手順については
上記ブログでまとめているので省略します。

◆目次
1.Auth0の設定
2.API Gatewayの設定
3.APIの動作検証

## 1. Auth0の設定

まずはAuth0の公式サイトからアカウントを作成します。
※こちら無料で利用可能です。

それでは早速、Auth0の設定に入りたいと思います。

Auth0にログインしたら、[Applications] - [APIs]を選択し、
Create APIを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/67448326-a500-34a6-a250-7971506ea566.png)

NameとIdentifierに任意の文字列を入力して、Createを実行します。
※Identifierはアカウント内でユニークであれば問題ありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/841b8181-1549-db3d-f3d9-4efc57d13e21.png)

ここでは以下を入力
Name: oci-apigateway
Identifier: https://oci-apigateway-endpoint

次に[Applications] - [Applications]を選択し、
Create Applicationを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/1c270e7d-3992-4dac-4970-bde107e8c2e9.png)

Nameに任意の文字列を入力し、Machine to Machine Applicationsを選択し、
Createを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/ccbf3040-a95a-0204-c7d4-6d76a2e352a2.png)

ここでは以下を入力
Name: app-oci-apigateway

こちらは先程作成したAPIを選択し、Authoriseを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/a7908f60-d204-d160-75a9-9787d878991c.png)

前述の手順でAPIとApplicationが作成されているので
まずはApplicationのトップのリンクを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/3f16e8dc-8892-5e35-600e-bfc7aca1f612.png)

Basic InformationのエリアにDomain、Client ID、Client Secretがあるので
それぞれ書き留めておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/54ab41d0-f861-fb7f-4614-d115ab0e91d0.png)

APIsのトップに遷移すると、API Audienceがあるのでこちらも書き留めておきます。
（前述のIdentifierと同じ値です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/67793ef7-58be-d7b1-c1b9-05c0d15a3744.png)

以上でAuth0側の設定は終了です。

## 2. API Gatewayの設定

ここでは既にAPI Gateway + Functionsが設定されている前提で
JWT認証を設定する部分を説明したいと思います。

左上メニュー[Ξ]から開発者サービスを選択し、
ゲートウェイを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/6823a1fc-378e-1d49-d69f-e8c8813988da.png)

あとは認証設定したいAPI Gatewayを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/f81a3090-9f59-24a2-62af-3c1f14d77e1d.png)

続いてデプロイメントを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/c937a1ef-3e0f-7b68-559d-374971c98e76.png)

ここで編集を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/0bc2a12d-067f-76ac-3f7d-fdeb3c52f158.png)

下記の通り、赤枠部分の通りとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/1b44b8a8-80c9-732d-e23f-232827a4f4b8.png)

ここでは下記の選択／入力をしています。
選択: 単一認証
匿名アクセスの有効化: チェック
認証タイプ: OAuth 2.0 / OpenID Connect
トークンの場所: ヘッダー
JWTトークン・ヘッダー名: Authorization
認証スキーム: Bearer

下にスクロールして下記の赤枠も選択／入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/0ac16378-7625-98a2-ea70-52bfa867a5e7.png)

こちらは下記の選択／入力をしています。
タイプ: リモートJWKS
JWKS URI: https://[Auth0のDomain]/.well-known/jwks.json

さらにスクロールして下記の赤枠も選択／入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/92d04d5a-3ab3-a8cc-a433-4ad2fe0efe19.png)

こちらは下記選択／入力をしています。
許可されている発行者: https://[Auth0のDomain]/
許可されているオーディエンス: [Auth0のAPI Audience] *https://oci-apigateway-endpoint

以上で変更の保存を選択したらAPI Gatewayの設定は終了です。

## 3. APIの動作検証

それでは最後にAPIの動作検証をしてみます。

最初にJWTトークンを発行します。

■設定情報
```
[Method] POST
[Endpoint] https://[Auth0のDomain]/oauth/token
[Header] Content-Type: application/json
[Body]
{
  "client_id": "[Auth0のClient ID]",
  "client_secret": "[Auth0のClient Secret]",
  "audience": "[Auth0のAPI Audience]",
  "grant_type": "client_credentials"
}
```

実行すると下記のようなレスポンスが返ってきますので
このaccess_tokenをコピーしておきます。
```
{
    "access_token": "eyJhb...qjGiw",
    "expires_in": 86400,
    "token_type": "Bearer"
}
```

あとはAPI Gatewayのヘッダーにトークンを埋め込むだけで完了です。

■設定情報

```
[Method] POST (任意)
[Endpoint] *API Gatewayのエンドポイント
[Header] 
Content-Type: application/json
authorization: Bearer <トークン>
[Body] *API GatewayのPOSTデータ
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3493138/3a02268a-0794-7ac2-2482-1002cc3d42a6.png)

上記でPOSTすればAPIがコールされます。
※デフォルト設定では10時間経過するとトークンの有効期限が切れて認証エラーとなります。

## おわり
以上、Auth0のJWT認証を使って簡単にAPI Gatewayに認証を実装することができました。