OAuthで「記名式」トークンを使うもう一つの方法

みなさまご無沙汰しております。
毎年、4月1日には、ジョークだけど実は使えるかもな規格を書こうとしているのですが、今年も書けずにいつの間にやら4月も3分の1が過ぎてしまいました。結局のところ、今年は何に忙しくしていたかというと、OAuthで「記名式」トークンを使う方法を規格化しようとしていて時間が経ってしまいました。

「記名式」って何のことやらと思いますよね?説明しましょう。

通常のOAuthのトークンは「ベアラ(bearer)・トークン」と言います。ベアラ(bearer)とは、「bear (持ってきた)+ er(人)」ですので、「持参人」となります。トークンも日本では馴染みのない単語ですが、これは「切符」のことです。昔の地下鉄などでは、切符の代わりに「トークン」というコインを改札機に入れて通過していました。今でもトロントの地下鉄などはそうです。ですから、ベアラ・トークンと言うと難しく感じますが、日本語にすれば「持参人切符」ということになります。持ってきたのが誰であっても、その切符が有効ならば中に入れるのです。日本の電車の切符は基本的にこのタイプですね。

このタイプの切符の問題点は、落としたり盗まれたりすると、それが使われてしまうということです。

これに対して、「記名式」の切符というものがあります。国際線のボーディングパスなどがこれに当たります。ボーディングパスにはあなたの名前が書いてあるはずです。そして、ゲートでは、その名前とあなたのパスポートが一致するかを確認します。(同時に、あなたの顔とパスポートの写真が一致するかもチェックされます。)「記名式」ですから、誰かがそのボーディングパスを盗んでも、それを使うことはできません。彼は、ボーディングパスと対に成っているパスポートを持っていないからです。(パスポートも一緒に落としたとしても、今度は顔写真が問題になります。)このように「記名式切符」は盗難や紛失に強いので、「持参人切符」よりもセキュリティレベルが高いとされます。

この記名式切符にあたるOAuth Tokenの作り方を記述する文書を大急ぎで書いたのが、OAuth JWT Proof of Possession (OAuth JPoP) となります。この文書は、RFC7800に記載されている全ての方式に対応する他、『Mutual X.509 Transport Layer Security (TLS) Authentication for OAuth Clients』が想定するものにも対応するように書かれていました。ただ、これだとオプションの数が多くなりすぎますし、一気通貫で使うには、両方の文書から正しい部分を抜き出して使う必要があって、いかにも不便でした。そこで、IETF 98 Chicago の会場でサイドミーティングを持ちまして、これら2つの必要な部分を抜き出してくっつけてしまうことになりました。そうしてできたのが、『Mutual TLS Profiles for OAuth Clients1です。

Mutual TLS Profiles for OAuth Clients』の仕組みは簡単です。まず、ClientはToken Endpointに対してMutual TLSクライアント認証をします。すると、OAuth Serverは、ここで使われたX.509証明書をTLSスタックから取り出して、そのHashを返すAccess Tokenと結びつけてとっておきます。Clientは次にリソースにアクセスしますが、この時もMutual TLSクライアント認証をします。リソースは、この時使われた証明書のハッシュと、Access Tokenに結び付けられた証明書のハッシュが等しいことを検証しなければなりません。この方法は任意ですが、その1つのやり方としては、Access TokenをJWT形式にしておいて、その中に証明書のハッシュを埋め込んでしまうことです。つまり、証明書のハッシュが、上記のボーディングパスの例で言うところの「名前」に当たり、相互TLS認証に使ったX.509証明書がパスポート、そして、対応する秘密鍵(=あなたしか持っていないもの)が、あなたの「顔」にあたるわけですね。ざっくり言うとですが。

この方式の良いところは、OAuth Client自体は殆ど何も変えなくて良いというところです。対応しなければならないのはサーバ側という事になります。
一方で、リスクもあります。Client側からは、Serverがそのトークンを「持参人切符」として扱ったのか「記名式切符」として扱ったのかわからないのです。どちらを使ったかによってリスクレベルが変わりますので、Client自身のリスク管理には、その情報が必要です。ですので、この方式を使う場合は、同じリソースURIは、「持参人切符」は取り扱ってはならないということになります2。本来は、異なるAuthorization Schemeを使うべきなんですが、Bearerスキーマをそのまま使うことにしたのは、英国のOpen Bankingでの採用のしやすさに配慮した結果です3

一方のOAuth JPoPですが、これも徐々に進んでいくと思います。と言うのは、TLSが当該OAuthシステムのセキュリティドメイン外でterminateされる場合がままありまして、そのようなときには、TLSに依存しないでend to endでの保護をしたくなるわけです。このユースケースはマイクロソフトが出すということでしたので、それが出てきてからゆったりと進めていくような形になるかと思います。

え、ところで何で「もう一つの」なのかですって?

実は、このドラフトを書く前に、主流に成るだろうと多くの人が思っていた方式がありました。Token Bindingです。今でも将来的にはこちらが主流になるだろうと考えています。しかし、これにはTLSスタックを入れ替えたりだとか、インフラレイヤーの変更を伴って、アプリケーションレイヤーだけでは解決できないのですね。そのため、「今使いたいのに使えない」という悲鳴があがりまして、だったらこうしたら、というのがこれらのドラフトなのです。だから「もう一つの」なのです。

ではっ!

脚注

  1. あんまりいい名前では無いな。
  2. ここのところを説明したpull requestを出してあるのだが、Brianがその必要を感じず取り込まれていない。
  3. なので、石を投げないでください…。

コメントを残す

メールアドレスが公開されることはありません。

*

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください