Callback
To Start
You will receive a json file from the web browser. It's need to be controlled before accepting the registration.
The json file must have this structure :
{
"id": "BP63qesxI-...",
"rawId": "BP63qesxI-...",
"response": {
"attestationObject": "o2NmbXRmcGFja2VkZ2F0dFN0bXSj...",
"clientDataJSON": "eyJ0eXBlIjoid2ViYXV0aG4uY3J...",
"transports": ["nfc", "usb"],
"publicKeyAlgorithm": -8,
"publicKey": "MCowBQYDK2VwAyE...",
"authenticatorData": "pwU_KOYP8gQFgRDoKV9JAJG_LMGwWBtPT..."
},
"type": "public-key",
"authenticatorAttachment": "cross-platform"
};
The id is the id generated by the authenticator (crendential.id
).
First of all, instantiate the client and the RP has defined previously :
<?php
use Svgta\WebAuthn\client;
require dirname(__FILE__, 2) . '/vendor/autoload.php';
$webauthn = new client();
$webauthn->rp->set(
name: 'My wonderful project',
);
Perform the validation
Do the Validation
This exemple is a base of use :
$aaguid = $webauthn->register()->aaguid();
$validation = $webauthn->register()->validate(); //return a json string
Get the response of the authenticator
You will receive an array :
userHandle
: the user.idcredentialId
: the id given by the authentificatorjsonData
: the datas of the process in a json string.
Example of a result of jsonData
:
{
"userHandle": "86948860-...",
"date": {
"registrationTs": 1701002021,
"registrationDate": "2023-11-26 13:33:41",
"lastAccesTs": 1701002021,
"lastAccesDate": "2023-11-26 13:33:41"
},
"credential": {
"alg": -8,
"id": "M5XWWYD4e6M...",
"publicKeyCredentialSource": {
"publicKeyCredentialId": "M5XWWYD4e6M...",
"type": "public-key",
"transports": ["nfc", "usb"],
"attestationType": "basic",
"trustPath": {
"type": "Webauthn\\TrustPath\\CertificateTrustPath",
"x5c": ["-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----\n"]
},
"aaguid": "2fc0579f-8113-47ea-b116-bb5a8db9202a",
"credentialPublicKey": "pAEBAycgBiFY...",
"userHandle": "ODY5NDg...",
"counter": 4,
"otherUI": null
}
},
"info": {
"registration": {
"isUserPresent": true,
"isUserVerified": true,
"hasAttestedCredentialData": true,
"signCount": 4
},
"authentication": [],
"attestedCredentialData": {
"metadataBLOB": {
"aaguid": "2fc0579f-...",
"attestationCertificateKeyIdentifiers": [],
"statusReports": [{
"status": "FIDO_CERTIFIED_L1",
"effectiveDate": "2020-05-12",
"certificationDescriptor": "YubiKey ...",
"certificateNumber": "FIDO20020190826002",
"certificationPolicyVersion": "1.1.1",
"certificationRequirementsVersion": "1.3"
}, {
"status": "FIDO_CERTIFIED",
"effectiveDate": "2020-05-12"
}
],
"timeOfLastStatusChange": "2020-05-12"
},
"metadataStatement": {
"legalHeader": "Submission of this statement and retrieval and use of this statement indicates acceptance of the appropriate agreement located at https:\/\/fidoalliance.org\/metadata\/metadata-legal-terms\/.",
"aaguid": "2fc0579f-...",
"attestationCertificateKeyIdentifiers": [],
"description": "YubiKey ...",
"alternativeDescriptions": [],
"authenticatorVersion": 328706,
"protocolFamily": "fido2",
"schema": 3,
"upv": [{
"major": 1,
"minor": 0
}
],
"authenticationAlgorithms": ["secp256r1_ecdsa_sha256_raw", "ed25519_eddsa_sha512_raw"],
"publicKeyAlgAndEncodings": ["cose"],
"attestationTypes": ["basic_full"],
"userVerificationDetails": [[{
"userVerificationMethod": "passcode_external"
}, {
"userVerificationMethod": "presence_internal",
"caDesc": {
"base": 64,
"minLength": 4,
"maxRetries": 8,
"blockSlowdown": 0
}
}
], [{
"userVerificationMethod": "passcode_external",
"caDesc": {
"base": 64,
"minLength": 4,
"maxRetries": 8,
"blockSlowdown": 0
}
}
], [{
"userVerificationMethod": "presence_internal"
}
], [{
"userVerificationMethod": "none"
}
]],
"keyProtection": ["hardware", "secure_element"],
"matcherProtection": ["on_chip"],
"cryptoStrength": 128,
"attachmentHint": ["external", "wired", "wireless", "nfc"],
"tcDisplay": [],
"tcDisplayPNGCharacteristics": [],
"attestationRootCertificates": ["-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----"],
"ecdaaTrustAnchors": [],
"icon": "data:image\/png;base64,iVBORw0KGgoAAAANSUhEU...",
"authenticatorGetInfo": ["basic_full"],
"supportedExtensions": []
}
}
}
}
Without attestation, it's someting like that :
{
"userHandle": "8dc2279f-...",
"date": {
"registrationTs": 1701002775,
"registrationDate": "2023-11-26 13:46:15",
"lastAccesTs": 1701002775,
"lastAccesDate": "2023-11-26 13:46:15"
},
"credential": {
"alg": -8,
"id": "O1kSf7QDZGY...",
"publicKeyCredentialSource": {
"publicKeyCredentialId": "O1kSf7QDZGYUc...",
"type": "public-key",
"transports": [],
"attestationType": "none",
"trustPath": {
"type": "Webauthn\\TrustPath\\EmptyTrustPath"
},
"aaguid": "00000000-0000-0000-0000-000000000000",
"credentialPublicKey": "pAEBAycgBiFYI...",
"userHandle": "OGRjMjI3OWYt...",
"counter": 3,
"otherUI": null
}
},
"info": {
"registration": {
"isUserPresent": true,
"isUserVerified": true,
"hasAttestedCredentialData": true,
"signCount": 3
},
"authentication": [],
"attestedCredentialData": {
"metadataBLOB": "Unknown device",
"metadataStatement": "Unknown device"
}
}
}
Explanation :
date
: give the date of the registration of the device. The update date is the same as the create date.userHandle
: is the user.id given to make the registrationcredential
:alg
: the algorithm used by the device to sign the datas. The same algorithm will be used to sign datas for the authentication processid
: the key.id of the devicepublicKeyCredentialSource
: the datas to do the authentication process
info
: informations about the user and the device. You can use them to do more verifications or, for example, using the icon of the device in your app.
What to save in your DataBase
For the authentication process, you will need to give back the jsonData string.
You may be need to index in your dataBase for tje authentication process :
userHandle
credentialId
You will have an exception if you asked in the parameters to have an attestation without MDS json given. You need to give a MDS (MetaData Service) to verify the attestation.
MetaData Service
Basic usage
MDS is needed to verify attestation. The library accept the value in a json string.
Example :
{
"aaguid": "...",
"metadataStatement": {
"legalHeader": "Submission ...",
"aaguid": "...",
"description": "Pone ...",
"authenticatorVersion": 1,
"protocolFamily": "fido2",
"schema": 3,
"upv": [{
"major": 1,
"minor": 0
}
],
"authenticationAlgorithms": [
"secp256r1_ecdsa_sha256_raw"
],
"publicKeyAlgAndEncodings": [
"ecc_x962_raw",
"cose"
],
"attestationTypes": [
"basic_full"
],
"userVerificationDetails": [
[{
"userVerificationMethod": "passcode_internal"
}
],
[{
"userVerificationMethod": "fingerprint_internal"
}
]
],
"keyProtection": [
"hardware",
"secure_element"
],
"matcherProtection": [
"software"
],
"cryptoStrength": 128,
"attachmentHint": [
"nfc",
"bluetooth"
],
"tcDisplay": [],
"attestationRootCertificates": [
"MIIBwTCCAWegAwIBAgIUM9zX0yKQj8xg..."
],
"icon": "data:image/png;base64,iVBORw0KGgoAAAA...",
"authenticatorGetInfo": {
"versions": [
"FIDO_2_0"
],
"extensions": [
"hmac-secret"
],
"aaguid": "09591fc6981148f78f57b9f23df6413f",
"options": {
"plat": false,
"rk": true,
"clientPin": false,
"up": true,
"uv": true
},
"transports": [
"ble",
"nfc"
],
"firmwareVersion": 1
}
},
"statusReports": [{
"status": "NOT_FIDO_CERTIFIED",
"effectiveDate": "2022-11-10"
}
],
"timeOfLastStatusChange": "2022-11-10"
}
To validate with MDS :
$aaguid = $webauthn->register()->aaguid();
$webauthn->mds->load($jsonMDS);
Using MDS from FIDO Alliance
The FIDO Alliance offer for free an API to the MDS3 BLOB (link to the webpage). It's a JWT. You can use this library to get all the datas.
You must not get the MDS3 BLOB from Fido Alliance every time. You need to save the datas in your database and call the update when needed. The JWT give the date of the next update : please, use it.
The library save the MDS3 BLOB in your temp dir and parse in it the datas.
$webauthn->fido->update();
//Get the next update date :
$date = $webauthn->fido->nextUpdate(); //2023-12-01 -> save it in your database
//Get all MDS in json string format
foreach( $webauthn->fido->get_tmp_mds() as $aaguid => $json){
//process the save in your dataBase with :
// key : $aaguid (string)
// value : $json (string)
}
If you need to validate attestation with a MDS from FIDO Alliance :
From your database
$aaguid = $webauthn->register()->aaguid();
//...
// Process to get the json string from your dataBase using the $aaguid key
//...
$webauthn->mds->load($jsonString);
$ret = $webauthn->register()->validate(); //return a json string
From your server temp dir after getting the MDS3 Blob
$aaguid = $webauthn->register()->aaguid();
if($mdsJson = $webauthn->fido->get_tmp_mds_aaguid($aaguid))
$webauthn->mds->load($mdsJson);
$ret = $webauthn->register()->validate();
Last updated