ラベル Passkey の投稿を表示しています。 すべての投稿を表示
ラベル Passkey の投稿を表示しています。 すべての投稿を表示

2024年11月27日水曜日

パスキーの情報をRPとパスキープロバイダで同期する話

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

少し前にGoogleのえーじさんがPasskeyのSingal APIについて記事を書いていました。


要するに、RP側に登録済みのパスキーの情報と、ユーザ側に存在しているパスキーの情報がずれないようにするためにSignalを使って検知〜同期をできるようにしましょう、という話ですね。

よくあるケースだとRP側にパスキーを登録したのはいいんだけど、ブラウザ側でパスキーを削除してしまった、もしくはその逆をしてしまった、という場合に認証情報が送れない、もしくは送っても登録情報が削除されていて認証できない、という状態を防ぎましょう、ってことかと。

ただ、Signal APIではこのシナリオのうちの前者には対応できず、後者への対応のみとなるみたいです。つまり、RP側がSignal APIに対応していればパスキープロバイダへ通知はできるけど、パスキープロバイダ側で削除した情報はRPへは通知されない、ってことですね。

仕様はW3CのGithubで公開されているので時間を見て読んでみようと思います。(ほぼ1年前に作ったテスト用の実装へも反映したいですね)

2024年10月17日木曜日

Credential Exchange Format/Protocolの新Working draft

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

Authenticate 2024が10/14-16で開催されましたね。
各社イベントに向けて色々と実装をして発表にこぎつける、というのは世の常ですが、これはもちろんスペックライターについても同じようです。



ということで満を持して発表されましたね。

  • Credential Exchange Format
  • Credential Exchange Protocol
これらの新しいWorking draftが今週金曜日18日にリリースされるようです。

以前から触れていたCredential Exchange Specificationsですがパスキーのインポート・エクスポートのための仕様という冠で登場って感じですかね。

同期パスキーなど色々と新しい考え方が盛り込まれてきたFIDO関係ですが、NISTを含めちゃんと利用ガイドを整えていかないといけませんね。(まぁ、そもそも鍵はデバイスから出ないっていうのが原則だったわけなので、考え方を変えていかないといけません)

2024年5月22日水曜日

PlayStationでパスキーを使う(リカバリ時にパスワードを生成する必要がなくなりました)

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

今週は大阪でFIDO Allianceのセミナ〜Plenaryですね。ちょうど昨日、私もPlenaryでゲストスピーカーとしてOpenID FoundationおよびOpenIDファウンデーションジャパンとFIDO Allianceとの協業について話をしました。

さて、そんなFIDOイベントの中でPlayStationアカウントのパスキー対応のアップデートについて話がありました。(4月ごろアップデートされたそうです)

このブログでも以前書いたものですね。

https://idmlab.eidentity.jp/2024/02/playstation.html

https://idmlab.eidentity.jp/2024/02/playstation_01288657578.html

ポイントは、これまでアカウントのリカバリを行う際に一旦パスワードを生成してからパスキーの登録、パスワードが無効化される、という流れだったところをダイレクトにパスキーを生成できるようになった、というところです。

と言うことで試してみました。

パスワード忘れ、パスキーにアクセスできない人はこちら、ということでリカバリプロセスに入ります。

アカウントの回復を開始します。
登録済みメールアドレスを入れて回復プロセスが開始されます。セキュリティの質問か生年月日を入れることになりますが、ここは変わらないですね。あんまり意味はなさそうなので単なる心理的障壁を作っているだけなのかもしれません。

ここが更新されたポイントですね。パスワードを生成、に加えてパスキーを生成のメニューができています。

ここでパスキーを生成すると無事にパスキーでのログインが回復されました。



アカウントのリカバリプロセスのAssurance Levelの低下は大きな問題につながる可能性が高いので、一時的にでもパスワードのような強度の低い認証手段に落とさずにリカバリできるのはとてもいいですね。



2024年5月19日日曜日

NIST SP800-63B-3の同期可能クレデンシャルに関する追補版を読む(7)

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

NIST SP 800-63B-3の追補版も最後のまとめ部分を残すのみです。

早速ですが本文書でどのように結論づけているのかをみていきましょう

同期可能な認証器は、認証の状況、特に多要素暗号認証子の使用における実質的な技術的変化を示すものである。暗号鍵の複製とクラウド・インフラへの保存を許可することに関連するトレードオフの 評価は、必然的に行われることになる。このことは、明確なリスク(認証鍵に対する企業管理の喪失など)をもたらすが、同時に、 一般市民や企業にとっての主要な脅威ベクトルを排除する、便利でフィッシングに強い認証機能への道筋を提供する。同期可能な認証器は、すべてのユースケースに適しているわけではない。しかし、本補足文書に含まれるガイドラインに沿った方法で導入される場合、AAL2 リスク軽減策との整合性を達成し、フィッシング耐性認証の採用をより広範に促進することができる。

企業等で利用する場合は鍵が制御外のファブリック(iCloudなど)に保存されることによるリスクがありますが、一般ユーザのシナリオではフィッシング耐性のない認証器を使うよりはマシっていうことなんでしょうねぇ。要はユースケースに応じたリスク分析をちゃんとやろうねっていうNISTのガイドラインの根本は変わらないわけで。

