WebAuthnLite

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

Installation

If available in Hex, the package can be installed by adding web_authn_lite to your list of dependencies in mix.exs:

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

Documentation can be generated with ExDoc and published on HexDocs. Once published, the docs can be found at https://hexdocs.pm/web_authn_lite.

Usage : 1. Registration

1.1. Generate and store challenge

Server-side

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.

1.4. Validate ClientDataJSON

Server-side

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

{:ok, attestation_object} =
WebAuthnLite.Operation.Register.validate_attestation_object(
%{attestation_object: encoded_attestation_object,
client_data_json: encoded_client_data_json})

1.6. Store Credential.Id with account

Server-side

pubkey = attestation_object.auth_data.attested_credential_data.credential_public_key
# identifier
pubkey_id = encoded_raw_id
# key params
pubkey_map = pubkey.map
pubkey_json = pubkey.json

Usage : 2. Authentication

2.1. Generate and store challenge

Server-side

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.

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

{: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})