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
FIDO CTAP2 from Authenticator perspective
ynojima
2
850
Introduction to WebAuthn Testing API
ynojima
3
1.8k
WebAuthn for Java developers
ynojima
2
1.9k
WebAuthn from the relying-party view
ynojima
2
5.9k
WebAuthn in a nutshell - NTT Tech Conf #3 (ja)
ynojima
2
1.8k
Spring Securityでハードウェアトークン認証
ynojima
0
850
Other Decks in Programming
See All in Programming
推し活としてのrails new/oshikatsu_ha_iizo
sakahukamaki
3
1.7k
/←このスケジュール表に立ち向かう フロントエンド開発戦略 / A front-end development strategy to tackle a single-slash schedule.
nrslib
1
590
ECSのサービス間通信 4つの方法を比較する 〜Canary,Blue/Greenも添えて〜
tkikuc
11
2.3k
WEBエンジニア向けAI活用入門
sutetotanuki
0
300
Server Driven Compose With Firebase
skydoves
0
400
What’s New in Compose Multiplatform - A Live Tour (droidcon London 2024)
zsmb
1
340
Universal Linksの実装方法と陥りがちな罠
kaitokudou
1
220
Amazon Neptuneで始めてみるグラフDB-OpenSearchによるグラフの全文検索-
satoshi256kbyte
4
330
Piniaの現状と今後
waka292
5
1.5k
讓數據說話:用 Python、Prometheus 和 Grafana 講故事
eddie
0
350
現場で役立つモデリング 超入門
masuda220
PRO
13
2.9k
リリース8年目のサービスの1800個のERBファイルをViewComponentに移行した方法とその結果
katty0324
5
3.6k
Featured
See All Featured
Large-scale JavaScript Application Architecture
addyosmani
510
110k
10 Git Anti Patterns You Should be Aware of
lemiorhan
654
59k
How GitHub (no longer) Works
holman
311
140k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Six Lessons from altMBA
skipperchong
26
3.5k
A Modern Web Designer's Workflow
chriscoyier
692
190k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
355
29k
The Power of CSS Pseudo Elements
geoffreycrofte
72
5.3k
Embracing the Ebb and Flow
colly
84
4.4k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Happy Clients
brianwarren
97
6.7k
We Have a Design System, Now What?
morganepeng
50
7.2k
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固有公開鍵 の読込