この文書は、既存のデジタル・アイデンティティ・ガイドラインに付随するものであり、各省庁 が十分な情報に基づきリスクベースの決定を行い、適切な場合には最新の業界イノベーション を統合するための情報を提供する。

改めて本文書は既存のガイドラインの付随文書であることを強調し、先に書いたとおりちゃんとしたリスク分析に則って対策を考えましょう、ということです。

ということでこれで一通り見てきたわけですが、私的なまとめとしては、

  • 同期と共有は違うぞ
  • 同期を許容する場合はバックエンドの同期ファブリックの信頼性も評価しないとだめ
  • 統制レベルを上げる場合は同期を不許可にするようにMDMなどで制御することも必要
  • ただ、かといってフィッシング耐性がない認証器を許容するよりはマシな場合もある
  • 結局ユースケースごとにリスク評価をしましょうね
  • その意味でこのガイドライン追補版では新たなタイプの認証器の特徴とリスクなどをまとめたのでちゃんと導入するように
ということくらいでしょうか。


2024年5月18日土曜日

NIST SP800-63B-3の同期可能クレデンシャルに関する追補版を読む(6)

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

少し間が開きましたがNIST SP 800-63B-3の追補版の続きです。

今回は同期と共有は違うぞ!という話のうちの共有の部分です。1回目にも書きましたがAppleの共有パスワードグループの話などもありますので、非常に重要な部分だと思います。

サイバーセキュリティ・ガイドラインは、歴史的に、ユーザ間で認証器を共有しないよう警告してきた。このガイダンスにもかかわらず、一部のユーザ・グループやアプリケーションでは、個人がデジタル・アカウントへのアクセスを共有できるようにするために、認証器とパスワードの共有が行われている。

表 3 に示すように、一部の同期可能な認証器の実装は、このようなユーザの行動を受け入れ、 異なるユーザ間で認証キーを共有する方法を確立している。さらに、一部の実装は、一般的なサービスにおいて、パスワード共有に代わる便利で より安全な方法として、同期可能な認証器の共有を積極的に推奨している。 

言われてますよ、Appleさん。。

企業ユースケースの場合、鍵の共有に関する懸念は、鍵が承認されたデバイスや同期 ファブリックから移動されることを制限するデバイス管理技術を使用することで、効果的に緩和することができる。しかし、公衆向けのユースケースでは、同様の緩和策は現在のところ利用できないため、 リライングパーティは、同期可能な認証プロバイダが採用する共有モデルに依存することになる。公衆向けアプリケーションの所有者は、共有認証器に関連するリスクを認識する必要がある。公衆と対話する場合、機関は、ユーザがどの特定の認証器を使用しているのかについて限られ た可視性しか持たないため、すべての同期可能な認証器が共有の対象となる可能性があることを想定する必要がある。多くの共有モデルには、リスクを最小化する実質的な制御(例えば、共有を許可するためにデバイス間の近接を要求する)があるが、他の実装はそれほど制限的ではない。

やっぱり共有を制御する方法とセットになっていることが必要なんじゃないかと思いますね。この辺りの判断をリライングパーティに全部任せちゃうのは実質不可能だと思いますし。

この新しいクラスの認証者がもたらす共有のリスクは、特別なものではない。実際には、すべての AAL2 認証タイプに適用され、中には同期可能な認証タイプより弱いものもある。AAL2 のどの認証子も、それを共有しようとするユーザによって共有される可能性がある。ユーザは、パスワード、OTP、帯域外認証子、さらにはプッシュ認証イベントを積極的に共有したり、被指名人(正式か否かを問わない)がエンドユーザに代わって認証を行うことを許可したりすることができる。

各省庁は、直面する特定のリスク、脅威、およびユーザビリティの考慮事項に基づいて、アプリ ケーションにどの認証手段を受け入れるかを決定する。同期可能な認証方式は、AAL2 までの実装を求めるアプリケーションの新しいオプションとして提供されるかもしれず、他の認証方式と同様に、この技術のトレードオフは、セキュリティ、プライバシー、公平性、およびユーザビリティに対する期待される結果に基づいて、うまくバランスをとるべきである。

そろそろこのレポートもおしまいです。

というか早くSP800-63-4の次のドラフトが出て欲しいですね。

 

2024年5月9日木曜日

NIST SP800-63B-3の同期可能クレデンシャルに関する追補版を読む(4)

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

引き続きNIST SP800-63B-3の同期可能な認証器に関する追補版についてみていきましょう。


今回は実際にインプリメンテーションを行う場合の考慮事項や要求事項についてです。

Implementation Considerations and Requirements

同期可能な認証器は、W3CのWebAuthn仕様に基づいて構築されており、共通のデータ構造、チャレンジ・レスポンス暗号プロトコル、公開鍵認証情報を活用するためのAPIを提供している。この仕様は柔軟で適応性があるため、WebAuthnクレデンシャルのすべてのデプロイが連邦政府機関の実装要件を満たすとは限らない。
この仕様には一連の「フラグ」があり、依拠当事者(RP)アプリケーションは、認証イベ ントの追加コンテキストを提供し、それが RPのアクセス・ポリシーに適合するかどうかを判断す るために、認証者に要求することができる。本節では、RPとして活動する連邦機関が、NIST AAL2 脅威緩和策に適合する同期可能な認証器の実装を構築する際に理解し、問い合わせる必要がある、WebAuthn仕様の特定のフラグについて 説明する。

