== クイックスタート

WebAuthn認証は、事前に認証デバイスで生成した公開鍵をサーバーに登録し、認証時に認証デバイスで生成した
署名を公開鍵で検証することで認証が成立する認証方式です。登録時にサーバーに送信される公開鍵やデバイスの構成情報を
含むデータは構成証明（Attestation）と呼ばれ、認証時にサーバーに送信される署名を含んだデータはアサーション（Assertion）と呼ばれます。

=== 構成証明の検証

認証デバイスの登録時に構成証明を検証する際は、`RegistrationRequest` を引数に
`WebAuthnManager#validate` メソッドを用いて登録リクエストのパース、検証を行ってください。
登録リクエストの検証でエラーが発生した場合に、元のパースされたデータにアクセスしたい場合は、
`WebAuthnManager#parse` メソッドを用いて登録リクエストをパースしたうえで、
得られた `RegistrationData` のインスタンスを `WebAuthnManager#validate` メソッドに渡して実行してください。

`RegistrationRequest` のメンバー はフロントエンド側でWebAuthn JS APIを実行して取得した値となります。
何らかの方法でフロントエンド側からサーバー側に伝送し、指定してください。

`RegistrationParameters` は、`WebAuthnManager#validate` メソッドのもう一つの引数であり、
サーバーの状態や検証条件をまとめたパラメータです。 サーバーの状態については、 `serverProperty` としてまとめています。
`ServerProperty` のコンストラクタを呼び出す際のパラメータには以下の値を指定して下さい。

- `origin` にはWebAuthnによる認証を提供するサイトのOriginを指定して下さい。WebAuthnでは、ブラウザが認識しているOriginを
ClientDataに書き込んで署名を行います。WebAuthn4Jは書き込まれたOriginが指定されたOriginと合致するかを検証することで、
フィッシング攻撃を防ぎます。
- `rpId` にはWebAuthnによる認証を提供するサイトのrpIdを指定して下さい。rpIdは資格情報のスコープを指定するパラメータです。
詳しくは https://www.w3.org/TR/webauthn-1/#relying-party-identifier[WebAuthnの仕様書のrpIdの項] を参照して下さい。
- `challenge` には発行したChallengeを指定して下さい。`challenge` はリプレイ攻撃を防ぐ為のパラメータです。
サーバー側で `challenge` としてランダムなバイト列を生成し、フロントエンド側でWebAuthn JS APIを実行する際に
パラメータとして指定して署名対象に含め、サーバー側で値の一致を検証することで、リプレイ攻撃からユーザーを防御することが出来ます。
発行したChallengeを検証時まで永続化しておくのはアプリケーション側の責務です。セッションなどに格納しておくと良いでしょう。
- `tokenBindingId` はToken bindingを利用する場合のパラメータです。利用しない場合は `null` を指定してください。

検証に失敗した場合は、 `ValidationException` のサブクラスの例外が発生します。
検証に成功した場合は、返却された値から `Authenticator` インスタンスを作成し、データベース等へアプリケーション側で永続化して下さい。
認証時に必要となります。

```java
// Client properties
byte[] attestationObject = null /* set attestationObject */;
byte[] clientDataJSON = null /* set clientDataJSON */;
String clientExtensionJSON = null;  /* set clientExtensionJSON */;
Set<String> transports = null /* set transports */;

// Server properties
Origin origin = null /* set origin */;
String rpId = null /* set rpId */;
Challenge challenge = null /* set challenge */;
byte[] tokenBindingId = null /* set tokenBindingId */;
ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, tokenBindingId);

// expectations
boolean userVerificationRequired = false;
boolean userPresenceRequired = true;
List<String> expectedExtensionIds = Collections.emptyList();

RegistrationRequest registrationRequest = new RegistrationRequest(attestationObject, clientDataJSON, clientExtensionJSON, transports);
RegistrationParameters registrationParameters = new RegistrationParameters(serverProperty, userVerificationRequired, userPresenceRequired, expectedExtensionIds);
RegistrationData registrationData;
try{
    registrationData = webAuthnManager.parse(registrationRequest);
}
catch (DataConversionException e){
    // If you would like to handle WebAuthn data structure parse error, please catch DataConversionException
    throw e;
}
try{
    webAuthnManager.validate(registrationData, registrationParameters);
}
catch (ValidationException e){
    // If you would like to handle WebAuthn data validation error, please catch ValidationException
    throw e;
}

// please persist Authenticator object, which will be used in the authentication process.
Authenticator authenticator =
        new AuthenticatorImpl( // You may create your own Authenticator implementation to save friendly authenticator name
                registrationData.getAttestationObject().getAuthenticatorData().getAttestedCredentialData(),
                registrationData.getAttestationObject().getAttestationStatement(),
                registrationData.getAttestationObject().getAuthenticatorData().getSignCount()
        );
save(authenticator); // please persist authenticator in your manner
```

