« Previous 1 2 3
Secure authentication with FIDO2
Replacements
First Login
Now that the public key and the credential ID assigned by the security token are stored in the database, the user can log on to your system. Again, the user first uses GET to request the challenge and other parameters from the application server. Because you do not have a valid session at this time, the JavaScript client in your application needs to query the username or, as described, read it from a login form. Along with the username, which you pass in with the URL for simplicity's sake, all the stored credential IDs of the user can now be read from the database. Remember that these are stored in Base64 encoding; therefore you transmit all stored IDs to the client so it can select a suitable one. You do not need the public key in this call yet. You can now create the challenge with the commands:
$ids = array(); foreach($dbdata AS $credentials){$ids[] = base64_decode($credentials['credentialId']); } $getArgs = $WebAuthn>getGetArgs($ids); $_SESSION['challenge'] = $WebAuthn-> getChallenge(); print(json_encode($getArgs)); return;
You will have to adapt the variables and indexes in the foreach
construct to match your database structure. Now the client can sign the challenge with a security token to match the IDs and POST the signature back to the web application in the body of the challenge. The challenge for selecting a security token in Firefox is shown in Figure 2.
Now read the HTTP body of the request again and decode the JSON it contains as shown above. The following commands take the data apart and decode the Base64 data it contains once again:
$clientDataJSON = base64_decode($post->clientDataJSON); $authenticatorData = base64_decode($post->authenticatorData); $signature = base64_decode($post->signature); $credentialId = base64_decode($post->id);
Now find the public key to match the credential ID in your database and store it in the $credentialPublicKey
variable. Again, remember that the data in the database is Base64 encoded. If there is no matching key, you need to return a corresponding error. To do so, use an object and the success
and msg
attributes as shown earlier. If the public key is found, you still need the challenge from the session, which you can then use to perform the check:
$challenge = $_SESSION['challenge']; $WebAuthn->processGet($clientDataJSON, $authenticatorData, $signature, $credentialPublicKey, $challenge);
This command throws a WebAuthnException
if an error occurs during the check; you need to handle this accordingly. Without an error, the user is considered to be logged in. Now you can create all session data, just as after a normal login, and then report success back to the client. You can reload the page with JavaScript or configure a redirection to a subpage.
Other Possible Uses
Once you have completed the development of a FIDO2 login as shown, you will certainly start thinking about many potential adjustments to the process. For example, given the appropriate information, authentication can be implemented without the need to enter usernames. Or you can use FIDO2 as a second factor, just as some online services already make use of its functionality. With Windows 10 and Microsoft Hello as the authenticator, you can also use FIDO2 on the devices in your Windows domain.
Conclusions
In this article, I showed you how to enable FIDO2-based login for a web service. If you prefer to use languages other than PHP for your web development, you will find similar libraries for them. The principle remains the same, and you do not necessarily have to adapt the JavaScript page of the client. Just try out the different FIDO2 configuration and usage possibilities.
Infos
- Have I Been Pwned: https://haveibeenpwned.com
- EIDI project: https://itsec.cs.uni-bonn.de/eidi/ (in German)
- FIDO: https://fidoalliance.org/fido2/
- WebAuthn demo page: https://webauthn.io
- WebAuthn library by Lukas Buchs: https://github.com/lbuchs/WebAuthn
« Previous 1 2 3
Buy this article as PDF
(incl. VAT)