View Source WaxAPIREST.Callback behaviour (wax_api_rest v0.4.0)

Behaviour for the callback module that implements various tasks for WaxAPIREST.Plug

Note that users shall be authenticated in some manner when registering - relying on the provided username would be insecure as it would allow an attacker to register new key (and then authenticate) for any existing account.

Link to this section Summary

Types

Key data

User information

List of registered user keys

Callbacks

Returns the current challenge

Callback called on Plug.Conn.t/0 upon successful authentication

Save the current attestation or authentication challenge and returns the connection

Returns the user info required for WebAuthn

Returns the user keys

Link to this section Types

@type key_data() :: %{
  :cose_key => Wax.CoseKey.t(),
  optional(:transports) => [WaxAPIREST.Types.AuthenticatorTransport.t()] | nil,
  optional(:sign_count) => non_neg_integer()
}

Key data

@type user_info() :: %{
  :id => String.t(),
  optional(:name) => String.t(),
  optional(:display_name) => String.t()
}

User information

The returned id field must be URL base64 encoded no longer than 64 bytes.

@type user_keys() ::
  [{credential_id :: Wax.CredentialId.t(), key_data()}]
  | %{optional(credential_id :: Wax.CredentialId.t()) => key_data()}

List of registered user keys

Link to this section Callbacks

@callback get_challenge(conn :: Plug.Conn.t()) :: Wax.Challenge.t() | no_return()

Returns the current challenge

If a fault occurs an exception can be raised. Its error message will be displayed in the JSON error response.

Link to this callback

on_authentication_success(conn, credential_id, authenticator_data)

View Source
@callback on_authentication_success(
  conn :: Plug.Conn.t(),
  credential_id :: Wax.CredentialId.t(),
  authenticator_data :: Wax.AuthenticatorData.t()
) :: Plug.Conn.t() | no_return()

Callback called on Plug.Conn.t/0 upon successful authentication

Can be used to set a value (cookie...) in the connection.

Signature counter update should be performed at this step, if supported.

If a fault occurs an exception can be raised. Its error message will be displayed in the JSON error response.

Link to this callback

put_challenge(conn, challenge)

View Source
@callback put_challenge(
  conn :: Plug.Conn.t(),
  challenge :: Wax.Challenge.t()
) :: Plug.Conn.t() | no_return()

Save the current attestation or authentication challenge and returns the connection

If a fault occurs an exception can be raised. Its error message will be displayed in the JSON error response.

Link to this callback

register_key(conn, credential_id, authenticator_data, attestation_result)

View Source
@callback register_key(
  conn :: Plug.Conn.t(),
  credential_id :: Wax.CredentialId.t(),
  authenticator_data :: Wax.AuthenticatorData.t(),
  attestation_result :: Wax.Attestation.result()
) :: Plug.Conn.t() | no_return()

Saves a new attestation key for a user

The COSE key can be retrieved in the authenticator data using:

authenticator_data.attested_credential_data.credential_public_key

The COSE key is a map of integers (both keys and values). This can be conveniently saved in Erlang / Elixir using Erlang's term_to_binary/1 function (and possibly Base.encode64/1 if the database doesn't accept binary values).

The signature count can also be checked against the value saved in the database:

authenticator_data.sign_count

A single user can register several keys. Each key is identified by its key_id.

It returns the connection. This can be used to set a value (cookie...) in it.

If a fault occurs an exception can be raised. Its error message will be displayed in the JSON error response.

@callback user_info(conn :: Plug.Conn.t()) :: user_info() | no_return()

Returns the user info required for WebAuthn

This callback is called during attestation and authentication option request and must return the identifier of the user. This identifier is the user handle of the user account entity. As stated by the specification:

A user handle is an opaque byte sequence with a maximum size of 64 bytes. User handles are not meant to be displayed to users. The user handle SHOULD NOT contain personally identifying information about the user, such as a username or e-mail address;

The callback shall, however, return a string and not a binary as it will not be converted to a string.

It can also returns the name and display name of the user (see WaxAPIREST.Callback.user_info/0). If not provided, it will be defaulted to the request's values.

If the user doesn't exist or a fault occurs when retrieving user information, an exception can be raised. Its error message will be displayed in the JSON error response.

@callback user_keys(conn :: Plug.Conn.t()) :: user_keys()

Returns the user keys

If a fault occurs an exception can be raised. Its error message will be displayed in the JSON error response.