1. 詳細

1.1. クレデンシャル情報の表現

クレデンシャル情報を表現するインタフェースとして、 CredentialRecord インタフェースが存在します。 登録時に、 RegistrationData クラスが含む値を用いて CredentialRecord インタフェースの インスタンスを作成し、アプリケーションの作法に則り永続化してください。認証時の検証に必要となります。 なお、永続化する際は、検索する際の利便性を考え、credentialIdをキーに永続化すると良いでしょう。 CredentialRecord インタフェースの実装クラスを設計する際は、アプリケーションの要件に合わせて拡張すると良いでしょう。 典型的には、 CredentialRecord をユーザーが識別するための名前フィールドの追加などが考えられるでしょう。

1.2. CredentialRecordのシリアライズ、デシリアライズ

認証デバイスの登録時、CredentialRecord のインスタンスをデータベース等に永続化し、認証時に利用できるようにするのはアプリケーションの責務ですが、 CredentialRecord を構成する各メンバをシリアライズ、デシリアライズする際に使用できるクラスをWebAuthn4Jでは用意しています。 アプリケーションで永続化を実装する際の補助としてご利用ください。

1.2.1. attestedCredentialData

AttestedCredentialDataConverterAttestedCredentialDatabyte[] に変換したり、その逆の変換を行うことが出来ます。 なお、String として保存したい場合、さらに Base64UrlUtil を用いることで byte[] から Base64Url String に変換することが出来ます。

AttestedCredentialDataConverter attestedCredentialDataConverter = new AttestedCredentialDataConverter(objectConverter);

// serialize
byte[] serialized = attestedCredentialDataConverter.convert(attestedCredentialData);
// deserialize
AttestedCredentialData deserialized = attestedCredentialDataConverter.convert(serialized);

1.2.2. attestationStatement

AttestationStatement はインタフェースであり、PackedAttestationStatement や、AndroidKeyAttestationStatement など、フォーマットにあわせて複数の実装があります。 AttestationStatement のCBOR表現は具象型が何であるかについて自己記述性を持たない為、フォーマットは別途、別のフィールドとして永続化する必要があります。 そのため、CBORとしてシリアライズする際は、実際のattestationStatementのフィールドと、フォーマットのフィールドを持つエンベロープクラスを用意し、エンベロープクラスをシリアライズしなければなりません。

//serialize
AttestationStatementEnvelope envelope = new AttestationStatementEnvelope(attestationStatement);
byte[] serializedEnvelope = objectConverter.getCborConverter().writeValueAsBytes(envelope);

//deserialize
AttestationStatementEnvelope deserializedEnvelope = objectConverter.getCborConverter().readValue(serializedEnvelope, AttestationStatementEnvelope.class);
AttestationStatement deserializedAttestationStatement = deserializedEnvelope.getAttestationStatement();
class AttestationStatementEnvelope{

    @JsonProperty("attStmt")
    @JsonTypeInfo(
            use = JsonTypeInfo.Id.NAME,
            include = JsonTypeInfo.As.EXTERNAL_PROPERTY,
            property = "fmt"
    )
    private AttestationStatement attestationStatement;

    @JsonCreator
    public AttestationStatementEnvelope(@JsonProperty("attStmt") AttestationStatement attestationStatement) {
        this.attestationStatement = attestationStatement;
    }

    @JsonProperty("fmt")
    public String getFormat() {
        return attestationStatement.getFormat();
    }

    public AttestationStatement getAttestationStatement() {
        return attestationStatement;
    }
}

1.2.3. transports

JSON文字列として保存したい場合は ObjectConverter が使用できます。

String serializedTransports = objectConverter.getJsonConverter().writeValueAsString(transports);

1.2.4. counter

このメンバは元々long型の為、特に変換は不要です。

1.2.5. authenticatorExtensions

authenticatorExtensionsは元来CBORデータの為、CBORに変換できます。

byte[] serializedAuthenticatorExtensions = objectConverter.getCborConverter().writeValueAsBytes(authenticatorExtensions);

1.2.6. clientExtensions

clientExtensionsは元来JSONデータの為、JSONに変換できます。

String serializedClientExtensions = objectConverter.getJsonConverter().writeValueAsString(clientExtensions);

1.3. DCAppleDeviceのシリアライズ、デシリアライズ