表2, WebAuthn Level 3 flags
フラグ説明要求事項と推奨事項
User Present(UP)ユーザが認証器と対話したことを確認するための「プレゼンス」テストを示す(例:USBポートに挿入されたハードウェアトークンのタッピング)。連邦機関は、ユーザ提示フラグが設定されていることを確認しなければならない(SHALL)。認証意図をサポートする。
User Verified(UV)利用可能な「ユーザー検証」メソッドのいずれかを使用して、ユーザーが認証者によってローカル認証されたことを示す。連邦機関は、UV が優先されることを示さなければならず(SHALL)、すべてのアサーションは、UV フラグの値を確認するために検査されなければならない(SHALL)。これは、認証器が多要素暗号認証器として扱えるかどうかを示す。ユーザが検証されない場合、機関は、認証イベントに RP 固有の暗記秘密を追加することで、認証器を1要素暗号認証器として扱うことができる。WebAuthn レベル 3 仕様のさらなる拡張により、機関がローカル認証イベントのコンテキストを得ようとする場合、検証方法に関する追加データが提供される。
Backup Eligibility認証器を別のデバイスに同期できるかどうか(すなわち、鍵を別の場所に保存できるかどうか)を示す。同期可能だからといって、同期済みであることを意味しないことに注意。連邦機関は、同期可能な認証器の使用を制限するポリシーを確立する場合、このフラグを使用してもよい。このフラグは、デバイスにバインドされる認証子と、複数のデバイスにクローンされる 認証子を区別するために必要である。
Backup State認証器が別のデバイスに同期されたかどうかを示す。連邦機関は、他のデバイスに同期された認証器に対する制限を確立する場合、このフラグを使用してもよい。公開アプリケーションの場合、連邦政府機関は、ユーザエクスペリエンス上の懸念から、このフラグに基づいて受諾を変更すべきではない(SHOULD NOT)。企業の判断のために、このフラグは、特定のアプリケーションのために同期可能な 認証器の制限をサポートするために使用してもよい[MAY]。

以前パスキー対応の認証機能を実装した際にも出てきたフラグですね。

https://idmlab.eidentity.jp/2024/02/api.html

同期可能かどうかの判断にはBEやBSを使うわけです。アプリによってはこのフラグを見て同期可能な認証器を受け入れるかどうかを決める、と言うことです。

 

表2に示されるフラグに加えて、機関は、実装および受け入れを選択する同期可能な認証器のオリジンおよび機能について、より詳細な情報を得ることを望むかもしれない。FIDO2 WebAuthn のコンテキストにおいて、認証者の中には、特定の認証者の能力および製造者を 判断するために使用できる認証機能をサポートしているものがある。企業ユースケースの場合、各機関は、プラットフォームプロバイダが提供する機能に基づいて、認証機能を実装するべきである(SHOULD)。好ましくは、RP が認証器に関する一意の識別情報を要求するエンタープライズ認証の形をとる。

構成証明(Attestation)は、広範な公衆向けアプリケーションに使用すべきではない(SHOULD NOT)。このような要件(すなわち、構成証明に対応していない場合、一部の一般ユーザの同期可能な認証器をブロックする要件)は、ユーザをショートメッセージサービス(SMS)のワンタイムパスワード(OTP)のような、フィッシングに脆弱な安全性の低い認証オプションに誘導する可能性がある。

この視点は面白いですね。パブリック(共有端末とかのイメージかな?)なアプリケーションで同期可能な認証器を使うとってしまうまずいので同期可能なクレデンシャルをブロックすると言うポリシーを適用すると、手軽な認証手段を実装しがちになる、という話でしょうか?(@Shiroicaさんご指摘ありがとうございます)


RP がフラグおよび認証データを要求しても、認証器は要求された情報をすべて返さないかもしれないし、リソースへのアクセスに要求される期待応答と矛盾する情報を返すかもしれない。したがって、各機関は、同期可能な認証器を使用するユースケースを評価し、返された情報に基づいて適切なアクセスポリシー決定を行うことが決定的に重要である。
こちらも現実論として全ての認証器がちゃんとフラグを返してくるということは期待してはいけない、ちゃんとリスクを含め評価をしてポリシーを決めようね、ということです。これ非常に大事だと思います。


ということでまだ続きますが、今回はここまでです。

2024年5月7日火曜日

NIST SP800-63B-3の同期可能クレデンシャルに関する追補版を読む(3)

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

前回に引き続きNIST SP800-63-3の追補版を見ていきます。

だいぶ中身に入ってきました。
早速読んでいきます。

Updates on the Allowance of Cloning Authentication Keys

SP 800-63B のセクション 5.1.8.1「多要素暗号化ソフトウェア認証機能」は、認証器があるデバイスから別のデバイスへ暗号化認証鍵を「クローン」することを制限している。具体的には、以下のとおりである:

多要素暗号化ソフトウェア認証器は、複数のデバイスへの秘密鍵のクローニングを抑制すべきであり、促進してはならない(SHALL NOT)。

