NAME
Authen::WebAuthn - A library to add Web Authentication support to server applications
VERSION
version 0.004
SYNOPSIS
This module lets you validate Web Authentication registration and authentication responses.
Currently, it does not handle the generation of registration and authentication requests.
The transmission of requests and responses from the application server to the user's browser, and interaction with the WebAuthn browser API is also out of scope and could be handled by a dedicated JS library.
To register a new device:
# Obtain registration response from web browser
# Then,
my $webauthn_rp = Authen::WebAuthn->new(
rp_id => "app.example.com",
origin => "https://app.example.com"
);
my $registration_result = eval {
$webauthn_rp->validate_registration(
challenge_b64 => ... ,
requested_uv => ... ,
client_data_json_b64 => ... ,
attestation_object_b64 => ... ,
token_binding_id_b64 => ... ,
)
};
if ($@) {
die "Error validating registration: $@";
}
To authenticate a user:
# Obtain authentication response from web browser
# Then,
my $webauthn_rp = Authen::WebAuthn->new(
rp_id => "app.example.com",
origin => "https://app.example.com"
);
my $validation_result = eval {
$webauthn_rp->validate_assertion(
challenge_b64 => ...,
credential_pubkey_b64 => ...,
stored_sign_count => ...,
requested_uv => ...,
client_data_json_b64 => ...,
authenticator_data_b64 => ...,
signature_b64 => ...,
extension_results => ...,
token_binding_id_b64 => ...,
trust_anchors => ...,
)
};
if ($@) {
die "Error validating authentication: $@";
}
ATTRIBUTES
rp_id
The identifier of your Relying Party. Usually, this is set to the domain name over which your application is accessed (app.example.com).
origin
The origin, as defined by the HTML standard, that your Relying Party is expecting to find in registration or authentication responses. This must contain the scheme and port of your application, but no path (http://app.example.com:8080 or https://app.example.com)
METHODS
validate_registration
This method validates the registration response emitted by the authenticator.
It takes the following named arguments
- challenge_b64
-
The base64url-encoded challenge that was submitted to the authenticator
- requested_uv
-
Whether or not the Relying Party required user verification for this operation. Possible values are
required
,preferred
,discouraged
. - client_data_json_b64
-
The base64url-encoded client data received from the authenticator
- attestation_object_b64
-
The base64url-encoded attestation object received from the authenticator
- token_binding_id_b64
-
The base64url-encoded Token Binding ID for the current connection. Usually this comes from a
Sec-Provided-Token-Binding-ID
HTTP header. If you are not using Token Binding, you can omit this parameter. - trust_anchors
-
If the authenticator response contains an attestation,
validate_registration
will attempt to chain it to a trusted root certificate. You need to explicitly specify which certificates to trust if your authenticator provides an attestation.If you requested "none" as an attestation format while initiating the registration flow, there is no need to provide any trust anchors.
This optional parameter can either be an arrayref of strings representing PEM-encoded certificates, or a subref which returns a arrayref of PEM-encoded certificates:
sub { my (%params) = @_; my $aaguid = $params{'aaguid'}; my $attestation_type = $params{'attestation_type'}; my $attestation_format = $params{'attestation_format'}; ... return [ $pem1, $pem2, ...]; }
- allowed_attestation_types
-
If you want to restrict the allowed attestation types, you can pass an arrayref of strings as the
allowed_attestation_types
parameter.Currently supported values are
None
,Self
,Basic
By default, all attestation types are allowed
- allow_untrusted_attestation
-
By default, if an attestation type such as
Basic
is used by the authenticator and a correct trust_anchor could not be found, the validation will fail as mandated by the WebAuthn specification. However, in some cases it is permitted to allow the registration to proceed, but treat it asSelf
attestation.This setting allows you to successfully validate registration, but change the type to
Self
if a trusted certificate was not provided in thetrust_anchors
parameter.
This method croaks on errors. If the registration was successful, it returns a hashref with the following subkeys:
- credential_id
-
The base64url-encoded credential ID for this authenticator
- credential_pubkey
-
The base64url-encoded public key for this authenticator, in COSE format
- signature_count
-
The initial signature count of this authenticator
This information is supposed to be persisted in the Relying Party, usually in some sort of database
The following keys are also returned:
- attestation_result
-
Contains information about the result of the attestation validation
- type
-
The type of attestation used by the authenticator:
None
,Self
,Basic
, ... - trust_path
-
An arrayref of DER-encoded certificates provided by the authenticator
- aaguid
-
The verified AAGUID of the authenticator, this is only provided if the attestation was verified successfully and chained up to a trusted root certificate.
validate_assertion
This method validates the registration response emitted by the authenticator.
It takes the following named arguments
- challenge_b64
-
The base64url-encoded challenge that was submitted to the authenticator
- credential_pubkey_b64
-
The base64url-encoded credential public key corresponding to the received Credential ID
- stored_sign_count
-
The current signature count in the Relying Party's database. Set it to 0 to disable verification of the signature count
- requested_uv
-
Whether or not the Relying Party required user verification for this operation. Possible values are
required
,preferred
,discouraged
. - client_data_json_b64
-
The base64url-encoded client data received from the authenticator
- authenticator_data_b64
-
The base64url-encoded authenticator data received from the authenticator
- signature_b64
-
The base64url-encoded signature received from the authenticator
- extension_results
-
A hashref containing extension results received from the authenticator
- token_binding_id_b64
-
The base64url-encoded Token Binding ID for the current connection. Usually this comes from a
Sec-Provided-Token-Binding-ID
HTTP header. If you are not using Token Binding, you can omit this parameter.
This method croaks on errors. If the registration was successful, it returns a hashref with the following subkeys:
- signature_count
-
The new signature count, to be updated in the Relying Party's database
convert_raw_ecc_to_cose
my $cose_b64 = Authen::WebAuthn::convert_raw_ecc_to_cose($u2f_b64);
This method takes the base64url-encoded raw ECC key (U2F format) and converts it to a base64url-encoded COSE representation. It can be useful for converting existing U2F device registration to WebAuthen device registrations in your Relying Party.
CAVEAT
This module only supports the "None" attestation type at the moment, which means Relying Parties cannot have a strong guarantee of the authenticator's security properties. This makes it possible for users to register weak authenticators.
Because of that, is it not recommended to use this module in passwordless authentication scenarios. However, it should be good enough for using security keys as a second factor.
This limitation may be addressed in a future version.
SEE ALSO
- W3C Web Authentication specification
- FIDO::Raw
-
A library with a similar purpose, based on Yubico's libfido2
- Authen::U2F
-
A library for adding U2F support to server applications
- Crypt::U2F::Server
-
A library for adding U2F support to server applications, based on Yubico's libu2f-server
AUTHOR
Maxime Besson <mbesson@cpan.org>
COPYRIGHT AND LICENSE
This software is copyright (c) 2024 by Maxime Besson.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.