webauthn4j-device-checkでは、CredentialRecord インタフェースの代わりに、DCAppleDevice インタフェースを実装したクラスを、構成証明の検証時とアサーションの検証時の間で永続化する必要があります。 概ねCredentialRecordのシリアライズ、デシリアライズで解説した方法でシリアライズ、デシリアライズが可能ですが、一点気を付ける必要がある点として、 webauthn4j-device-check独自のクラス(例えば AppleAppAttestAttestationStatement )のシリアライズ、デシリアライズを行う為に、 ObjectConverterDeviceCheckCBORModule が登録されたものを使用する必要があります。 DeviceCheckCBORModule が登録された`ObjectConverter` は DeviceCheckManager#createObjectConverter で得ることが出来ます。

1.4. WebAuthn以外のFIDO CTAP2セキュリティキーを用いた独自アプリケーションでの利用

FIDO CTAP2セキュリティキーにとって、WebAuthnは一つの応用例でしかなく、セキュアな認証を必要とする独自アプリケーションで セキュリティキーを利用することも可能です。本節では、FIDO CTAP2セキュリティキーを用いた独自アプリケーションにおけるAttestation、Assertion検証でWebAuthn4Jを利用する方法を説明します。

1.4.1. FIDO CTAP2セキュリティキーを用いた独自アプリケーションでの登録、認証のフロー

FIDO CTAP2セキュリティキーを独自アプリケーションで認証に使用する場合、セキュリティキーを登録するために、 アプリからFIDO CTAP2セキュリティキーの authenticatorMakeCredential メソッドを呼び出し、公開鍵やデバイスの構成情報を 含むデータ(構成証明、Attestation)を取得し保存します。 取得されたAttestationは、セキュリティキーがアプリとして受け入れ可能なキーか判定するために検証が必要です。 WebAuthn4Jでは、 CoreRegistrationVerifier クラスを用いることで、取得されたAttestationを検証可能です。

認証時には、同様にアプリからFIDO CTAP2セキュリティキーの authenticatorGetAssertion メソッドを呼び出し、認証時にサーバーに送信される署名を含んだデータ(アサーション、Assertion)を取得します。 取得されたAssertionを検証することで、アプリは認証に用いられたセキュリティキーが、登録時に用いられたセキュリティキーと同一であることを確認し、正当なアクセスか判定することが可能となります。WebAuthn4Jでは、 CoreAuthenticationVerifier クラスを用いることで、取得されたAssertionを検証可能です。

1.4.2. アプリケーション固有のクライアントデータの真正性の担保、検証

上記のフローに従って実装することで、FIDO CTAP2セキュリティキーを用いた安全な認証が実現可能ですが、 FIDO CTAP2セキュリティキーを呼び出す主体(クライアント)と、Attestation、Assertionを検証する主体(サーバー)が分離している場合、クライアントが登録、認証時にアプリケーション固有のクライアントデータを生成し、クライアントデータを追加でサーバーで検証したい場合もあります。クライアントデータ自体はAttestation、Assertionと一緒に送信すれば良いですが、 クライアントデータを中間者攻撃から防御するために、クライアントデータに対して署名を行い、保護する必要があります。

さて、FIDO CTAP2では、登録時に利用する authenticatorMakeCredential メソッドと認証時に利用する authenticatorGetAssertion メソッド 、どちらにも共通するパラメータとして、clientDataHash というパラメータが存在します。セキュリティキーは、受け取った clientDataHash パラメータを署名対象のデータの一部として署名を生成するため、アプリケーションとして署名で保護したいクライアントデータのハッシュを取得し、 clientDataHash にセットすることで、アプリケーション固有のクライアントデータが改竄されていない真正なデータか、サーバー側で検証することが出来ます。

1.5. Project Modules

WebAuthn4Jは、以下の4つのModuleから構成されます。

1.5.1. Core: webauthn4j-core.jar

WebAuthn Attestation/Assertionの検証機能およびコア機能を提供します。

1.5.2. Metadata: webauthn4j-metadata.jar

FIDO Metadata Serviceを用いたTrustAnchorの解決など、追加的な機能を提供します。

1.5.3. Core-Async: webauthn4j-core-async.jar

WebAuthn Attestation/Assertionの検証機能およびコア機能の非同期版を提供します。現時点では、実験的な提供です。 含まれているクラスは、Publicであっても、セマンティックバージョニングに従わずに破壊的変更が入る場合があります。

1.5.4. Metadata-Async: webauthn4j-metadata-async.jar