同期可能な認証器は、デバイスや異なるプラットフォーム・プロバイダにまたがって、以前に 登録した認証器へのアクセスをユーザに提供するため、明示的に鍵の複製を促進する。NISTがSP 800-63B-4の初期公開草案(ipd)からこの制限を削除したことで、この現実が認識された。本文書の発行時点で、5.1.8.1 項の上記の記述は、本補足により置き換えられ、本補足に規定される要件に基 づいて導入される同期可能な認証器は、AAL2 で想定される脅威から保護するのに十分であるとみなされるものとする。


そうです、元々のSP 800-63Bでは秘密鍵のクローニングを制限していたわけです。今回の更新でこの点について緩和が行われたわけです。

ただ、そのために満たすべき要件を以下の通り定義しています。

同期可能な認証器のすべての使用に関する一般要件:

  • すべての鍵は、承認された暗号技術を用いて生成されなければならない。
  • デバイスからクローンまたはエクスポートされた秘密鍵は、暗号化された形式でのみ保存されるものとする。
  • すべての認証トランザクションは、デバイス上で生成された、または同期ファブリック(クラウドストレージ など)から復元された暗号鍵を使用して、ローカル・デバイス上で秘密鍵操作を実行しなければならな い。
  • クラウドベースのアカウントに保存された秘密鍵は、認証されたユーザのみがシンクファブリック内の秘密鍵にアクセスできるよう、アクセス制御メカニズムによって保護されなければならない。
  • 同期ファブリック内の秘密鍵へのユーザ・アクセスは、同期された鍵を使用する認証プロトコルの完全性を保持するために、AAL2相当のMFAによって保護されなければならない。
  • これらの一般的要件および同期可能な認証器の使用に関するその他の機関固有の要件は、文書化し、公開ウェブサイトおよびデジタル・サービス・ポリシー(該当する場合)を含め、周知されるも のとする。

ちゃんと認定された暗号技術を使うこと、同期された鍵を使って認証に必要な操作を行う場合はローカルで操作を行うこと(要するにリモート署名なんかはNGってことですね)、秘密鍵へのアクセス制御を行うこと、具体的にはAAL2相当の認証強度で保護されていること、同期可能な認証器を使っていることをポリシーとして公開・周知すること、が記載されています。要は、同期してもいいけどちゃんと認められた方法で管理し、その旨を周知せよ、ということですね。

また、追加要件として以下のについても定義されています。 

連邦企業が同期可能な認証器を使用するための追加要件: 

  • 連邦企業の秘密鍵(すなわち、連邦鍵)は、FISMA Moderateの保護または同等の保護を達成した同期ファブリックに保管しなければならない。
  • 連邦企業の秘密鍵を含む認証器を生成、保管、同期するデバイス(携帯電話、ノート型パソコン、タブレットなど)は、モバイル・デバイス管理ソフトウェアまたはその他のデバイス・コンフィギュレーショ ン・コントロールによって保護され、権限のないデバイスまたは同期ファブリックへの鍵の同期または共有を防止しなければならない。
  • 同期ファブリックへのアクセスは、省庁が管理するアカウント(例えば、中央アイデンティティ・アクセス管理ソリューションまたはプラットフォーム・ベースの管理アカウント)によって制御され、 秘密鍵のライフ・サイクルに対する企業管理を維持するものとする。
  • 秘密鍵を生成する認証器は、認証器の能力およびソースを検証するために使用できる認証機能(例えば、エンタープライズ認証)をサポートすべきである(SHOULD)。

これらの管理は、特に同期をサポートし、FIPS 140 の検証を含む、既存の多要素ソフトウ ェア暗号認証の要件および AAL2 の要件に追加するものとみなされるものとする。

秘密鍵の同期に使うファブリック(要するにクラウドストレージやiCloudやGoogle Platformなど)の保護レベルはFISMA(米国連邦政府のセキュリティ基準)のModerate(平均レベル)もしくは同等が求められています。

また、同期ファブリックへのアクセス制御についてはIAMなどによりしっかり管理されている必要がある、ということなので共有パスワードグループはこの辺りに引っかかるんじゃないかな、、と思います。多分、企業などでiOSやmacOSを使う場合はMDMなどで共有パスワードグループを制御する(できるかどうかは知りませんが)ことが必要になりそうです。



2024年5月6日月曜日

NIST SP800-63B-3の同期可能クレデンシャルに関する追補版を読む(2)

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

引き続きNIST SP800-63-3の追補版を見ていきます。


前回はイントロ、文書の目的について読みましたが今回はAAL2の要件と同期可能な認証器の関係性について見ていきます。

では早速。

Syncable Authenticators Achieve AAL2

NIST の認証機関保証レベルは、主に、認証プロセスに対する特定の脅威から保護する認証機 関の能力を中心に構成されている。AAL2 では、ユーザが 2 つの 1 要素認証子、またはユーザ・アカウントにバインドされた多要素 認証子を所持しているという高い信頼性を提供することが意図されている。表 1 は、SP800-63-3 から要求される脅威の緩和と、適切に構成された同期可能な認証子がこれらの 脅威からどのように保護されるかを示している。

SP 800-63-3 による必要な脅威の緩和(表 4-1) 

