2018年10月23日火曜日

[Azure AD]認可コード再利用禁止ポリシーの現状

こんにちは、富士榮です。

今月(2018年10月)のはじめに突如アナウンスされた「Azure ADのOAuth2.0におけるAuthorization Codeの再利用禁止」について現状を確認してみます。
というか、まさか認可コードが再利用できるとは思っていなかったので、アナウンスされるまで気が付きませんでした・・・。
アナウンス
https://blogs.technet.microsoft.com/jpazureid/2018/10/04/authorization-code-reuse/ 
リリースノート
https://docs.microsoft.com/ja-jp/azure/active-directory/fundamentals/whats-new#change-notice-authorization-codes-will-no-longer-be-available-for-reuse

◆アナウンスされた内容

詳しくは上記リンクを見て頂ければと思いますが、ざっくり言うと以下の事項がアナウンスされました。

  • 従来はAzure ADのOAuth2.0/Code Flowで認可エンドポイントから発行される認可コード(Authorization Code。MSの日本語訳だと「承認コード」)の再利用が出来てしまう状態だった
  • RFC 6749に準拠するため、認可コードの再利用を禁止することにした
  • 新たなポリシーはv1/v2の両方のエンドポイントに対して適用される
  • 新たなポリシーの適用は2018年10月10日から開始される
  • ポリシー適用後は認可コードを再利用しようとすると「invalid_grant」エラーが出るので、アクセストークンを取得し直す場合はリフレッシュトークンを利用するように既存のコードを修正すること


◆RFC 6749における認可コードの取り扱い

RFC 6749をみると、認可コードの取り扱いは以下の様に記載されています。

  1. 認可コードは認可サーバーによって許可される. 漏洩のリスクを軽減するため, 認可コードは発行されてから短期間で無効にしなければならない (MUST)
  2. 認可コードの有効期限は最大でも10分を推奨する (RECOMMENDED)
  3. クライアントは2回以上認可コードを使用してはならない (MUST NOT)
  4. もし認可コードが2回以上使用された場合は, 認可サーバーはリクエストを拒否しなければならず (MUST)
  5. この認可コードを基に発行されたこれまでのすべてのトークンを無効化すべきである (SHOULD)
  6. 認可コードはクライアント識別子とリダイレクトURIに紐づく.

出典)OpenIDファウンデーション・ジャパン翻訳WG
https://openid-foundation-japan.github.io/rfc6749.ja.html#code-authz-resp

この3~5番目のあたりですね。

なお、RFCにおけるMUST NOT(してはならない)の定義は「この語句、もしくは「することはない( SHALL NOT )」は、その規定が当該仕様の絶対的な禁止事項であることを意味します。」となっています。(強調は筆者による)
出典)IPA翻訳:RFC において要請の程度を示すために用いるキーワード
https://www.ipa.go.jp/security/rfc/RFC2119JA.html


・・・

「絶対的な禁止事項」って明確に書いてあるのに無視したんですね。
マイクロソフトのアナウンスを見ると、以下の注釈が付いていますので、よく理解せずに実装をしてしまったアプリへの配慮があったということなんだとは思いますが。
「アプリの破損を最小限に抑えるための試みにおいて、このパターンに依存していて、サインインが 1 日 10 回より多いアプリには、例外が与えられてきました。」


ちなみに、同じくRECOMMENDEDになっている2番の認可コードの有効期限はAzure ADでは15分です。

こちらもRFC的な意味合いを見ると「この語句もしくは「推奨される( RECOMMENDED )」という形容表現は、 特定の状況下では、特定の項目を無視する正当な理由が存在するかもしれませんが、 異なる選択をする前に、当該項目の示唆するところを十分に理解し、 慎重に重要性を判断しなければならない、ということを意味します。」(同じく強調は筆者による)とあるので、ちゃんと正当な理由の存在をもって慎重に重要性を判断したんだと信じたいところです。

15分になっている理由として、アナウンスの中の別の文章を見ると、「従来は 15 分間 (10 分間の有効期限に加えて時刻ずれを考慮して 5 分の猶予が与えられている) 有効です」とあります。時刻ずれを考慮したんですね。
ちょっと待て。。。発行から15分という話なら時刻ずれ関係なくないか?認可コードの中にタイムスタンプが埋め込まれている?唯一、Azure AD B2Cが発行する認可コードがJWTっぽいのでデコードしてみましたが、ペイロードがなくタイムスタンプ情報が入っているようには見えないんですが・・・。それとも認可エンドポイントとトークンエンドポイントが別のサーバで動いていて時刻同期がされていない、ということ?うーむ。

◆取り敢えず動作の確認

