3scaleで実現するOAuth MTLSベースのアクセス制御

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

# はじめに

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)」をご参照ください。
このたび、OAuth MTLSベースのアクセス制御を機能追加する[パッチ](https://github.com/3scale/APIcast/pull/1101)を出し、無事に3scaleにマージされましたのでご紹介します。おそらく、次バージョンの3scale 2.8あたりで、本機能がサポートないしテクノロジープレビューという形で公開されるのではないかと想定しております。

# OAuth MTLSとは

OAuth MTLS (正式には、OAuth 2.0 Mutual TLS Client Authentication and Certificate-Bound Access Tokens)とは、下図のような、トークン横取り攻撃を軽減するための方式です。OAuth Working Groupによって[仕様化](https://tools.ietf.org/html/draft-ietf-oauth-mtls-13)されています(Internet-Draft段階)。
![token_interception_attack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267112/aa4e8d96-4705-082e-7afd-d97565c79f7a.png)

Bearer Tokenの場合、トークンの所持者以外の第三者でもトークンを行使できるという課題があるため、上図のようにトークンさえ横取りしてしまえば、攻撃者はリソースに自由にアクセスできるようになります。
一方、OAuth MTLSが実現するHolder-of-Key Tokenの場合、トークンの所持者以外の第三者がトークンを行使しようとした場合これを検知できます。

OAuth MTLSの具体的な方式は下図です。
![oauth_mtls.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267112/96015734-7782-ba36-586b-971a02456b1f.png)

クライアントは、トークンリクエスト時に、認可サーバに対してクライアント証明書を送付します。認可サーバは、発行するトークンに、クライアント証明書のハッシュ値を含めます。
クライアントは、リソースアクセス時に、リソースサーバに対してクライアント証明書を送付します。リソースサーバは、送付されたクライアント証明書のハッシュ値を計算し、トークンに含まれるハッシュ値と一致するかを確認することで、不正アクセスを検知することができます。

OAuth MTLSのより詳しい内容に関しては、「[OAuth 2.0でのHolder-of-Key TokenとKeycloakについて](https://qiita.com/tnorimat/items/ee45d2cb08d799a7d4a6)」という記事が参考になりますので、そちらをご参考ください。

# KeycloakにおけるOAuth MTLSの対応

「[OAuth 2.0でのHolder-of-Key TokenとKeycloakについて](https://qiita.com/tnorimat/items/ee45d2cb08d799a7d4a6)」という記事に記載されている通り、Keycloakでは「OAuth 2 Certificate Bound Access Tokens」という名称でバージョン4.0.0.FinalからOAuth MTLSがサポートされています。
しかし、Keycloakは認可サーバですので、あくまで実現できるのは、上図における「トークンにクライアント証明書のハッシュ値を含める」という部分のみである点に注意してください。

# 3scaleで実現するOAuth MTLSベースのアクセス制御

トークンの所持者以外の第三者によるトークンの行使を検知するためには、APIゲートウェイないしリソースサーバにおける、OAuth MTLSベースのアクセス制御(つまり、トークンに含まれるハッシュ値と送付されたクライアント証明書のハッシュ値の一致を確認する処理)が不可欠です。
[PR #1101](https://github.com/3scale/APIcast/pull/1101)では、当該処理をポリシーとして作り込みました。

# OAuth MTLSポリシーを使ってみよう！

OAuth MTLSポリシーは、現在[GitHub上](https://github.com/3scale/APIcast/tree/master/gateway/src/apicast/policy/oauth_mtls)にしか存在しないため、使用するためには独自ポリシーとしてインポートする必要があります。インポート方法に関しては、ThinkITで連載している「[フルセットのOSSベースAPI管理基盤3scale入門](https://thinkit.co.jp/series/8697)」の第4回「[3scaleのAPIゲートウェイの機能を拡張してみよう！](https://thinkit.co.jp/article/16544)」の「独自開発ポリシーのインポート」の部分をご参考ください。

インポートに成功すると、下図のようにOAuth MTLSポリシーがポリシー一覧に表示されます。
![original_policy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267112/11555b17-9ad1-f806-625c-0e42fbcec1b4.png)

ポリシー一覧から「OAuth 2.0 Mutual TLS Client Authentication」を選択することで、OAuth MTLSポリシーを設定できます。

実際に動作を確認してみましょう。

```bash
# 事前にクライアント証明書のハッシュ値が格納されたアクセストークンを発行し、環境変数tokenに格納。

$ curl -v "hello-3scale-apicast-production.192.168.99.113.nip.io:443/myapp/api/hello" -H "Authorization: Bearer $token"
< HTTP/1.1 403 Forbidden # クライアント証明書なしでは認証エラー
Authentication failed
$ curl -v --key ./key.pem --cert ./cert.pem "hello-3scale-apicast-production.192.168.99.113.nip.io:443/myapp/api/hello" -H "Authorization: Bearer $token"
< HTTP/1.1 200 OK # クライアント証明書あり、かつアクセストークンに格納されたクライアント証明書(ハッシュ値)と一致した場合はOK
```

# おわりに

本稿では、3scaleで実現するOAuth MTLSベースのアクセス制御を紹介しました。
現在、APIを公開するシステムが増えている中で、APIを公開して情報漏えい等の危険にさらされないようにするための、APIセキュリティの重要性が増しており、その中でもOAuth MTLS (Holder-of-Key Token)は注目を浴びている技術の一つです。
OAuth MTLSベースのアクセス制御を実装するAPIゲートウェイというのは非常にレアかと思いますので、この機会に是非3scaleをお試しください。