要求事項AAL2同期可能な認証器(パスキーなど)
Man in the Middleに対する耐性必須達成
適切に構成された同期可能な認証器は、認証され保護されたチャネルによって、すべての認証デー タを交換する。
Verifierに関するなりすまし耐性必須ではない達成
適切に設定された同期可能な認証器は、一意の公開鍵または秘密鍵のペアを作成し、そのペアの使用は、作成されたドメインに限定される(つまり、鍵は特定のウェブサイトまたはRelying Partyでのみ使用できる)。これにより、改ざんされたウェブ・ページが認証子の出力をキャプチャして再利用することを防ぐことができる。
Verifierに関する侵害耐性必須ではない達成
適切に設定された同期可能な認証器は、検証者側にのみ公開鍵を保存する。これらの鍵は、ユーザ認証には使用できない。同期ファブリックによって保存される秘密鍵は、承認された暗号化技術を使用して暗号化された形でのみ保存される。アクセス制御により、認証されたユーザー以外が保存された鍵にアクセスすることはできない。
リプレイ耐性必須達成
同期可能な認証器は、各認証トランザクションに組み込まれたランダムなノンスを使用する ことで、リプレイ耐性(すなわち、将来のトランザクションでの再利用防止)を防ぐ。
認証の意図推奨達成
同期可能な認証器は、暗号化認証プロトコルを開始するために、ユーザがアクティ ベーション・シークレットを入力することを要求する。これは、ユーザの積極的な参加なしにはイベントが進行しないため、認証の意図として機能する。

セクション5では、同期可能な認証器の設定に関する追加的な考慮事項について論じる。

AAL2 要件を満たすために、同期可能な認証器は、ローカルに保存された鍵をアンロックするた めにローカル認証イベントを利用しなければならない[SHALL]。あるいは、ローカル認証の仕組みが 利用できない場合は、別の認証手段(たとえば、ユーザが選択したパスワード)と併用しなければ ならない[SHALL]。FIDO2 Web認証(WebAuthn)コンテキストでは、W3C Web認証仕様の認証子データで利用可能な User Verificationフラグの値によって示される。FIDO2 WebAuthn 認証データフラグの詳細については、セクション5を参照のこと。

ポイントは最後の一文で、やはり同期クレデンシャル「だけ」ではダメで、ちゃんとローカル認証イベント(たとえば端末アンロックの利用など)を使う必要がある、ということに触れたところでしょうか。

次回も引き続き読んでいきたいと思います。


2024年3月20日水曜日

Entra IDの条件付きアクセスでパスキーを使った認証を強制する

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

前回、Entra IDの条件付きアクセスがデバイスコードフローなどの認証フロー単位で適用できるようになった(Preview)という話をしました。

https://idmlab.eidentity.jp/2024/03/entra-id.html


すると、某FacebXXkで某氏よりTeams Roomとかで使えそう、かつWindows Helloを除外した上でYubikeyなどFIDOキーを使った認証を強制できると良さそう、、というコメントをもらったのでやってみました。



やることは、

  • 認証強度の設定を行う
  • 条件付きアクセスに設定した認証強度を紐づける

です。


認証強度の設定

認証強度、というとよくわかりませんが、認証方法をカスタムで設定できるEntra IDのセキュリティ機能です。

認証方法→認証強度のメニューで「新しい認証強度」の追加を行います。この際に、パスキー(FIDO2)を選択します。Windows Hello for Businessや証明書ベース認証などと分けて設定ができるので、Windows Helloなどとは分けて設定ができます。ちなみにここでパスキー(FIDO2)として設定を行うとtransportがusb/nfcに設定されるっぽいのでplatform authenticatorは除外できます。細かいパラメータは先日のポストで書きましたので知りたい方はこちらへどうぞ。

また、詳細オプションを設定することでAuthenticator Attestation GUID(AAGUID)を設定することもできるので認証器の種類まで絞り込むこともできます。


条件付きアクセスの設定を行う

前回のポストで紹介したデバイスコードフローをブロックするポリシーをベースにカスタマイズしてみます。

やりたいことは、

  • デバイスコードフローの場合
  • パスキー(FIDO2)での認証を強制する
です。

条件付きアクセスの設定の許可のところでブロックしていたところを「アクセス権の許可」を選択、「認証強度が必要」から先ほど作成した認証強度を選択します。


設定としてはこれでおしまいです。

しばらく設定が馴染むまで待ちましょう。


動作確認

早速動きを見てみましょう。

ざっくりいうと、パスワードで認証するとパスキーでの追加認証が求められ、最初からパスキーで認証するとそのままログインが完了します。

以下の例ではまずはパスワードで認証しています。

するとパスキーでの追加認証が求められます。
認証器を使って認証します。

ログインが完了します。

確かに某氏が言うように割と不特定多数が触れる環境(例えばゲスト用の会議室など)でデバイスコードフローを使う場合にPINのみでログインされてしまう可能性などを鑑みるとこう言う使い方もありかもしれませんね。



2024年3月17日日曜日

Auth0の管理画面へのログインにパスキーを使うと少しハマる件

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

そういえばAuth0(Okta CIC)の管理画面へのログインにパスキーなどが使えるので使ってみたいと思います。

ちなみにちょっとだけ癖があります。簡単に書くと、

  • パスキー追加をメニューから実施する場合はplatform認証器は選べない
  • USBキーやOTPなど多要素認証を追加し利用すると「このデバイスでのログインの高速化」を目的としてplatform認証器の登録を促される
  • リカバリはリカバリーコードを利用する
  • どうやらパスキーとしてはUSBなど外部キーを前提に設計されている
  • デバイス登録を目的にplatform認証器登録も使えるが同期される前提はなさそう

