「なぜ OpenID Connect にはトークンが二種類あるの?」という質問を、たびたびもらいます。そこにはいくつかの設計上の要件があり、わたしたちは仕様策定のなかで議論してきました。
1 - RP (リライング・パーティ) からの要件は、ログイン後のユーザー・インタフェースの簡便なカスタマイゼーションです。
2 - Salesforce や他の IdP には、既にユーザー情報 (user-info) エンドポイントとその他保護リソースが存在しており、これらに対するアクセスをスコープとしてアクセス・トークンに追加したいと考えています。
3 - T-Mobile 他では、署名つきトークン (signed token) にスコープを含め、エンドポイントに渡しています。
4 - Google 他の要件は、Connect が複数種類のクライアント、とくにブラウザ内の Ajax をサポートすることでした。
5 - リソースごとに毎回ユーザーに認可を求めることはできない、ということには、全員が同意しました。
まず、要件 1 を満たすには、RP に対して user_id の入った署名つきトークンを送る必要があり、そして、そのトークンは認可サーバー (Authorization Server) からのレスポンスに含まれていなくてはないことがわかります。
よって、id_token が必要なのです。Facebook には、署名つきリクエスト (signed request) という独自形式のしくみがあります。わたしたちコミュニティは、JWT という、より汎用的でオープンな標準を考案しました。これは署名つきリクエストと似ており、加えて暗号化もサポートします。
OAuth 2.0 の手法のひとつとして、異なる保護リソースに対して複数のトークンを生成することを、ダウンスコーピング (down-scoping) といいます。各リソースごとに、認可リクエストにおいて、複数のスコープを要求するのです。
認可サーバーは、すべてのスコープに対して有効なリフレッシュ・トークン (Refresh Token) を提供します。そしてこのトークンをトークン・エンドポイントに提示し、全てではなく一部のスコープに対する新しいトークンを要求することになります。
ダウンスコーピングにはいくつか問題がありますが、最も大きなものは、これが code フローでしか使えないため、要件 1 と 4 を満たせないということです。
これに対し、いくつかの選択肢があります:
id_token をアクセス・トークンとして用いる方法では、要件 2 を満たせませんし、長い期間有効となるアクセス・トークンがセッション・クッキーとなってブラウザーに保管されるかもしれないという、新たなセキュリティ上の懸念が生じます。
アクセス・トークンを id_token に含めるやりかたは、Facebook Connect が選択した方法と同じです。要件 1 と 2 に対してはうまくいきますが、やはりいくつか問題があります。それは、id_token をセッション管理に用いたいと RP が考えた場合です。そのためにはセッション・クッキーに長期間有効なアクセス・トークンを埋め込むことになりますが、id_token のサイズがかなり大きくなってしまいます。要件 3 は満たせたとしても、アクセス・トークンにはその他のユーザー情報を載せることができません。
認可サーバーからのレスポンスとしてふたつのトークンを返却することで、すべての要件を満たすことができます。
一般的に、 OAuth 2.0 の implicitフローを用いる RP では、あらかじめ登録されたリダイレクト・エンドポイントに認可サーバーから返却されたレスポンスの中から、id_token を取り出します。次に署名を検証し、そこに含まれる user_id を用いて Web ページをカスタマイズする一方、もし必要であればさらに、OAuth 2.0 によって認証されたリクエストを user_info エンドポイントに対して行います。これにより、再度アクセスしてきたユーザーのログイン処理を、RP が許容することのできる時間内に行うことができるようになります。新規ユーザーの場合であっても、比較して少し時間はかかりますが、プロファイル情報を取得することが可能です。
OpenID Connect に関連して、新規の OAuth 2.0 response_type が複数登録されています。これによって、クライアントからの様々な要求を満たすためのトークンの返却方法に、いくつかの選択肢が生まれることになります。
id_token を活用した、セッション管理およびシングル・ログアウト拡張についても、現在検討中です。
トークンを分離することについては、現在 OASIS の SAML WG がセッション・トークン・プロファイルの公開レビューを行っており、おそらくそこで部分的にですが検証が行われることになるでしょう。
トークンをひとつにすることは一見魅力的ですが、たくさんの理由から、わたしたちのユースケースの多くに対してはうまくいきません。わたしも単一の JWT トークンを主張していた一人ですが、結局負けました。
近いうちに、OpenID Connect の response_typeについて投稿したいと思います。
John B.
(出典: thread-safe.com)