Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
WebAuthn & WebAuthn4J Introduction
Search
Yoshikazu Nojima
June 07, 2019
Programming
2
2.4k
WebAuthn & WebAuthn4J Introduction
WebAuthn & WebAuthn4J Introduction
Yoshikazu Nojima
June 07, 2019
Tweet
Share
More Decks by Yoshikazu Nojima
See All by Yoshikazu Nojima
Mavenパッケージの署名検証
ynojima
1
27
FIDO CTAP2 from Authenticator perspective
ynojima
2
870
Introduction to WebAuthn Testing API
ynojima
3
1.9k
WebAuthn for Java developers
ynojima
2
1.9k
WebAuthn from the relying-party view
ynojima
2
6k
WebAuthn in a nutshell - NTT Tech Conf #3 (ja)
ynojima
2
1.8k
Spring Securityでハードウェアトークン認証
ynojima
0
860
Other Decks in Programming
See All in Programming
短期間での新規プロダクト開発における「コスパの良い」Goのテスト戦略」 / kamakura.go
n3xem
2
170
Stackless и stackful? Корутины и асинхронность в Go
lamodatech
0
800
Beyond ORM
77web
7
890
PHPで作るWebSocketサーバー ~リアクティブなアプリケーションを知るために~ / WebSocket Server in PHP - To know reactive applications
seike460
PRO
2
450
Mermaid x AST x 生成AI = コードとドキュメントの完全同期への道
shibuyamizuho
0
160
php-conference-japan-2024
tasuku43
0
310
良いユニットテストを書こう
mototakatsu
8
2.6k
Effective Signals in Angular 19+: Rules and Helpers
manfredsteyer
PRO
0
110
アクターシステムに頼らずEvent Sourcingする方法について
j5ik2o
4
280
rails statsで大解剖 🔍 “B/43流” のRailsの育て方を歴史とともに振り返ります
shoheimitani
2
940
CSC305 Lecture 26
javiergs
PRO
0
140
nekko cloudにおけるProxmox VE利用事例
irumaru
3
430
Featured
See All Featured
Done Done
chrislema
181
16k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
2
170
Designing for humans not robots
tammielis
250
25k
Into the Great Unknown - MozCon
thekraken
33
1.5k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
48k
What's in a price? How to price your products and services
michaelherold
243
12k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
665
120k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Fireside Chat
paigeccino
34
3.1k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Code Review Best Practice
trishagee
65
17k
[RailsConf 2023] Rails as a piece of cake
palkan
53
5k
Transcript
Copyright © Yoshikazu Nojima 2019 WebAuthnの概要とWebAuthn4Jのご紹介 2019-06-07 OSSセキュリティ技術の会 能島 良和
(@shiroica)
Copyright © Yoshikazu Nojima 2019 自己紹介 • 能島良和 • 通信キャリアでホスティングサービスの開発・運用
• 前職は通信キャリア系SIerで社内向けにSpringのPJ支援業務 • Apache CloudStack Commiter(活動休止中。。) • WebAuthn周りは趣味 • Twitter:@shiroica • GitHub:ynojima 1
Copyright © Yoshikazu Nojima 2019 アジェンダ • WebAuthn登場の背景 • WebAuthnの概要
• フロントエンドとWebAuthn • バックエンドとWebAuthn • WebAuthn4Jとは • Spring Security WebAuthn • まとめ 2
Copyright © Yoshikazu Nojima 2019 WebAuthn登場の背景:パスワードの限界 • フィッシング攻撃耐性 • 本物そっくりの偽物サイトを作成し、ユーザーを誤認させたうえでID/Passwordを入力させ詐取
• 精巧に作成されたフィッシングサイトは45%のユーザーが騙されるという研究結果も • リスト型攻撃耐性 • 脆弱な他サービスで流出したID/Passwordを用いた攻撃 • 自サービスは堅牢でも、ユーザーがパスワードを使いまわした場合、巻き添え被害の可能性 • モバイルデバイス対応 • モバイルデバイスでは複雑なパスワードの入力が不便 パスワード要求はユーザーの離脱率に顕著な悪影響 パスワード認証に代わる認証手段が必要 3
Copyright © Yoshikazu Nojima 2019 Web Authentication仕様とは 最近W3Cで勧告候補になった、パスワード認証の問題点を克服したセキュアな認証を 実現するためのWeb標準。セキュリティキーによる二段階認証や生体認証を実現。 ▪主な特徴
• 指紋認証や顔認証など認証方式を差し替え可能 • 生体情報をサーバーで保存せず、安全性が高い • フィッシング攻撃、 CSRF攻撃対策の組込 4
Copyright © Yoshikazu Nojima 2019 デモ 5
Copyright © Yoshikazu Nojima 2019 Web Authenticationの認証フロー(概略) • ユーザー登録 ユーザー
認証デバイス ブラウザ サーバー DB RP固有公開鍵 の保存 承認ジェスチャ (指紋スキャン等) の実施 • RP固有公開鍵 • Credential Id • ドメイン(RP Id)のハッ シュ • その他 を送信 • RP固有公開鍵 • Credential Id • ドメイン(RP Id)のハッシュ • その他 を送信 耐タンパ 領域 RP固有秘密鍵 を保存 RP固有公開鍵・秘密鍵ペアを生成 • チャレンジ • チャレンジ、ドメイン(RpId) その他のハッシュ クライアントデータのハッシュ、 RP Idに対する署名を生成 ドメイン(RP Id) チャレンジ その他の検証 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 ユーザー検証機能付き認証デバイスの場合
Copyright © Yoshikazu Nojima 2019 Web Authenticationの認証フロー(概略) • ユーザー認証 ユーザー
認証デバイス ブラウザ サーバー 承認ジェスチャ (指紋スキャン等) の実施 • Credential Id • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • Credential Id • チャレンジ、ドメイン (RpId)その他 • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • RP Idのハッシュ • チャレンジ、ドメイン(RpId) その他のハッシュ RP固有秘密鍵でRpIdのハッシュ、 フラグ、カウンタ、クライアント データのハッシュを署名 ドメイン(RP Id)、署名 チャレンジ、その他の検証 • チャレンジ を送信 ユーザー検証機能付き認証デバイスの場合 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 RP固有秘密鍵を読込 ローカル認証 公開鍵認証 DB RP固有公開鍵 の読込
Copyright © Yoshikazu Nojima 2019 WebAuthnの技術的な特徴 ローカル認証と公開鍵認証の組み合わせ • ローカル認証 •
ユーザーと認証デバイス間の認証 認証方式は交換可能(例:指紋認証、虹彩認証、PIN) • 公開鍵認証 • 認証デバイスとサーバー間の認証 8 ユーザー 認証デバイス サーバー ローカル認証 (指紋認証等) 公開鍵認証
Copyright © Yoshikazu Nojima 2019 生体認証をローカル認証とするメリット 生体認証をリモート認証とした場合のリスク • 生体情報は変更不可能なことから究極のプライバシー情報。取扱は慎重さが求められる •
サーバーに生体情報を保存する生体認証では、生体情報は経路上で様々な攻撃に晒される • WebAuthnでは生体情報が認証デバイスから外に流通せず、安全性が高い(ローカル認証) • クライアント(ブラウザ)とサーバーは公開鍵と、公開鍵で検証できる署名を受け取るのみ • 生体情報と秘密鍵は認証デバイスのTPMやセキュアエレメントのような耐タンパ領域に保存 • デメリット • 登録時に使用した認証デバイスがないと認証できない ※認証デバイスの保持を認証要素の1つと見做せる側面もある 9 ユーザー 認証デバイス ブラウザ サーバー DB 生体情報の 検証 承認ジェスチャ (生体情報) の提供 • 生体情報 • 生体情報
Copyright © Yoshikazu Nojima 2019 フィッシング攻撃に対する効果 • ユーザー認証 ユーザー 認証デバイス
ブラウザ サーバー 承認ジェスチャ (指紋スキャン等) の実施 • Credential Id • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • Credential Id • チャレンジ、ドメイン (RpId)その他 • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • RP Idのハッシュ • チャレンジ、ドメイン(RpId) その他のハッシュ RP固有秘密鍵でRpIdのハッシュ、 フラグ、カウンタ、クライアント データのハッシュを署名 • チャレンジ を送信 ユーザー検証機能付き認証デバイスの場合 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 RP固有秘密鍵を読込 ドメイン(RP Id)、署名 その他の検証 DB RP固有公開鍵 の読込 秘密鍵はRpId(≒ドメイン)毎に保存されており、 フィッシング攻撃で他ドメインから認証要求を受けて も秘密鍵は不正利用されない
Copyright © Yoshikazu Nojima 2019 リスト型攻撃に対する効果 • ユーザー認証 ユーザー 認証デバイス
ブラウザ サーバー 承認ジェスチャ (指紋スキャン等) の実施 • Credential Id • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • Credential Id • チャレンジ、ドメイン (RpId)その他 • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • RP Idのハッシュ • チャレンジ、ドメイン(RpId) その他のハッシュ RP固有秘密鍵でRpIdのハッシュ、 フラグ、カウンタ、クライアント データのハッシュを署名 • チャレンジ を送信 ユーザー検証機能付き認証デバイスの場合 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 RP固有秘密鍵を読込 ドメイン(RP Id)、署名 その他の検証 DB RP固有公開鍵 の読込 サーバー側に保存されるのはRP固有の公開鍵であり、 他サイトで漏洩してもリスト型攻撃を受ける心配は不要
Copyright © Yoshikazu Nojima 2019 モバイルデバイス対応 近年のスマホで充実している、生体認証(指紋、顔認識)を ローカル認証に活用することで、パスワードを打ち込む 煩雑さからユーザーを開放し、離脱率を抑えることが期待 12
Copyright © Yoshikazu Nojima 2019 フロントエンドとWebAuthn 13
Copyright © Yoshikazu Nojima 2019 WebAuthn APIの提供箇所 • ユーザー登録 ユーザー
認証デバイス ブラウザ サーバー DB RP固有公開鍵 の保存 承認ジェスチャ (指紋スキャン等) の実施 • RP固有公開鍵 • Credential Id • ドメイン(RP Id)のハッ シュ • その他 を送信 • RP固有公開鍵 • Credential Id • ドメイン(RP Id)のハッシュ • その他 を送信 耐タンパ 領域 RP固有秘密鍵 を保存 RP固有公開鍵・秘密鍵ペアを生成 • チャレンジ • チャレンジ、ドメイン(RpId) その他のハッシュ クライアントデータのハッシュ、 RP Idに対する署名を生成 ドメイン(RP Id) チャレンジ その他の検証 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 ユーザー検証機能付き認証デバイスの場合 WebAuthnはブラウザからアプリケーション に対し、JavaScript APIとして提供 登録API navigator.credentials.create() 認証API navigator.credentials.get()
Copyright © Yoshikazu Nojima 2019 サービス/システムにWebAuthnを導入する場合、 フロントエンドで必要な対応 • ユーザー登録 ユーザー
認証デバイス ブラウザ サーバー DB RP固有公開鍵 の保存 承認ジェスチャ (指紋スキャン等) の実施 • RP固有公開鍵 • Credential Id • ドメイン(RP Id)のハッ シュ • その他 を送信 • RP固有公開鍵 • Credential Id • ドメイン(RP Id)のハッシュ • その他 を送信 耐タンパ 領域 RP固有秘密鍵 を保存 RP固有公開鍵・秘密鍵ペアを生成 • チャレンジ • チャレンジ、ドメイン(RpId) その他のハッシュ クライアントデータのハッシュ、 RP Idに対する署名を生成 ドメイン(RP Id) チャレンジ その他の検証 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 ユーザー検証機能付き認証デバイスの場合 フロントエンドは、バックエンドからチャレンジを 受け取り、ブラウザのWebAuthn APIを呼出。 結果をバックエンドに返送する処理が必要
Copyright © Yoshikazu Nojima 2019 WebAuthn登録API (navigator.credentials.create) メソッドのオプション 16 let
publicKeyCredentialCreationOptions = { rp: rp, user: user, challenge: challenge, pubKeyCredParams: pubKeyCredParams, timeout: timeout, excludeCredentials: excludeCredentials, authenticatorSelection: authenticatorSelection, attestation: attestation, extensions: extensions }; let credentialCreationOptions = { publicKey: publicKeyCredentialCreationOptions }; navigator.credentials.create(credentialCreationOptions) .then(function(credential){ // submit to Relying Party server });
Copyright © Yoshikazu Nojima 2019 Relying Partyに関するオプション 例) rpメンバ(PublicKeyCredentialRpEntity )
17 メンバ 説明 備考 id rpId。Credentialが有効なドメインのスコープを 指定するオプション name Relying Partyの名称。画面付きのFIDO2 Authenticatorで表示に使用されると思われる icon Relying Partyのアイコン。画面付きのFIDO2 Authenticatorで表示に使用されると思われる let rp = { id: "http://localhost", name: "spring-security-webauthn sample", icon: "http://localhost/img/spring-security-webauthn.png" };
Copyright © Yoshikazu Nojima 2019 rpId:WebAuthnでサイトを区別するスコープの単位 rpIdで指定したドメイン自身、及びそのサブドメインでCredentialは共有 例)以下のように、複数のサブドメインに跨って存在するサイトがあるとする ◆ rpIdが”example.com”の場合
Credentialは上記すべてのドメインで有効 ◆ rpIdが”admin.example.com”の場合 Credentialは”admin.example.com”のみで有効 18 id.example.com www.example.com admin.example.com
Copyright © Yoshikazu Nojima 2019 作成するCredentialが紐づくユーザーに関するオプション 例) userメンバ(PublicKeyCredentialUserEntity) 19 メンバ
説明 備考 id userHandle。ユーザーを一意に特定するバイト 列。Authenticatorが、あるRPのアカウント (userHandle)に対して複数のCredentialを持 たないよう制御するのに利用 name ユーザーアカウントの入力用の表記(Human- palatable)。 displayName ユーザーアカウントの表示用の表記(Human- Readable)。 icon ユーザーアカウントのアイコン。 let user = { id: userHandle, name: "
[email protected]
", displayName: "Yoshikazu Nojima", icon: "http://localhost/user/ynojima/icon.png" };
Copyright © Yoshikazu Nojima 2019 リプレイ攻撃を防ぐためのオプション。 例) challengeメンバ(BufferSource) 20 メンバ
説明 備考 challenge Relying Partyのバックエンドから受信したチャ レンジデータ。バイト列。 let challenge = base64url.toBuffer(challengeBase64);
Copyright © Yoshikazu Nojima 2019 RPが受け入れ可能なCredentialのタイプとアルゴリズムの指定オプション 例) pubKeyCredParamsメンバ (PublicKeyCredentialParameters) 21
メンバ 説明 備考 alg Credentialのアルゴリズム。[IANA-COSE- ALGS-REG]に登録された値から選択 Relying Partyの バックエンド側 も対応が必要 type “public-key”固定 let pubKeyCredParams = [ { alg: -7, //ES256 for FIDO U2F Key, etc. type: "public-key" }, { alg: -257, //RS256 for Windows Hello type: "public-key" } ];
Copyright © Yoshikazu Nojima 2019 ユーザーの認証操作入力待機時間を指定するオプション 例) timeoutメンバ(unsigned long) 22
メンバ 説明 備考 timeout ユーザーの認証操作入力待機時間。ミリ秒 let timeout = 300000;
Copyright © Yoshikazu Nojima 2019 Authenticatorが、あるRPのアカウントに対して複数のCredentialを持たな いよう制御する為のオプション 例) excludeCredentialsメンバ (PublicKeyCredentialParameters配列)
23 メンバ 説明 備考 type “public-key”固定 id credentialId。 transports Authenticatorとの接続に使用できると思われる 通信手段のヒント let excludeCredentials = [ { type: "public-key", id: id, transports: ["usb", "nfc", "ble", "internal"], } ];
Copyright © Yoshikazu Nojima 2019 RPが受け入れ可能なAuthenticatorを明示し、フィルタリングするための オプション 例) authenticatorSelectionメンバ (AuthenticatorSelectionCriteria)
24 メンバ 説明 備考 authenticator Attachment AuthenticatorのClient Platformに対する取り付 け方の指定。内蔵の場合、”platform”。取り外し 可能の場合、”cross-platform”。指定不要の場合、 メンバを削除 require ResidentKey AuthenticatorにCredentialを保存するか指定。 falseの場合、Credentialをデバイスに保存しない Authenticator(FIDO-U2Fトークン等)も許可 (その場合、ユーザーのID入力が必要) user Verification Authenticatorでユーザー識別を行うか指定。 値域:”required”, “preferred”, “discouraged” let authenticatorSelection = { //authenticatorAttachment: "platform", requireResidentKey: false, userVerification: "preferred" };
Copyright © Yoshikazu Nojima 2019 要求するAttestationのタイプを指定するオプション 例) “direct”を指定した場合、RPがAuthenticatorの出所を厳密に検証するための 情報を取得できる一方、RPがユーザーをサイトを跨いでトラッキングするた めにも使えてしまうというプライバシー上の懸念から、追加のダイアログが
表示される。 RPが認定したAuthenticatorのみに利用を制限したいエンタープライズ用途 以外では、”none”が適切 attestationメンバ (AttestationConveyancePreference) 25 メンバ 説明 備考 attestation 要求するattestationを指定。 値域:”none”, “indirect”, “direct” let attestation = "none";
Copyright © Yoshikazu Nojima 2019 例) WebAuthnの拡張ポイント。本資料では省略 extensionsメンバ (AuthenticationExcentionsClientInputs) 26
let extensions = {};
Copyright © Yoshikazu Nojima 2019 WebAuthn認証API (navigator.credentials.get) メソッドのオプション 27 let
publicKeyCredentialRequestOptions = { challenge: challenge, timeout: timeout, rpId: rpId, allowCredentials: allowCredentials, userVerification: userVerification, extensions: extensions }; let credentialRequestOptions = { mediation: "required", //WebAuthn lv.1ではrequiredのみ publicKey: publicKeyCredentialRequestOptions }; return navigator.credentials.get(credentialRequestOptions) .then(function(credential){ // submit to Relying Party server });
Copyright © Yoshikazu Nojima 2019 リプレイ攻撃を防ぐためのオプション。CSRFトークンのようなもの。 例) challengeメンバ(BufferSource) 28 メンバ
説明 備考 challenge Relying Partyのバックエンドから受信したチャ レンジデータ。バイト列。 let challenge = base64url.toBuffer(challengeBase64);
Copyright © Yoshikazu Nojima 2019 ユーザーの認証操作入力待機時間を指定するオプション 例) timeoutメンバ(unsigned long) 29
メンバ 説明 備考 timeout ユーザーの認証操作入力待機時間。ミリ秒 let timeout = 300000;
Copyright © Yoshikazu Nojima 2019 rpIdの指定オプション。 Credential作成時と同一値の指定が必要 例) ※CredentialはrpIdと紐づけられている為、作成時と異なる値を指定した場 合、指定したrpIdに紐づくCredentialが見つからないエラーが発生する。
rpIdメンバ(UVString) 30 メンバ 説明 備考 rpId Credentialが有効なドメインのスコープを指定。 Credential作成時のrp.id let rpId = "http://localhost";
Copyright © Yoshikazu Nojima 2019 FIDO-U2Fのようなnon-residentKey(Authenticatorにデータを保存しない 種類のCredential)をサポートするために、ユーザーに紐づくCredentialのid のリストを指定するオプション 例) allowCredentialsメンバ
(PublicKeyCredentialDescriptor配列) 31 メンバ 説明 備考 id credentialId type public-key固定 transports Authenticatorとの接続に使用できると思われる 通信手段のヒント let allowCredentials = [ { id: credentialId, type: "public-key", transports: ["usb", "nfc", "ble", "internal"] } ];
Copyright © Yoshikazu Nojima 2019 例) WebAuthnの拡張ポイント。本資料では省略 extensionsメンバ (AuthenticationExcentionsClientInputs) 32
let extensions = {};
Copyright © Yoshikazu Nojima 2019 バックエンドとWebAuthn 33
Copyright © Yoshikazu Nojima 2019 サービス/システムにWebAuthnを導入する場合、 バックエンドで必要な対応 34 • ユーザー認証
ユーザー 認証デバイス ブラウザ サーバー 承認ジェスチャ (指紋スキャン等) の実施 • Credential Id • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • Credential Id • チャレンジ、ドメイン (RpId)その他 • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • RP Idのハッシュ • チャレンジ、ドメイン(RpId) その他のハッシュ RP固有秘密鍵でRpIdのハッシュ、 フラグ、カウンタ、クライアント データのハッシュを署名 ドメイン(RP Id)、署名 チャレンジ、その他の検証 • チャレンジ を送信 ユーザー検証機能付き認証デバイスの場合 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 RP固有秘密鍵を読込 DB RP固有公開鍵 の読込 フロントエンドからcredentialIdやチャレンジ、署名な どの認証情報を受信し、WebAuthn仕様で定められた 検証を実施 リプレイ攻撃防止用のチャレンジを送信
Copyright © Yoshikazu Nojima 2019 WebAuthn4Jとは • WebAuthnの登録・認証メッセージ検証用ライブラリ • Java製、Apache2ライセンス
• コミュニティベースの開発 • https://github.com/webauthn4j/webauthn4j ◼ 主な特徴 • 全Attestation Statement対応 • FIDO Allianceの準拠テストツールをパス • ポータビリティ • 依存ライブラリはJackson(JSON, CBOR処理)、Apache Kerby (ASN.1処理)、SLF4J(ログインタフェース)のみ。導入の障壁が少ない • テストサポート機能の充実 • Keycloak向け拡張モジュール開発中 • Spring Security拡張モジュール開発中 35
Copyright © Yoshikazu Nojima 2019 基本的な使用方法(登録) 36 // フロントエンドから受信したリクエスト、検証条件を詰めてコンテキストクラスを組立 WebAuthnRegistrationContext
registrationContext = new WebAuthnRegistrationContext(clientDataJSON, attestationObject, transports, serverProperty, userVerificationRequired); // Validatorの生成 WebAuthnRegistrationContextValidator webAuthnRegistrationContextValidator = WebAuthnRegistrationContextValidator.createNonStrictRegistrationContextValidator(); // 検証の実施 WebAuthnRegistrationContextValidationResponse response = webAuthnRegistrationContextValidator.validate(registrationContext); // Authenticatorインスタンスの組立 Authenticator authenticator = // アプリの要件にあわせ、Authenticatorインタフェースの独自実装利用可 new AuthenticatorImpl( response.getAttestationObject().getAuthenticatorData().getAttestedCredentialData(), response.getAttestationObject().getAttestationStatement(), response.getAttestationObject().getAuthenticatorData().getSignCount() ); save(authenticator); // 認証に備え、永続化(方式はアプリケーション依存)
Copyright © Yoshikazu Nojima 2019 // フロントエンドから受信したリクエスト、検証条件を詰めてコンテキストクラスを組立 WebAuthnAuthenticationContext authenticationContext =
new WebAuthnAuthenticationContext( credentialId, clientDataJSON, authenticatorData, signature, serverProperty, userVerificationRequired); // 永続化していたAuthenticatorの読込(方式はアプリケーション依存) Authenticator authenticator = load(credentialId); // Validatorの生成 WebAuthnAuthenticationContextValidator webAuthnAuthenticationContextValidator = new WebAuthnAuthenticationContextValidator(); // 検証の実施 WebAuthnAuthenticationContextValidationResponse response = webAuthnAuthenticationContextValidator.validate(authenticationContext, authenticator); // カウンタの更新(方式はアプリケーション依存) updateCounter( response.getAuthenticatorData().getAttestedCredentialData().getCredentialId(), response.getAuthenticatorData().getSignCount() ); 基本的な使用方法(認証) 37
Copyright © Yoshikazu Nojima 2019 Attestation Statementの検証のサポート • Attestation :認証デバイスの真正性を検証可能するための仕組
• ユースケース • 利用者に安全性を検証済の認証デバイスを配布し、 その認証デバイス以外の利用を抑止したい • 主にエンタープライズ用途、エンタープライズ用途以外では非推奨 • 検証方式 • 認証デバイスはモデル毎に固有のAttestation証明書を保持 • 認証デバイスベンダから提供されるルート証明書をトラストアンカーに検証 • Attestation Statementとは • Attestation証明書のコンテナ • Packed/Android Key/Android SafetyNet/TPM/FIDO-U2F/Noneの6種類 • WebAuthn4Jは6種類のフォーマットを全てサポート 38
Copyright © Yoshikazu Nojima 2019 テストサポート機能 • WebAuthnによるログインのテストを自動化する場合、 最大の問題は認証デバイスをどうするか •
WebAuthn4Jではテストサポート用に認証デバイスのエミュレータを用意 39 // 認証デバイスエミュレータの接続されたクライアントエミュレータを準備 private ClientPlatform clientPlatform = EmulatorUtil.createClientPlatform(new AndroidSafetyNetAuthenticator()); @Test void validate_test(){ String rpId = “example.com”; Challenge challenge = new DefaultChallenge(); AuthenticatorSelectionCriteria authenticatorSelectionCriteria = new AuthenticatorSelectionCriteria(AuthenticatorAttachment.CROSS_PLATFORM, true, UserVerificationRequirement.REQUIRED); PublicKeyCredentialParameters publicKeyCredentialParameters = new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256); PublicKeyCredentialUserEntity publicKeyCredentialUserEntity = new PublicKeyCredentialUserEntity(); AuthenticationExtensionsClientInputs<RegistrationExtensionClientInput> extensions = new AuthenticationExtensionsClientInputs<>(); PublicKeyCredentialCreationOptions credentialCreationOptions = new PublicKeyCredentialCreationOptions( new PublicKeyCredentialRpEntity(rpId, “example.com”), publicKeyCredentialUserEntity, challenge, Collections.singletonList(publicKeyCredentialParameters), null, Collections.emptyList(), authenticatorSelectionCriteria, AttestationConveyancePreference.DIRECT, extensions ); // エミュレータによるCredentialの生成 PublicKeyCredential<AuthenticatorAttestationResponse, RegistrationExtensionClientOutput> publicKeyCredential = clientPlatform.create(credentialCreationOptions); // 以下省略 }
Copyright © Yoshikazu Nojima 2019 WebAuthn4Jのスコープ 40 • ユーザー認証 ユーザー
認証デバイス ブラウザ サーバー 承認ジェスチャ (指紋スキャン等) の実施 • Credential Id • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • Credential Id • チャレンジ、ドメイン (RpId)その他 • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • RP Idのハッシュ • チャレンジ、ドメイン(RpId) その他のハッシュ RP固有秘密鍵でRpIdのハッシュ、 フラグ、カウンタ、クライアント データのハッシュを署名 ドメイン(RP Id)、署名 チャレンジ、その他の検証 • チャレンジ を送信 ユーザー検証機能付き認証デバイスの場合 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 RP固有秘密鍵を読込 DB RP固有公開鍵 の読込 スコープ外 スコープ外 スコープ • WebAuthn4JはWebAuthnの Attestation/Assertionの検証のみを実施 する単機能ライブラリ • HTTPリクエストからのAttestation/ Assertionの取出処理、DBへの永続化 はスコープ外 • 特定の認証フレームワークに 依存しない為の設計 • ギャップへの対応 • 認証フレームワークに合わせた アダプタライブラリを準備
Copyright © Yoshikazu Nojima 2019 Spring Security WebAuthn • WebAuthn4Jが提供しない機能をSpring
Securityの流儀に則って 実装したアダプタライブラリ • https://github.com/sharplab/spring-security-webauthn • https://github.com/spring-projects/spring-security/pull/6842 • 提供機能 • Spring SecurityのAuthenticationProvider インタフェースの実装 • WebAuthnオプション用 RESTエンドポイントServletFilter • WebAuthn認証用ServletFilter • JavaConfig • 等々 41
Copyright © Yoshikazu Nojima 2019 まとめ • パスワード認証には限界がある • フィッシング攻撃対応
• リスト型攻撃対応 • モバイルデバイス対応 • W3Cで新しい認証方式としてWeb Authentication仕様の策定が進められている • ローカル認証と公開鍵認証の組み合わせ • 生体情報をサーバーで保存する必要がなく安全性が高い • 仕様としてフィッシング攻撃対策、CSRF攻撃対策を盛込済 • 主要ブラウザで実装が進行中 • Edge/Chrome/Firefox/Safari • サーバーサイドの実装を補助する為、WebAuthn4JというJavaライブラリを開発 • Spring SecurityやKeycloak向けにアダプタ開発中 42
Copyright © Yoshikazu Nojima 2019 APPENDIX 43
Copyright © Yoshikazu Nojima 2019 rpId:WebAuthnでサイトを区別するスコープの単位 rpIdで指定したドメイン自身、及びそのサブドメインで資格情報(鍵ペア)は共有 例)以下のように、複数のサブドメインに跨って存在するサイトがあるとする ◆ rpIdが”example.com”の場合
資格情報は上記すべてのドメインで有効 ◆ rpIdが”admin.example.com”の場合 資格情報は”admin.example.com”のみで有効 44 id.example.com www.example.com admin.example.com
Copyright © Yoshikazu Nojima 2019 以下のように、複数のTLD(トップレベルドメイン)に跨って存在するサイトがあるとする このようなドメイン自体が異なる場合でも、パスワード認証では認証用DBさえ共有していれば、 同一ID/Passでログインさせることが出来ていた。 WebAuthn仕様では同一サイトとして扱えず、登録時のドメインと同一のドメインでのみ認証可 異なるドメイン間での資格情報の共有(1/2)
45 example.co.jp example.com example.co.uk
Copyright © Yoshikazu Nojima 2019 サービスのリブランド、会社合併等によるドメイン名変更も、 既存ユーザーが認証出来なくなる問題が存在 異なるドメイン間での資格情報の共有(2/2) 46 旧サイト名.com
新サイト名.com ブランディング上の ドメイン名の変更
Copyright © Yoshikazu Nojima 2019 WebAuthnで異ドメイン間で資格情報を共有出来ない問題は、 異ドメイン間をOpenID ConnectやSAMLでシングルサインオン させることで緩和可能 緩和策:異ドメイン間でのシングルサインオン
47 example.co.jp example.com example.co.uk ログイン後、 SSOによるリダイレクト ログイン後、 SSOによるリダイレクト 代表ドメインに WebAuthnでログイン
Copyright © Yoshikazu Nojima 2019 WebAuthn採用時の悩み 48 どうやって自動テスト書く?
Copyright © Yoshikazu Nojima 2019 E2Eテストで扱う典型的な認証フロー(パスワード認証) 1. 登録画面に遷移する 2. 登録画面でユーザー名と
パスワードを入力する 3. 登録ボタンを押す 4. 認証画面に遷移する 5. 認証画面でユーザー名と パスワードを入力する 6. 認証画面で認証ボタンを押す 49 自動化は容易
Copyright © Yoshikazu Nojima 2019 E2Eテストで扱う典型的な認証フロー(WebAuthn認証) 1. 登録画面に遷移する 2. 登録画面でユーザー名を入力する
3. Authenticatorの追加ボタンを押す 4. Authenticatorデバイス側で承認ジェスチャーを行う 5. 登録ボタンを押す 6. 認証画面に遷移する 7. 認証画面で認証ボタンを押す 8. Authenticatorデバイスで認証ジェスチャーを行う 50
Copyright © Yoshikazu Nojima 2019 E2Eテストで扱う典型的な認証フロー(WebAuthn認証) 1. 登録画面に遷移する 2. 登録画面でユーザー名を入力する
3. Authenticatorの追加ボタンを押す 4. Authenticatorデバイス側で承認ジェスチャーを行う 5. 登録ボタンを押す 6. 認証画面に遷移する 7. 認証画面で認証ボタンを押す 8. Authenticatorデバイスで認証ジェスチャーを行う 51 手動操作が必要
Copyright © Yoshikazu Nojima 2019 52 認証ジェスチャなしで応答を 返す、エミュレータが欲しい
Copyright © Yoshikazu Nojima 2019 Web Authentication Testing API WebAuthnのE2Eテスト実装を支援するためのChromeのAPI
Chrome://flags画面あるいは起動オプションから有効化可能(デフォルトでは無効) 53
Copyright © Yoshikazu Nojima 2019 selenium-javaでのテストコード例(1/2) 54 @RunWith(SpringRunner.class) @SpringBootTest(classes =
SampleWebApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) public class E2ETestBase { protected WebDriver driver; protected WebDriverWait wait; @BeforeClass public static void setupClassTest(){ WebDriverManager.chromedriver().setup(); } @Before public void setupTest() { ChromeOptions chromeOptions = new ChromeOptions(); chromeOptions.addArguments(“--enable-web-authentication-testing-api”); //chromeOptions.setHeadless(true); driver = new ChromeDriver(chromeOptions); wait = new WebDriverWait(driver, 5); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS); } @After public void teardown() { if (driver != null) driver.quit();} } 起動オプションで指定 Headless起動も可能
Copyright © Yoshikazu Nojima 2019 selenium-javaでのテストコード例(2/2) 55 public class RegistrationAndAuthenticationE2ETest
extends E2ETestBase{ @Test public void test() { // Registration SignupComponent signupComponent = new SignupComponent(driver); signupComponent.navigate(); signupComponent.setFirstname(“John”); signupComponent.setLastname(“Doe”); signupComponent.setUsername(“
[email protected]
”); signupComponent.setPassword(“password”); signupComponent.clickAddAuthenticator(); signupComponent.getResidentKeyRequirementDialog().clickNo(); signupComponent.waitRegisterClickable(); signupComponent.clickRegister(); // Password authentication wait.until(ExpectedConditions.urlToBe(“http://localhost:8080/angular/login”)); PasswordLoginComponent passwordLoginComponent = new PasswordLoginComponent(driver); passwordLoginComponent.setUsername(“
[email protected]
”); passwordLoginComponent.setPassword(“password”); passwordLoginComponent.clickLogin(); // 2nd-factor authentication AuthenticatorLoginComponent authenticatorLoginComponent = new AuthenticatorLoginComponent(driver); // nop wait.until(ExpectedConditions.urlToBe(“http://localhost:8080/angular/profile”)); } テストコード自体は ページオブジェクト パターンに則った Seleniumの普通の テストコード
Copyright © Yoshikazu Nojima 2019 ChromeのAuthenticatorエミュレータが返却する Attestation Certificate • Attestation
Certificateは自己署名証明書 • RPがルート証明書とチェーンしているか検証している場合、検証エラー 56
Copyright © Yoshikazu Nojima 2019 おまけ1 ChromiumのWebAuthnのE2Eテストコード https://github.com/chromium/chromium/blob/fc74bfe460548ef49e12 d78c476f0ffc5ff2db99/third_party/blink/web_tests/http/tests/credenti almanager/virtual-navigator-credentials.html#L20-L43
57
Copyright © Yoshikazu Nojima 2019 おまけ2 WebAuthn Testing API Design
Doc https://docs.google.com/document/d/1bp2cMgjm2HSpvL9-WsJoIQMsBi1oKGQY6CvWD- 9WmIQ/edit#heading=h.wemjkxju7znw 58
Copyright © Yoshikazu Nojima 2019 Web Authenticationの認証フロー(詳細) • ユーザー登録 ユーザー
認証デバイス ブラウザ サーバー DB RP固有公開鍵 の保存 承認ジェスチャ (ローカル認証情報) の提供 • RP固有公開鍵 • Credential Id • 構成証明公開鍵証明書 • 署名 • カウンタ を送信 • クライアントデータ • 構成証明 • RP Idのハッシュ • カウンタ • Credential Id • RP固有公開鍵 • 構成証明公開鍵証明書 を送信 耐タンパ 領域 RP固有秘密鍵を保存 RP固有公開鍵・秘密鍵ペアを生成 構成証明 証明書を読込 • チャレンジ • RP Id • 他 • RP Idのハッシュ • クライアントデータのハッシュ クライアントデータのハッシュ、 RP Idに対する署名を生成 クライアントデータ、 構成証明、署名、認証 パス他の検証 • クライアントデータ • チャレンジ • オリジン • TokenBinding ID • 他 を生成 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 ユーザー検証機能付き認証デバイスの場合
Copyright © Yoshikazu Nojima 2019 Web Authenticationの認証フロー(詳細) • ユーザー認証 ユーザー
認証デバイス ブラウザ サーバー 承認ジェスチャ (ローカル認証情報) の提供 • Credential Id • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • Credential Id • クライアントデータ • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • RP Idのハッシュ • クライアントデータのハッシュ を送信 RP固有秘密鍵でRP Idのハッシュ、 フラグ、カウンタ、クライアント データのハッシュを署名 クライアントデータ、 認証デバイスデータ、署名 他の検証 • チャレンジ を送信 • クライアントデータ • チャレンジ • オリジン • TokenBinding ID • 他 を生成 ユーザー検証機能付き認証デバイスの場合 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 RP固有秘密鍵を読込
Copyright © Yoshikazu Nojima 2019 Web Authenticationの認証フロー(詳細) • ユーザー登録(二要素認証への適用) ユーザー
認証デバイス ブラウザ サーバー DB RP固有公開鍵 の保存 承認ジェスチャ (ボタン押下) の提供 • RP固有公開鍵 • Credential Id(NonceとMAC) • 構成証明公開鍵証明書 • 署名 • カウンタ を送信 • クライアントデータ • 構成証明 • RP Idのハッシュ • カウンタ • Credential Id • RP固有公開鍵 • 構成証明公開鍵証明書 を送信 耐タンパ 領域 デバイスシークレットをキーに NonceとRP Idのハッシュから RP固有公開鍵・秘密鍵ペアを導出 構成証明秘密鍵、 構成証明公開鍵証明書、 デバイスシークレット を読込 • チャレンジ • RP Id • 他 • RP Idのハッシュ • クライアントデータのハッシュ を送信 構成証明秘密鍵でRP Id、 クライアントデータのハッシュ、 Credential Id、RP固有公開鍵を署名 クライアントデータ、 構成証明、署名、認証パス 他の検証 • クライアントデータ • チャレンジ • オリジン • TokenBinding ID • 他 を生成 Yubico社のFIDO-U2F認証デバイスの場合 RNGでNonce を生成 デバイスシークレットをキーに RP固有秘密鍵とRP IdからMACを生成
Copyright © Yoshikazu Nojima 2019 Web Authenticationの認証フロー(詳細) • ユーザー認証(二要素認証への適用) ユーザー
認証デバイス ブラウザ サーバー DB Credential Id リストの取得 承認ジェスチャ (ボタン押下) の提供 • フラグ • カウンタ • 署名 を送信 • Credential Id • クライアントデータ • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 耐タンパ 領域 デバイスシークレットをキーに NonceとRP Idのハッシュから RP固有公開鍵・秘密鍵ペアを導出 デバイスシークレット を読込 • RP Idのハッシュ • クライアントデータのハッシュ • Credential Id(NonceとMAC) を送信 RP固有秘密鍵でRP Idのハッシュ、 フラグ、カウンタ、クライアント データのハッシュを署名 クライアントデータ、 認証デバイスデータ、署名 他の検証 • Credential Idリスト • チャレンジ、RP Id、他 を送信 Yubico社のFIDO-U2F認証デバイスの場合 ID/Passの入力 ID/Passの送信 • クライアントデータ • チャレンジ • オリジン • TokenBinding ID • 他 を生成 DB RP固有公開鍵 の読込