という感じです。最初からplatform認証器が登録できればいいのに。ちょっと実装が古いのかな。


さて、始める前に基本的な話を。IDaaSを使ってID基盤を構築するときに忘れてはいけないのはIDaaS自体の認証強化とアクセス制限です。

最低限やっておくべきことは、
  • 管理者アカウントの分離(共有ユーザの排除)
  • 管理権限の適正化
  • 認証強化(多要素認証)
  • ※API実行ユーザも忘れずに!
くらいでしょうか。
特にヘルプデスクやオペレータのアカウントも作る必要もあると思うので適切に権限分離は重要だと思います。
また、日本企業に多いと思いますが、上記に加えてアクセス元の環境の制限(IP制限など)も行いたい、という話も出てくることもあります。(これは働き方改革なのか、ネットワークペリメーター神話がまだまだ生きているだけなのかはケースバイケースです)

ということでAuth0でも管理画面へのログイン時の認証を強化できますのでやっておきましょう。
ちなみに、ご存知の通りAuth0の管理画面へログインするためにはローカルログインに加えてLinkedInやMicrosoft Account、Githubアカウント、Googleアカウントが使えます。
当然、それらのIDシステムもパスキーに対応していたりと認証強化を行うことは可能ですが、今回のテーマはAuth0側でさらに認証強化をする、という話です。

IdP側の認証強化の結果をこのケースおけるRPとなるAuth0の管理画面はどこまで信じることができるのか?と言う話とUI/UXの関係については別途書こうと思いますが、ざっくり言うと外部IdP(ここで言うとGoogleなど)は認証結果に対する責任は取ってくれない、かつどのような認証手段で認証したのかは教えてくれないので、重要な顧客IDを預かるIDaaSは自前でも多要素認証を実装しておくことが重要です。

ログインしてプロファイルページを開くと認証手段の追加ができます。
ちなみに設定が行われいていないテナントでは順次ログイン時に強制的に多要素認証設定を行うように促されるため最近のテナントを持っている方は設定済みかもしれません。

ということで追加してみます。WebAuthn with FIDO Security Keysをクリックしてみましょう。(なお、ポップアップがブロックされているとエラーになりますので、許可してください)

登録画面が出てきますね。初めに書いた通りplatform認証器ではなくUSBセキュリティキーが前提となっています。
登録が終わるとリカバリーコードが発行されるのでコピーしておきます。ちなみにダッシュボードからリカバリーコードは再生成できますので、こちらのスクリーンショットのコードはすでに無効です。

これで登録が完了しました。

一旦ログアウトしてログインし直してみます。USBキーが求められます。

すると、「このデバイスでのログインを高速化」と言われます。

そしてTouch IDが求められます。

USBキーとデバイスの両方が登録された状態になります。

USBキーを使う場面は少なくともSyncされたデバイスでは出番はなさそうです。
どうもplatform認証器はあくまでデバイス登録を目的としたものとして整理されているようですね。

しかし、iCloudで同期されているのかと思いつつiPhoneでダッシュボードにログインしてみるとplatform認証器は使えません。
USBキーが求められるので、仕方なく先ほど登録したUSBキーを使ってログインします。(先ほどYubikey NFCを使ったのでNFCで読み込ませました)

するときました。先ほどMacで登録したのと同じようにログインの高速化。
FaceIDを使ってデバイス登録を求められます。

しかし、すでにデバイス登録をMacでしているのでエラーが出ます。。。


iCloudで同期されているので登録済みって言われてます。

やはりパスキーが同期されている想定はなく、あくまでplatform認証器はデバイス登録に特化して利用、あくまで認証は外部キーを使うという整理になっていそうですね。






2024年3月12日火曜日

パスキーの実験に使ったコードをgithubにあげました

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

そういえばパスキーの実験をしていた頃のコードを公開するのを忘れていた気がするので公開しておこうと思います。

これまでのパスとでやったことはこちらです。


あくまで実験的に実装した内容ですので参考までに、です。

そろそろ忙しくなってきたのでOpenID Providerのログインにパスキーを組み込むのは少し先になりそうです。。。

2024年3月1日金曜日

パスキーでログインを実装する(検証編)

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

前回の続きです。前回はログイン処理の前段部分まで実装できたので今回はcredential.get()の結果の検証を行います。

その前に、これまでのポストはこちらです。


検証の大きな流れは、以下の通りです。
  • challengeの検証
  • originの検証
  • credentialIdをキーに保存済みの公開鍵をDBから取得
  • verificationDataの生成
  • 公開鍵とsignatureを使ってverificationDataの署名を検証
と、例によってCBORのデコードやバイナリの切り出し、公開鍵の変換(DER→COSE-Key)など本質的ではないところの面倒臭い処理があるので生で実装するのはやめました。

結論はsimplewebauthnのライブラリを使うことになるのですが、その前にざっくりやるべき処理だけ理解しておきたいと思います。(署名検証部分)

  • 鍵の変換
    • パスキー登録の時にレスポンスから取得できるPublicKeyはDER形式なのでcoseに変換する必要があります
    • 変換した鍵の中身を使って以下のBufferを連結して検証用の鍵を作ります
      • 0x04
      • 鍵のx
      • 鍵のy
  • VerificationData(検証対象とするデータ)の生成
    • 以下のBufferを連結して検証対象のデータを生成します
      • 0x00
      • rpIdHash(登録時にも使ったrpIdの検証用のHashと同じ値)
      • clientDataHash(clientDataJSONのSHA256ハッシュ値)
      • credentialId
      • publicKey
