3scaleとOktaを連携してみた

初版: 2018/12/6
著者: 田畑義之, 株式会社日立製作所 (GitHubアカウント: [@y-tabata](https://github.com/y-tabata))
本記事は、あくまで執筆者の見解であり、所属企業及びRed Hatの公式なドキュメントではありません。

# はじめに
2018年10月5日、Red Hat 3scale API Management (以下、3scale)の[バージョン2.3](https://access.redhat.com/documentation/en-us/red_hat_3scale/2.3/html/release_notes/)がリリースされました。2018年5月31日の2.2のリリースから約4か月ぶりの新バージョンです。
本稿では、3scale 2.3で可能になった「Keycloak以外のIdPとの連携機能」を検証すべく、3scaleとOktaを連携してみましたので、ご紹介します。
3scale 2.3の新機能の概要に関しては、「[完全OSSになった3scale 2.3の新機能紹介](https://qiita.com/yo-tabata/items/c91e49364a084fdf09b5)」をご参照ください。

# 3scaleとは
3scaleとは、Red Hat主体で開発が進められているAPI管理製品です。
詳細は、「[OSSベースのAPI管理製品 3scale 2.2を試してみた](https://qiita.com/yo-tabata/items/eb81c5cb324cefa87efc)」の「[3scaleとは](https://qiita.com/yo-tabata/items/eb81c5cb324cefa87efc#3scale%E3%81%A8%E3%81%AF)」をご参照ください。

# Oktaとは
Oktaとは、全世界で使われているID管理をクラウド上で実現するIDaaSです。
詳細は[公式サイト](https://www.okta.com/)をご参照ください。

# 3scaleとOktaを連携させてみる
API管理製品のサードパーティIdP連携機能には、一般的に下記の2つがあります。

-   OpenID Connect Discovery機能
    指定されたIssuerのディスカバリーエンドポイントから、エンドポイント等のIdP情報を取得する機能。

-   Client Synchronization機能
    API管理製品で追加/削除したアプリケーションのクライアントIDとクライアントシークレットを、クライアントレジストレーションエンドポイントを用いて、IdPに同期する機能。

3scale 2.3では、下表の通り、Keycloak以外のIdPに対するOpenID Connect Discovery機能がサポートされました。

|             機能             | Keycloak |            Keycloak以外           |
| :------------------------: | :------: | :-----------------------------: |
| OpenID Connect Discovery機能 |     ○    | ○ <font color="Red">new!</font> |
|  Client Synchronization機能  |     ○    |                ×                |

上記サポート範囲に関しては、[KCS](https://access.redhat.com/solutions/3690151)に詳しい説明があります。また、Client Synchronization機能に関しては、[RFE](https://issues.jboss.org/browse/THREESCALE-1156)が出ていますので、今後のエンハンスに乞うご期待です。

それでは、実際に連携してみましょう。今回は、Oktaを使って、OAuth 2.0のResource Owner Passwordフローを実現してみます。公式ガイドの["Implementing the Resource Owner Password Flow"](https://developer.okta.com/authentication-guide/implementing-authentication/password)を参考に進めます。

## Oktaの認可サーバを立てる
まずはOktaの認可サーバを立てます。Oktaの認可サーバを立てるためには、Oktaのディベロッパアカウントが必要となるので、<https://developer.okta.com/signup/>からサインアップしましょう。下のようなサインアップページが表示されます。

![okta_dev_signup.png](https://qiita-image-store.s3.amazonaws.com/0/267112/3fef3669-0d4f-29cd-b588-cd81dad59536.png)

必要事項を記入し、サインアップに成功すると、OktaのDeveloper Consoleが表示されます。

![dev_console.png](https://qiita-image-store.s3.amazonaws.com/0/267112/643e57a1-d5ae-123b-dfe1-ef587580503f.png)

この時点で、認可サーバの準備は成功です。認可サーバのドメインは、`"dev-XXXXX.oktapreview.com"`です。

## 3scaleにOpenID Connect Issuerを設定する
3scaleのIntegrationビューで、認可サーバのIssuer URIをOpenID Connect Issuerに設定します。

![integration_issuer.png](https://qiita-image-store.s3.amazonaws.com/0/267112/96f06bab-0871-8a02-cce6-70657335c3e5.png)

認可サーバのIssuer URIは、OktaのDeveloper Consoleの[API]タブの[Authorization Servers]から辿ることができます。ディベロッパアカウントの作成によって作られた認可サーバの名前は、`"default"`です。したがって、Issuer URIの形式は、`"https://dev-XXXXX.oktapreview.com/oauth2/default"`です。

![okta_issuer.png](https://qiita-image-store.s3.amazonaws.com/0/267112/4403e28d-0647-4a62-09eb-c484cec1551d.png)

ちなみに、認可サーバのドメイン`"dev-XXXXX.oktapreview.com"`とDeveloper Consoleのドメイン`"dev-XXXXX-admin.oktapreview.com"`は異なるので、誤ってDeveloper ConsoleのドメインをOpenID Connect Issuerに指定しないように注意しましょう。

## Oktaの認可サーバにアプリケーションを追加する
3scale 2.3では、Keycloak以外のIdPに対するClient Synchronization機能は未サポートのため、手動でOktaの認可サーバにアプリケーションを追加する必要があります。

アプリケーションは、Developer Consoleの[Applications]タブの[Add Application]ボタンから追加することができます。[Add Application]ボタンを押すと、下のようなページが表示されます。

![create_new_application1.png](https://qiita-image-store.s3.amazonaws.com/0/267112/75c11d62-4f93-911b-0125-2be1c4da5a21.png)

プラットフォームを選択します。ここでは特にこだわりはないので、今回は[Native]を選択します。

![create_new_application2.png](https://qiita-image-store.s3.amazonaws.com/0/267112/ce0f56e2-a421-04f9-4b66-175f79a6236d.png)

[Grant type allowed]は、デフォルトでは[Authorization Code]のみにチェックが入っています。今回はResource Owner Passwordフローを実現するので、[Resource Owner Password]にチェックを入れます。

以上でアプリケーションが追加されました。デフォルトでは、クライアント認証方法としてProof Key for Code Exchange (PKCE)が選択されていますが、3scaleと連携するためには、クライアントシークレットを用いた認証方法に変更する必要があります。
[Client Credentials]の[Edit]ボタンを押し、[Client authentication]として、[Use Client Authentication]を選択します。[Save]ボタンを押すと、下のように、クライアントシークレットが表示されます。

![client_credentials.png](https://qiita-image-store.s3.amazonaws.com/0/267112/7bed7c94-4226-92af-4ac6-37e265c5d4da.png)

## Oktaが発行するアクセストークンをカスタマイズする
3scaleは、クライアント認証にアクセストークンのazpクレームを用います。azpクレームがない場合は、audクレームを用います。そのため、3scaleと連携するためには、azpクレームまたはaudクレームにクライアントIDを格納する必要があります。
デフォルトでは、認可サーバ`"default"`が発行するアクセストークンにはazpクレームはなく、またaudクレームには、`"api://default"`という値が格納されています。

ここではazpクレームにクライアントIDを格納するように、アクセストークンをカスタマイズします。
azpクレームを追加するためには、Developer Consoleの[API]タブの[Authorization Servers]からdefault認可サーバを選択し、[Claims]タブの[Add Claim]ボタンを押します。

![add_claim.png](https://qiita-image-store.s3.amazonaws.com/0/267112/1ac013cf-eb39-05e4-3ac4-069dbb88580a.png)

アクセストークンのazpクレームにクライアントIDを設定します。

![claims.png](https://qiita-image-store.s3.amazonaws.com/0/267112/b901b10d-9eda-3345-5c31-824a6845d7a7.png)

azpクレームにクライアントIDを格納するようにカスタマイズすることができました。

## 3scaleにアプリケーションを追加する
3scaleにアプリケーションを追加します。3scaleでは、管理者ポータルを用いたアプリケーション追加とAccount Management APIを用いたアプリケーション追加に対応していますが、管理者ポータルを用いたアプリケーション追加機能では、クライアントシークレットを指定できないので、ここではAccount Management APIを用いて、アプリケーションを追加します。`"application_id"`にクライアントIDを、`"application_key"`にクライアントシークレットを指定します。

![application_create.png](https://qiita-image-store.s3.amazonaws.com/0/267112/9128de58-cb3c-819d-973e-7670bfb28c2c.png)

`201`が返ってきたら、アプリケーションの追加に成功です。

## トークンを発行する
早速トークンを発行してみましょう。

```bash
curl -X POST https://dev-XXXXX.oktapreview.com/oauth2/default/v1/token
-H 'Content-Type:application/x-www-form-urlencoded'
-d 'grant_type=password&username=<ユーザ名>&password=<パスワード>
&client_id=<クライアントID>&client_secret=<クライアントシークレット>
&scope=openid'
```

下のようなレスポンスが取得できます。

```json
{
  "access_token":"<アクセストークン>",
  "token_type":"Bearer",
  "expires_in":3600,
  "scope":"openid",
  "id_token":"<IDトークン>"
}
```

## APIをコールする
取得したアクセストークンを用いて、APIをコールしてみましょう。

```bash
curl <API> -H 'Authorization:Bearer <アクセストークン>'
```

# おわりに
本稿では、3scaleの「Keycloak以外のIdPとの連携機能」を紹介しました。
APIcastがJWKをサポートしたことにより、Okta以外にも様々なIdPとの連携が可能になりました。是非お試しください。