README.md

# WebAuthnLite

W3C Web Authentication API (a.k.a. WebAuthN / FIDO 2.0) RP library in Elixir

## Installation

If [available in Hex](https://hex.pm/docs/publish), the package can be installed
by adding `web_authn_lite` to your list of dependencies in `mix.exs`:

```elixir
def deps do
  [
    {:web_authn_lite, "~> 0.1.0"}
  ]
end
```

Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
be found at [https://hexdocs.pm/web_authn_lite](https://hexdocs.pm/web_authn_lite).

# Usage : 1. Registration

## 1.1. Generate and store challenge

### Server-side

```Elixir
challenge = WebAuthnLite.Challenge.generate_base64_url_encoded_challenge()

conn
|> put_session(:webauthn_register_challenge, challenge) # for phenix etc...
...
```

## 1.2. Request WebAuthn registration

### Client-side

Set Base64 URL decoded challenge and call `navigator.credentials.create()`

## 1.3. Send encoded response to Server-side

### Client-side

Encode following params and send them to server-side.

* `clientDataJSON`
* `attestationObject`

## 1.4. Validate ClientDataJSON

### Server-side

```Elixir
challenge = conn |> get_session(:webauthn_register_challenge)

{:ok, client_data_json} =
  WebAuthnLite.Operation.Register.validate_client_data_json(
    %{client_data_json: encoded_client_data_json,
      origin: origin,
      challenge: challenge
    }
  )
```

## 1.5. Validate AttestationObject

### Server-side

```Elixir
{:ok, attestation_object} = 
  WebAuthnLite.Operation.Register.validate_attestation_object(
    %{attestation_object: encoded_attestation_object,
      client_data_json: encoded_client_data_json,
      rp_id: rp_id,
      up_required: up_required,
      uv_required: uv_required})
```

## 1.6. Store Credential.Id with account

### Server-side

```Elixir
pubkey = attestation_object.auth_data.attested_credential_data.credential_public_key

# identifier
pubkey_id = attestation_object.auth_data.attested_credential_data.credential_id

# key params
pubkey_map = pubkey.map
pubkey_json = pubkey.json
```

# Usage : 2. Authentication

## 2.1. Generate and store challenge

### Server-side

```Elixir
challenge = WebAuthnLite.Challenge.generate_base64_url_encoded_challenge()

conn
|> put_session(:webauthn_authn_challenge, challenge) # for phenix etc...
...
```

## 2.2. Request WebAuthn authentication

### Client-side

Set Base64 URL decoded challenge and call `navigator.credentials.get()`

## 2.3. Send encoded response to Server-side

### Client-side

Encode following params and send them to server-side.

* `clientDataJSON`
* `authenticatorData`
* `signature`

## 2.4. Validate clientDataJSON

### Server-side

```
challenge = conn |> get_session(:webauthn_authn_challenge)

{:ok, client_data_json} =
  WebAuthnLite.Operation.Authenticate.validate_client_data_json(
    %{client_data_json: encoded_client_data_json,
      origin: origin,
      challenge: challenge
    }
  )
```

## 2.5. Validate authenticatorData

```Elixir
{:ok, authenticator_data} =
  WebAuthnLite.Operation.Authenticate.validate_authenticator_assertion(
    %{signature: encoded_signature,
      authenticator_data: encoded_authenticator_data,
      client_data_json: encoded_client_data_json,
      public_key: public_key,
      rp_id: rp_id,
      up_required: up_required,
      uv_required: uv_required,
      sign_count: sign_count})
```