結構面倒くさいです。

ということでsimplaewebauthnのライブラリを使いました。
// 検証
const result = await simpleWebAuthn.verifyAuthenticationResponse({
response: req.body,
expectedChallenge: req.session.challenge,
expectedOrigin: origin,
expectedRPID: req.hostname,
authenticator: authenticator
});

超簡単です。
それぞれパラメータを解説していきます。
  • response
    • nagivator.credential.get()の結果取得できるpublicKeyCredentialをtoJSON()したオブジェクトをそのまま渡します
  • expectedChallenge
    • sessionに保存してあるchallengeを取り出してセットします
  • expectedOrigin
    • アクセスしているサイトのoriginをセットします。以前解説した通りngrokを使っている関係でschemeは工夫しています
// originの生成
const scheme = req.hostname !== 'localhost'? "https" : req.protocol;
const origin = url.format({
protocol: scheme,
host: req.get('host')
});
  • expectedRPID
    • ホスト名をつかっています
  • authenticator
    • credentialIdをキーにデータベースを検索し取得した公開鍵と署名回数のデータを含むオブジェクトを生成します(JSONBinに保存しているのでレスポンスの中に公開鍵、署名回数が含まれます)
// authenticator
const authenticator = {
credentialPublicKey: base64url.toBuffer(JSONBinResponse.publicKey),
credentialID: base64url.toBuffer(credentailId),
counter: JSONBinResponse.signCount
};

これでおしまいです。
検証結果(verified)がtrue/falseで返ってくるので認証OK/NGで処理を振り分けましょう。また、署名回数が前回よりも増えていることの確認をしておくことで認証器の偽造にも対応できます。(MacOSのTouchIDの署名回数は0のままなので署名回数の検証はできません)
if(result.verified) {
// 検証成功
// 検証回数が増えているかどうか(0の場合以外)
if(result.authenticationInfo.newCounter !== 0) {
if(result.authenticationInfo.newCounter <= JSONBinResponse.signCount){
console.log("error signCount is not increased");
}
}
// UVが行われているかどうか
if(!result.authenticationInfo.userVerified) {
console.log("user was not verified");
}

こんな感じで認証結果が表示できるように作りました。


と、ここで疑問が湧いてきます。
対象ユーザが正しいかどうかの検証ってしなくていいの?ログイン時にパスワードはもちろんユーザ名も入れてないけど、って話です。
今回の実装ではResidentKeyで認証器側でユーザ情報を持っている前提で組んでいるので、そうではない環境を想定するとユーザ名を入力させて認証はパスキー、という動線も作らないといけません。また、Credential IDだけを使って公開鍵をDBから取得していますが、ちゃんとユーザハンドルとDB内にCredential IDと紐付けて保存されているユーザIDが一致していることの確認をしないといけません。
ということで公開鍵をユーザDBから取得するところのロジックはこんな感じで実装していきます。
}
// credentialIdをキーにPublicKeyとCounterを取得する
// userHandleが一致していることを検証する
exports.getPublicKey = async function(credentialId, userHandle) {
// JSONBin用のヘッダ
const headers = new Headers({
"X-Master-Key": process.env.JSONBIN_MASTER_KEY,
"Content-Type": "application/json"
});
// JSONBinのユーザCollectionからユーザbinのidを取得する
const collectionUrl = new URL(`${process.env.JSONBIN_BASEURL}/c/${process.env.JSONBIN_PASSKEYCOLLECTION_ID}/bins`);
const collectionResponse = await fetch(collectionUrl, {
headers: headers
});
const passKeyCollection = await collectionResponse.json();
const passKeyBin = passKeyCollection.find(i => i.snippetMeta.name === credentialId);
if(typeof passKeyBin === "undefined"){
console.log("passKey not found");
return {
result: false,
error: "passKey not found"
}
}else{
// 当該パスキーのBin idからBinの中身を読み出す
const passKeyBinUrl = new URL(`${process.env.JSONBIN_BASEURL}/b/${passKeyBin.record}`);
const passKeyBinResponse = await fetch(passKeyBinUrl, {
headers: headers
});
const passKeyJson = await passKeyBinResponse.json();
console.log(passKeyJson);
// ユーザIDが正しいか検証
console.log("userhandle to be compared: " + userHandle);
console.log("expected userhandle : " + passKeyJson.record.userId);
if(userHandle !== passKeyJson.record.userId) {
// ユーザ名が異なる
return {
result: false,
error: "different user handle"
}
} else {
// ユーザ名一致
return {
result: true,
username: passKeyJson.record.username,
publicKey: passKeyJson.record.publicKey,
signCount: passKeyJson.record.signCount
}
}
}
}

まあ、もちろん前提として本来は登録時にCredential IDが重複していないことをチェック、かつユーザIDとの紐づけた上で登録する、というロジックを入れておかないと安全にはならないのでプロダクションで実装する人は注意しましょう。

