Register Authenticators
First authenticator registration

Credential Creation Options

Now we want to register a new authenticator and attach it to a user. This step can be done during the creation of a new user account or if the user already exists and you want to add another authenticator.
You can attach several authenticators to a user account. It is recommended in case of lost devices or if the user gets access on your application using multiple platforms (smartphone, laptop…).
To register a new authenticator, you need to generate and send a set of options to it. These options are defined in a Webauthn\PublicKeyCredentialCreationOptions object.
To generate that object, you just need to call the methodgeneratePublicKeyCredentialCreationOptions of the $server object. This method requires a Webauthn\PublicKeyCredentialUserEntity object that represents the user entity to be associated with this new authenticator.
1
<?php
2
3
use Webauthn\PublicKeyCredentialUserEntity;
4
use Webauthn\PublicKeyCredentialCreationOptions;
5
6
$userEntity = new PublicKeyCredentialUserEntity(
7
'john.doe',
8
'ea4e7b55-d8d0-4c7e-bbfa-78ca96ec574c',
9
'John Doe'
10
);
11
12
/** This avoids multiple registration of the same authenticator with the user account **/
13
/** You can remove this code if it is a new user **/
14
// Get the list of authenticators associated to the user
15
$credentialSources = $credentialSourceRepository->findAllForUserEntity($userEntity);
16
17
// Convert the Credential Sources into Public Key Credential Descriptors
18
$excludeCredentials = array_map(function (PublicKeyCredentialSource $credential) {
19
return $credential->getPublicKeyCredentialDescriptor();
20
}, $credentialSources);
21
/** End of optional part**/
22
23
$publicKeyCredentialCreationOptions = $server->generatePublicKeyCredentialCreationOptions(
24
$userEntity, // The user entity
25
PublicKeyCredentialCreationOptions::ATTESTATION_CONVEYANCE_PREFERENCE_NONE, // We will see this option later
26
$excludeCredentials // Excluded authenticators
27
// Set [] if new user
28
);
Copied!
Now send the options to the authenticator using your favorite Javascript framework, library or the example available in the Javascript page.
The Public Key Credential Creation Options object (variable $publicKeyCredentialCreationOptions) can be serialized into JSON.
The variable $publicKeyCredentialCreationOptions and $userEntity have to be stored somewhere. These are needed during the next step. Usually these values are set in the session or solutions like Redis.

Response Verification

When the authenticator sends you the computed response (i.e. the user touched the button, fingerprint reader, submitted the PIN…), you can load it and check it.
The authenticator response looks similar to the following example:
1
{
2
"id": "LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
3
"rawId": "LFdoCFJTyB82ZzSJUHc-c72yraRc_1mPvGX8ToE8su39xX26Jcqd31LUkKOS36FIAWgWl6itMKqmDvruha6ywA",
4
"response": {
5
"clientDataJSON": "eyJjaGFsbGVuZ2UiOiJOeHlab3B3VktiRmw3RW5uTWFlXzVGbmlyN1FKN1FXcDFVRlVLakZIbGZrIiwiY2xpZW50RXh0ZW5zaW9ucyI6e30sImhhc2hBbGdvcml0aG0iOiJTSEEtMjU2Iiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9",
6
"attestationObject": "o2NmbXRoZmlkby11MmZnYXR0U3RtdKJjc2lnWEcwRQIgVzzvX3Nyp_g9j9f2B-tPWy6puW01aZHI8RXjwqfDjtQCIQDLsdniGPO9iKr7tdgVV-FnBYhvzlZLG3u28rVt10YXfGN4NWOBWQJOMIICSjCCATKgAwIBAgIEVxb3wDANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZdWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAwMDBaGA8yMDUwMDkwNDAwMDAwMFowLDEqMCgGA1UEAwwhWXViaWNvIFUyRiBFRSBTZXJpYWwgMjUwNTY5MjI2MTc2MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZNkcVNbZV43TsGB4TEY21UijmDqvNSfO6y3G4ytnnjP86ehjFK28-FdSGy9MSZ-Ur3BVZb4iGVsptk5NrQ3QYqM7MDkwIgYJKwYBBAGCxAoCBBUxLjMuNi4xLjQuMS40MTQ4Mi4xLjUwEwYLKwYBBAGC5RwCAQEEBAMCBSAwDQYJKoZIhvcNAQELBQADggEBAHibGMqbpNt2IOL4i4z96VEmbSoid9Xj--m2jJqg6RpqSOp1TO8L3lmEA22uf4uj_eZLUXYEw6EbLm11TUo3Ge-odpMPoODzBj9aTKC8oDFPfwWj6l1O3ZHTSma1XVyPqG4A579f3YAjfrPbgj404xJns0mqx5wkpxKlnoBKqo1rqSUmonencd4xanO_PHEfxU0iZif615Xk9E4bcANPCfz-OLfeKXiT-1msixwzz8XGvl2OTMJ_Sh9G9vhE-HjAcovcHfumcdoQh_WM445Za6Pyn9BZQV3FCqMviRR809sIATfU5lu86wu_5UGIGI7MFDEYeVGSqzpzh6mlcn8QSIZoYXV0aERhdGFYxEmWDeWIDoxodDQXD2R2YFuP5K65ooYyx5lc87qDHZdjQQAAAAAAAAAAAAAAAAAAAAAAAAAAAEAsV2gIUlPIHzZnNIlQdz5zvbKtpFz_WY-8ZfxOgTyy7f3Ffbolyp3fUtSQo5LfoUgBaBaXqK0wqqYO-u6FrrLApQECAyYgASFYIPr9-YH8DuBsOnaI3KJa0a39hyxh9LDtHErNvfQSyxQsIlgg4rAuQQ5uy4VXGFbkiAt0uwgJJodp-DymkoBcrGsLtkI"
7
},
8
"type": "public-key"
9
}
Copied!
The library needs PSR-7 requests. In the example below, we use nyholm/psr7-server to get that request.
1
<?php
2
3
use Nyholm\Psr7\Factory\Psr17Factory;
4
use Nyholm\Psr7Server\ServerRequestCreator;
5
6
$psr17Factory = new Psr17Factory();
7
$creator = new ServerRequestCreator(
8
$psr17Factory, // ServerRequestFactory
9
$psr17Factory, // UriFactory
10
$psr17Factory, // UploadedFileFactory
11
$psr17Factory // StreamFactory
12
);
13
14
$serverRequest = $creator->fromGlobals();
15
16
try {
17
$publicKeyCredentialSource = $server->loadAndCheckAttestationResponse(
18
'_The authenticator response you received…',
19
$publicKeyCredentialCreationOptions, // The options you stored during the previous step
20
$serverRequest // The PSR-7 request
21
);
22
23
// The user entity and the public key credential source can now be stored using their repository
24
// The Public Key Credential Source repository must implement Webauthn\PublicKeyCredentialSourceRepository
25
$publicKeyCredentialSourceRepository->saveCredentialSource($publicKeyCredentialSource);
26
27
// If you create a new user account, you should also save the user entity
28
$userEntityRepository->save($userEntity);
29
} catch(\Throwable $exception) {
30
// Something went wrong!
31
}
Copied!
Last modified 1d ago