=== アサーションの検証

認証時にアサーションを検証する際は、`AuthenticationRequest` を引数に  `WebAuthnManager#validate` メソッドを
実行してください。`AuthenticationRequest` の
コンストラクタの引数に指定する、 `credentialId` と `userHandle` 、 `authenticatorData`  、 `clientDataJSON` 、`signature` は
フロントエンド側でWebAuthn JS APIを実行して取得した値となります。
何らかの方法でフロントエンド側からサーバー側に伝送し、指定してください。
`WebAuthnManager#validate` メソッドのもう一つの引数である `AuthenticationParameters`  の
コンストラクタの引数に指定する、 `serverProperty` はサーバー側から取得する値をまとめたパラメータです。

`userVerificationRequired` は認証デバイスでのユーザーの本人性確認が必要かどうかを示すパラメータです。
パスワード＋認証デバイスの「所持」による多要素認証を行う場合は、パスワードで本人性の確認が出来ている為 `false` で良いでしょう。
パスワードレス認証として、認証デバイスによる本人性確認＋「所持」による多要素認証を行う場合は `true` を指定する必要があります。

`Authenticator` には、登録時に永続化した `Authenticator` を指定してください。

検証に失敗した場合は、 `ValidationException` のサブクラスの例外が発生します。
検証後は、 `Authenticator` に紐づけたカウンタの値を更新してください。カウンタは万が一認証デバイスのクローンが
作成された場合を検知するために用意されています。カウンタについて詳しくは
https://www.w3.org/TR/webauthn-1/#sign-counter[WebAuthnの仕様書のカウンタの項] を参照して下さい。

```java
// Client properties
byte[] credentialId = null /* set credentialId */;
byte[] userHandle = null /* set userHandle */;
byte[] authenticatorData = null /* set authenticatorData */;
byte[] clientDataJSON = null /* set clientDataJSON */;
String clientExtensionJSON = null /* set clientExtensionJSON */;
byte[] signature = null /* set signature */;

// Server properties
Origin origin = null /* set origin */;
String rpId = null /* set rpId */;
Challenge challenge = null /* set challenge */;
byte[] tokenBindingId = null /* set tokenBindingId */;
ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, tokenBindingId);

// expectations
boolean userVerificationRequired = true;
boolean userPresenceRequired = true;
List<String> expectedExtensionIds = Collections.emptyList();

Authenticator authenticator = load(credentialId); // please load authenticator object persisted in the registration process in your manner

AuthenticationRequest authenticationRequest =
        new AuthenticationRequest(
                credentialId,
                userHandle,
                authenticatorData,
                clientDataJSON,
                clientExtensionJSON,
                signature
        );
AuthenticationParameters authenticationParameters =
        new AuthenticationParameters(
                serverProperty,
                authenticator,
                userVerificationRequired,
                userPresenceRequired,
                expectedExtensionIds
        );

AuthenticationData authenticationData;
try{
    authenticationData = webAuthnManager.parse(authenticationRequest);
}
catch (DataConversionException e){
    // If you would like to handle WebAuthn data structure parse error, please catch DataConversionException
    throw e;
}
try{
    webAuthnManager.validate(authenticationData, authenticationParameters);
}
catch (ValidationException e){
    // If you would like to handle WebAuthn data validation error, please catch ValidationException
    throw e;
}
// please update the counter of the authenticator record
updateCounter(
        authenticationData.getAuthenticatorData().getAttestedCredentialData().getCredentialId(),
        authenticationData.getAuthenticatorData().getSignCount()
);
```