雑ではありますが一通りパスキーの実装が理解できたので、そろそろ元々のOpenID Provider作りを再開していこうかと思います。



2024年2月29日木曜日

PlayStationでパスキーを使う(実機編)

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

前回はPCブラウザでPlayStationネットワークへのログインをする際にパスキーを使う話をしましたが、今回は実機が触れる環境があるので実機でも触ってみましょう。

結果、期待していた本体側でHybridのQRが出て、という形ではなくデバイスフロー+モバイル側でパスキーログインというのが答えでした。
ただし、本体側でパスキー設定を有効化することもできるようなメニューができている点が新しいファームウェアでの対応ポイントっぽいです。

サインイン

本体でPlayStationネットワークへサインインするメニューを立ち上げると、このような画面が出ます。これはパスキーをサポートする前と何も変わりません。よくあるデバイスフロー(もしくはその代替で独自で作った仕組み)でのログインです。

ちなみに「手動でサインインする」を開くと通常通りパスワードでログインする画面は出てきてしまいますがパスキーが有効な状態だとどう頑張ってもログインはできません。


ですので先ほどのQRコードを読み込んでスマホでパスキーを使ってログインする必要があります。


うまくログインできると本体とリンクされて本体側でのサインイン処理が進みます。


本体のセキュリティー設定を見るとちゃんとパスキーが有効になっていることがわかります。



本体でパスキーの登録を行う

では、パスキーが無効な状態で先ほどのセキュリティー設定の画面を開いて、パスキーの生成を本体で行うとどうなるのでしょうか?
ご想像の通りQRコードが出てきます。

こちらを読み取ってスマホ側でパスキー登録を行う、という流れです。






こんな感じです。
せっかくPlayStationにはUSBのコネクタがあるのでYubikeyを使えるとかだと面白かったのですが、、流石にそれはなかったです。

ニンテンドーアカウントでもパスキーが使えるようになっていますし、ゲームコンソールなどのパスワード入力が難しいデバイスのログインもどんどん進化していっていますね。
Switchが欲しくなってきました。




2024年2月28日水曜日

PlayStationでパスキーを使う

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

そういえばPlayStation Network(PSN)がパスキーに対応したというニュースが1月末ごろに流れたので確認してみていたのですが、その時点ではUSアカウントしかサポートしていない?みたいな状態だったのでしばらく放置していましたが、先ほど確認してみたら私のアカウントでもパスキーが使えるようになっていました。

ポイントはこちらです。

  • パスキーのサポート(とりあえずブラウザからのログインで確認)
  • パスキーを有効にするとパスワードは無効化される
  • パスキーを無効化する際にパスワードの生成を求められる
  • パスキーの識別はUser-Agentが使われる
  • パスキーを無くした際はメール+秘密の質問もしくは生年月日で回復できる
  • 回復の際はパスワードを生成が求められ、パスキーは無効化される

まぁ利便性などを考えると仕方ないのかもしれませんが、メール到達性+生年月日で回復できてしまうのは微妙だなぁ、、と思いつつ。

5/22追記)リカバリプロセスが更新されています。詳しくはこちら


実機(といってもPS4しか持っていない)での確認は次回以降でやりたいと思いますが、とりあえずブラウザでの設定関係についてまとめておきます。


パスキーの登録

マイページにログインしてセキュリティーの設定の中に「パスキーでサインイン」というメニューがあります。


編集をクリックして登録を開始していきます。

とりあえずTouchIDで生成していきます。

生成が完了するとログアウトされます。


サインイン

サインイン画面に行くと自動的に候補となるパスキーが表示されます。

このまま選択してTouchIDをアクティベートするとログインが完了します。

なお、Autofillを無視してサインインIDにメールアドレスを入力して次へ、をクリックすると「パスキーでサインイン」しか出てこずパスワードでのログインはできないようになっています。


先ほどのマイページのセキュリティ設定を見るとパスキーが有効、パスワードが無効になっていることがわかります。



パスキーを無効化する

この状態でパスキーを無効化してみます。



パスワードの生成を求められますので、ここで生成するとパスキーが無効になり、パスワードでログインができるようになります。


パスキーの管理

パスキーの管理メニューを開くと登録済みのパスキーの一覧が出てきます。

パスキーの識別にはUser-Agentが使われるようです。自分で名前がつけられる方が親切な気はしますがまぁいいかと思います。


ローカル認証器が使えない状態でのサインイン(ハイブリッド)

メールアドレスを入力しパスキーでサインインから他端末で読ませるQRを表示する方法もありますが、リカバリの流れで他端末を使ったサインインもサポートしています。


リカバリ

他の端末を含め全部ロストしてしまったケース用の動線も用意されています。

具体的にはアカウント回復用のメール+秘密の質問もしくは生年月日を使います。


画面下部の「アカウントの回復用のEメールを送信」をクリックするとメールが送られてくるのでリンクをクリックすると回復用の画面が表示されます。


秘密の質問への回答を覚えている訳がないので生年月日を選びます。

検証に成功するとパスワードの生成を求められます。

この段階でパスキーが無効になりますので、パスワードでログインした後に再度パスキーを登録する必要があります。


なお、パスキーが無効化された状態でパスキーでログインしようとするとエラーが表示されます。



とりあえずはブラウザで試しましたが実機を触る時間ができたら実機でも試してみたいと思います。