FIDO Metadata Serviceを用いたTrustAnchorの解決など、追加的な機能の非同期バージョンを提供します。 現時点では、実験的な提供です。 含まれているクラスは、Publicであっても、セマンティックバージョニングに従わずに破壊的変更が入る場合があります。

1.5.5. App Attest: webauthn4j-appattest.jar

Apple App Attest Attestation/Assertionの検証機能を提供します。

1.5.6. Test: webauthn4j-test.jar

WebAuthn4Jのテストを行うための内部ライブラリです。含まれているクラスは、Publicであっても、セマンティックバージョニングに従わずに 破壊的変更が入る場合があります。

1.5.7. Util: webauthn4j-util.jar

WebAuthn4Jライブラリで使用されるユーティリティクラスをまとめたライブラリです。

1.6. カスタムなデータ変換ロジックの実装

WebAuthn4Jでは、JSONやCBORのシリアライズ、デシリアライズ処理にJacksonライブラリを使用しています。 Client ExtensionやAuthenticator Extensionのデータ変換でカスタムな変換を行いたい場合、WebAuthn4Jが内部で使用している Jacksonの ObjectMapper にカスタムなシリアライザ、デシリアライザを登録することで実現できます。

1.6.1. カスタムなデータ変換ロジックの登録

WebAuthn4Jは、Jacksonの ObjectMapperObjectConverter というクラスでラップして使用しており、 カスタムなシリアライザ、デシリアライザを登録した ObjectMapperObjectConverter インスタンス作成時にコンストラクタから インジェクトし、その ObjectConverterWebAuthnManager のインスタンス作成時にパラメータとして指定してください。

1.7. カスタムな検証ロジックの実装

WebAuthn4Jでは、カスタムな検証ロジックを実装し、追加することが可能です。 登録時の検証にカスタムロジックを追加する場合は、 CustomRegistrationVerifier を実装してください。 認証時の検証にカスタムロジックを追加する場合は、 CustomAuthenticationVerifier を実装してください。

1.7.1. カスタム検証ロジックの登録

CustomRegistrationVerifierCustomAuthenticationVerifier の実装は WebAuthnManager のコンストラクタの customRegistrationVerifiers パラメータおよび customAuthenticationVerifiers パラメータを通じて登録することが出来ます。

1.8. クラス

1.8.1. Data transfer Objects

com.webauthn4j.data パッケージ配下のクラスはイミュータブルなDTOとして設計されています。

1.8.2. Converter, WebAuthnModule

データパッケージ配下のクラスはJacksonによってシリアライズ、デシリアライズ可能なように設計されています。 一部のクラスはカスタムなシリアライザ、デシリアライザが必要であり、 converter パッケージ配下に集約されています。 カスタムシリアライザ、デシリアライザは WebAuthnJSONModuleWebAuthnCBORModule というJacksonのModuleにまとめられています。 WebAuthn4Jは内部で使用するJacksonの ObjectMapper に自動で WebAuthnModule を適用しますが、WebAuthnManager の外部で WebAuthn4Jのシリアライザ、デシリアライザを使用したい場合は、Jacksonの ObjectMapperWebAuthnModule を登録すると 良いでしょう。

1.8.3. TrustAnchorsResolver

TrustAnchorsResolver インタフェースは TrustAnchorCertPathTrustworthinessVerifier で構成証明ステートメントの信頼性の 検証を行う際に信頼するルート証明書のセットを探索するために使用されます。

1.8.4. TrustAnchorsProvider

TrustAnchorsProvider インタフェースは前述の TrustAnchorsResolver インタフェースの実装である TrustAnchorsResolverImpl がTrustAnchorの読込処理を委譲する先のインタフェースです。実装としてJava Key StoreファイルからTrustAnchorを読み込む KeyStoreFileTrustAnchorsProvider クラスが提供されている他、WebAuthn4J Spring Securityでは、SpringのResourceから TrustAnchorを読み込む CertFileResourcesTrustAnchorProvider が提供されています。

1.8.5. 例外クラス

データの変換に失敗した場合、 DataConversionException のサブクラスがスローされます。 データの検証に失敗した場合、 VerificationException のサブクラスがスローされます。

1.9. ログ

WebAuthn4JはSLF4Jをログインタフェースライブラリとして使用します。 Logbackなどログ実装ライブラリを構成し、ログをお好みのスタイルで出力してください。