Upgrade to Pro — share decks privately, control downloads, hide ads and more …

WebAuthn & WebAuthn4J Introduction

WebAuthn & WebAuthn4J Introduction

WebAuthn & WebAuthn4J Introduction

Yoshikazu Nojima

June 07, 2019
Tweet

More Decks by Yoshikazu Nojima

Other Decks in Programming

Transcript

  1. Copyright © Yoshikazu Nojima 2019 自己紹介 • 能島良和 • 通信キャリアでホスティングサービスの開発・運用

    • 前職は通信キャリア系SIerで社内向けにSpringのPJ支援業務 • Apache CloudStack Commiter(活動休止中。。) • WebAuthn周りは趣味 • Twitter:@shiroica • GitHub:ynojima 1
  2. Copyright © Yoshikazu Nojima 2019 アジェンダ • WebAuthn登場の背景 • WebAuthnの概要

    • フロントエンドとWebAuthn • バックエンドとWebAuthn • WebAuthn4Jとは • Spring Security WebAuthn • まとめ 2
  3. Copyright © Yoshikazu Nojima 2019 WebAuthn登場の背景:パスワードの限界 • フィッシング攻撃耐性 • 本物そっくりの偽物サイトを作成し、ユーザーを誤認させたうえでID/Passwordを入力させ詐取

    • 精巧に作成されたフィッシングサイトは45%のユーザーが騙されるという研究結果も • リスト型攻撃耐性 • 脆弱な他サービスで流出したID/Passwordを用いた攻撃 • 自サービスは堅牢でも、ユーザーがパスワードを使いまわした場合、巻き添え被害の可能性 • モバイルデバイス対応 • モバイルデバイスでは複雑なパスワードの入力が不便 パスワード要求はユーザーの離脱率に顕著な悪影響 パスワード認証に代わる認証手段が必要 3
  4. 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) チャレンジ その他の検証 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 ユーザー検証機能付き認証デバイスの場合
  5. 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固有公開鍵 の読込
  6. Copyright © Yoshikazu Nojima 2019 WebAuthnの技術的な特徴 ローカル認証と公開鍵認証の組み合わせ • ローカル認証 •

    ユーザーと認証デバイス間の認証 認証方式は交換可能(例:指紋認証、虹彩認証、PIN) • 公開鍵認証 • 認証デバイスとサーバー間の認証 8 ユーザー 認証デバイス サーバー ローカル認証 (指紋認証等) 公開鍵認証
  7. Copyright © Yoshikazu Nojima 2019 生体認証をローカル認証とするメリット 生体認証をリモート認証とした場合のリスク • 生体情報は変更不可能なことから究極のプライバシー情報。取扱は慎重さが求められる •

    サーバーに生体情報を保存する生体認証では、生体情報は経路上で様々な攻撃に晒される • WebAuthnでは生体情報が認証デバイスから外に流通せず、安全性が高い(ローカル認証) • クライアント(ブラウザ)とサーバーは公開鍵と、公開鍵で検証できる署名を受け取るのみ • 生体情報と秘密鍵は認証デバイスのTPMやセキュアエレメントのような耐タンパ領域に保存 • デメリット • 登録時に使用した認証デバイスがないと認証できない ※認証デバイスの保持を認証要素の1つと見做せる側面もある 9 ユーザー 認証デバイス ブラウザ サーバー DB 生体情報の 検証 承認ジェスチャ (生体情報) の提供 • 生体情報 • 生体情報
  8. Copyright © Yoshikazu Nojima 2019 フィッシング攻撃に対する効果 • ユーザー認証 ユーザー 認証デバイス

    ブラウザ サーバー 承認ジェスチャ (指紋スキャン等) の実施 • Credential Id • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • Credential Id • チャレンジ、ドメイン (RpId)その他 • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • RP Idのハッシュ • チャレンジ、ドメイン(RpId) その他のハッシュ RP固有秘密鍵でRpIdのハッシュ、 フラグ、カウンタ、クライアント データのハッシュを署名 • チャレンジ を送信 ユーザー検証機能付き認証デバイスの場合 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 RP固有秘密鍵を読込 ドメイン(RP Id)、署名 その他の検証 DB RP固有公開鍵 の読込 秘密鍵はRpId(≒ドメイン)毎に保存されており、 フィッシング攻撃で他ドメインから認証要求を受けて も秘密鍵は不正利用されない
  9. Copyright © Yoshikazu Nojima 2019 リスト型攻撃に対する効果 • ユーザー認証 ユーザー 認証デバイス

    ブラウザ サーバー 承認ジェスチャ (指紋スキャン等) の実施 • Credential Id • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • Credential Id • チャレンジ、ドメイン (RpId)その他 • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • RP Idのハッシュ • チャレンジ、ドメイン(RpId) その他のハッシュ RP固有秘密鍵でRpIdのハッシュ、 フラグ、カウンタ、クライアント データのハッシュを署名 • チャレンジ を送信 ユーザー検証機能付き認証デバイスの場合 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 RP固有秘密鍵を読込 ドメイン(RP Id)、署名 その他の検証 DB RP固有公開鍵 の読込 サーバー側に保存されるのはRP固有の公開鍵であり、 他サイトで漏洩してもリスト型攻撃を受ける心配は不要
  10. 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()
  11. 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を呼出。 結果をバックエンドに返送する処理が必要
  12. 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 });
  13. 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" };
  14. 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" };
  15. Copyright © Yoshikazu Nojima 2019 リプレイ攻撃を防ぐためのオプション。 例) challengeメンバ(BufferSource) 20 メンバ

    説明 備考 challenge Relying Partyのバックエンドから受信したチャ レンジデータ。バイト列。 let challenge = base64url.toBuffer(challengeBase64);
  16. 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" } ];
  17. Copyright © Yoshikazu Nojima 2019 ユーザーの認証操作入力待機時間を指定するオプション 例) timeoutメンバ(unsigned long) 22

    メンバ 説明 備考 timeout ユーザーの認証操作入力待機時間。ミリ秒 let timeout = 300000;
  18. 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"], } ];
  19. 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" };
  20. Copyright © Yoshikazu Nojima 2019 要求するAttestationのタイプを指定するオプション 例) “direct”を指定した場合、RPがAuthenticatorの出所を厳密に検証するための 情報を取得できる一方、RPがユーザーをサイトを跨いでトラッキングするた めにも使えてしまうというプライバシー上の懸念から、追加のダイアログが

    表示される。 RPが認定したAuthenticatorのみに利用を制限したいエンタープライズ用途 以外では、”none”が適切 attestationメンバ (AttestationConveyancePreference) 25 メンバ 説明 備考 attestation 要求するattestationを指定。 値域:”none”, “indirect”, “direct” let attestation = "none";
  21. 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 });
  22. Copyright © Yoshikazu Nojima 2019 リプレイ攻撃を防ぐためのオプション。CSRFトークンのようなもの。 例) challengeメンバ(BufferSource) 28 メンバ

    説明 備考 challenge Relying Partyのバックエンドから受信したチャ レンジデータ。バイト列。 let challenge = base64url.toBuffer(challengeBase64);
  23. Copyright © Yoshikazu Nojima 2019 ユーザーの認証操作入力待機時間を指定するオプション 例) timeoutメンバ(unsigned long) 29

    メンバ 説明 備考 timeout ユーザーの認証操作入力待機時間。ミリ秒 let timeout = 300000;
  24. 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"] } ];
  25. 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仕様で定められた 検証を実施 リプレイ攻撃防止用のチャレンジを送信
  26. 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
  27. 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); // 認証に備え、永続化(方式はアプリケーション依存)
  28. 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
  29. Copyright © Yoshikazu Nojima 2019 Attestation Statementの検証のサポート • Attestation :認証デバイスの真正性を検証可能するための仕組

    • ユースケース • 利用者に安全性を検証済の認証デバイスを配布し、 その認証デバイス以外の利用を抑止したい • 主にエンタープライズ用途、エンタープライズ用途以外では非推奨 • 検証方式 • 認証デバイスはモデル毎に固有のAttestation証明書を保持 • 認証デバイスベンダから提供されるルート証明書をトラストアンカーに検証 • Attestation Statementとは • Attestation証明書のコンテナ • Packed/Android Key/Android SafetyNet/TPM/FIDO-U2F/Noneの6種類 • WebAuthn4Jは6種類のフォーマットを全てサポート 38
  30. 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); // 以下省略 }
  31. 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への永続化 はスコープ外 • 特定の認証フレームワークに 依存しない為の設計 • ギャップへの対応 • 認証フレームワークに合わせた アダプタライブラリを準備
  32. 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
  33. Copyright © Yoshikazu Nojima 2019 まとめ • パスワード認証には限界がある • フィッシング攻撃対応

    • リスト型攻撃対応 • モバイルデバイス対応 • W3Cで新しい認証方式としてWeb Authentication仕様の策定が進められている • ローカル認証と公開鍵認証の組み合わせ • 生体情報をサーバーで保存する必要がなく安全性が高い • 仕様としてフィッシング攻撃対策、CSRF攻撃対策を盛込済 • 主要ブラウザで実装が進行中 • Edge/Chrome/Firefox/Safari • サーバーサイドの実装を補助する為、WebAuthn4JというJavaライブラリを開発 • Spring SecurityやKeycloak向けにアダプタ開発中 42
  34. Copyright © Yoshikazu Nojima 2019 WebAuthnで異ドメイン間で資格情報を共有出来ない問題は、 異ドメイン間をOpenID ConnectやSAMLでシングルサインオン させることで緩和可能 緩和策:異ドメイン間でのシングルサインオン

    47 example.co.jp example.com example.co.uk ログイン後、 SSOによるリダイレクト ログイン後、 SSOによるリダイレクト 代表ドメインに WebAuthnでログイン
  35. Copyright © Yoshikazu Nojima 2019 E2Eテストで扱う典型的な認証フロー(パスワード認証) 1. 登録画面に遷移する 2. 登録画面でユーザー名と

    パスワードを入力する 3. 登録ボタンを押す 4. 認証画面に遷移する 5. 認証画面でユーザー名と パスワードを入力する 6. 認証画面で認証ボタンを押す 49 自動化は容易
  36. Copyright © Yoshikazu Nojima 2019 E2Eテストで扱う典型的な認証フロー(WebAuthn認証) 1. 登録画面に遷移する 2. 登録画面でユーザー名を入力する

    3. Authenticatorの追加ボタンを押す 4. Authenticatorデバイス側で承認ジェスチャーを行う 5. 登録ボタンを押す 6. 認証画面に遷移する 7. 認証画面で認証ボタンを押す 8. Authenticatorデバイスで認証ジェスチャーを行う 50
  37. Copyright © Yoshikazu Nojima 2019 E2Eテストで扱う典型的な認証フロー(WebAuthn認証) 1. 登録画面に遷移する 2. 登録画面でユーザー名を入力する

    3. Authenticatorの追加ボタンを押す 4. Authenticatorデバイス側で承認ジェスチャーを行う 5. 登録ボタンを押す 6. 認証画面に遷移する 7. 認証画面で認証ボタンを押す 8. Authenticatorデバイスで認証ジェスチャーを行う 51 手動操作が必要
  38. Copyright © Yoshikazu Nojima 2019 Web Authentication Testing API WebAuthnのE2Eテスト実装を支援するためのChromeのAPI

    Chrome://flags画面あるいは起動オプションから有効化可能(デフォルトでは無効) 53
  39. 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起動も可能
  40. 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の普通の テストコード
  41. Copyright © Yoshikazu Nojima 2019 ChromeのAuthenticatorエミュレータが返却する Attestation Certificate • Attestation

    Certificateは自己署名証明書 • RPがルート証明書とチェーンしているか検証している場合、検証エラー 56
  42. Copyright © Yoshikazu Nojima 2019 おまけ2 WebAuthn Testing API Design

    Doc https://docs.google.com/document/d/1bp2cMgjm2HSpvL9-WsJoIQMsBi1oKGQY6CvWD- 9WmIQ/edit#heading=h.wemjkxju7znw 58
  43. 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 • 他 を生成 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 ユーザー検証機能付き認証デバイスの場合
  44. Copyright © Yoshikazu Nojima 2019 Web Authenticationの認証フロー(詳細) • ユーザー認証 ユーザー

    認証デバイス ブラウザ サーバー 承認ジェスチャ (ローカル認証情報) の提供 • Credential Id • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • Credential Id • クライアントデータ • 認証デバイスデータ • RP Idのハッシュ • フラグ • カウンタ • 資格情報データ • 署名 を送信 • RP Idのハッシュ • クライアントデータのハッシュ を送信 RP固有秘密鍵でRP Idのハッシュ、 フラグ、カウンタ、クライアント データのハッシュを署名 クライアントデータ、 認証デバイスデータ、署名 他の検証 • チャレンジ を送信 • クライアントデータ • チャレンジ • オリジン • TokenBinding ID • 他 を生成 ユーザー検証機能付き認証デバイスの場合 耐タンパ 領域 • ローカル認証情報(生体情報等) を検証 RP固有秘密鍵を読込
  45. 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を生成
  46. 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固有公開鍵 の読込