アナウンスでは10月10日から動作が変わる、ということだったので10月4日の段階で動作を確認してみました。
対象は、v1/v2/B2Cの3パターンです。

v1/v2はChrome ExtensionのAdvanced REST Clientで認可コードをトークンエンドポイントへ何度投げ込んでもIDトークン、アクセストークン、リフレッシュトークンが返ってきます。

15分経過すると有効期限切れのエラーが出ます。10分か15分かは置いておいてこちらは正しい挙動ですね。


尚、Azure AD B2Cの場合はAdvanced REST Clientだと上手く動かないことがあるので(Client Secretに記号が含まれることが多いから?)、Postmanを使って動作確認をします。

ツールは違えど、v1/v2と同じ動きです。


◆10月10日を超えたらどうなったのか?

ということで本題です。
10月10日を超えたので、どのような動きになったのか確認してみましょう。

結論から言いますと、アナウンス通りに認可コードの再利用が禁止されたのはv2エンドポイントだけでした。v1とAzure AD B2Cでは相変わらず認可コードが再利用できてしまいました。何か事情があったんでしょうか。。。

以下、v2エンドポイントで認可コードを再利用した際に出るエラーです。

「OAuth2 Authorization code was already redeemed」ってあるので、ちゃんと再利用だと判断されているようです。



いずれにしても認可コードの再利用を前提としたコードがあれば早めに書き直しましょう。v1/B2Cもそのうち再利用禁止になると思いますので。

2018年10月4日木曜日

Windows 10 October 2018 UpdateのEdgeでWebAuthnを試す

こんにちは、富士榮です。

昨日は #idcon vol. 25 「fidcon 勝手に Meetup」が品川のマイクロソフトで開催されていたので、参加してきました。なんともタイミングの良い?ことに、ちょうど Edge が正式に WebAuthn に対応した、Windows 10 October 2018 Update がリリースされたタイミングと重なりました。

ローンチのアナウンス
https://blogs.windows.com/windowsexperience/2018/10/02/how-to-get-the-windows-10-october-2018-update/


ちょうど日本マイクロソフトの物江さんが Edge の WebAuthn のセッションでデモをされたりもしており、なんというタイミング?!ということで、何か持っているんだと思います。

私はセッション中に Windows Update が降ってきてついつい再起動してしまったので、イベント終了後も開きっぱなしの Macbook Air を持ったまま品川の街を歩くハメになりましたが・・・


ということで、Edge のWebAuthn を試してみましょう。
手元にあったのは、FIDO2 に対応した Yubikey Security Key(青い奴)とマウスコンピュータの指紋認証用の USB ドングルなので、この辺りを使ってみます。

右:Yubico セキュリティキー
左:マウスコンピュータ FP01

テスト用のサイトとして、https://webauthn.org/ を使います。
内容としては、

  1. ユーザとデバイスを登録する
  2. ログインする

というシンプルなモノですが、Debug Windows でプロトコルの詳細なメッセージが確認できるので非常に便利です。
ちょうど最後のセッションで @shiroica さんがお話ししてくださった各パラメータの紹介が非常に役に立ちます。


ちなみにこのテストサイトではあまり細かいパラメータが触れるわけではなく、authenticatorSelection の指定は出来ず、attestation も direct 固定となっています。
この辺りを試すには https://webauthn.io/ を使った方が良いかも知れません。
ちなみに Google の @agektmr さんの話では、Google としてはエンタープライズのシナリオを除き attestation は none がお奨めとのことです。(会社が指定した Authenticator だけを使わせたい、というようなケースですね)

1.ユーザとデバイスを登録する

Register タブで Usernameを指定して Register ボタンを押すだけです。

画面の下の部分の Advanced を開くと実際のメッセージを確認することが出来ます。

PubKeyCredParams で -7 と -257 があることから U2F と Windows Hello に対応していることがわかったり、 attestation は direct となっているあたりがわかります。

登録が正常に完了すると OK とステータスが返ってきていることもわかります。

2.ログインする

同じく Login タブを開いてユーザ名を指定、Login ボタンをクリックすると今度はログインのプロセスが実行されます。

尚、Resident-key が使える FIDO2 対応の Authenticator で同じユーザ名で複数回 Registration を行うとログイン時に一覧が出てきます。
(本来は先にユーザ名を指定しているのでキーの特定をした上でログインプロセスが走るのでアカウント選択は出ませんが、同じ名前で登録すると毎回鍵ペアが生成されてしまうみたいです。RPの作りの問題?)

Authenticator で認証します。

ちゃんと webauth.get が成功しています。


もう少し詳しく勉強しないと細かいところはよくわからないので、続きは今晩開催される WebAuthn もくもく会で!
 https://fido2-workshop.connpass.com/event/100944/