Microsoft recently announced their new FIDO2 provisioning APIs within Microsoft Entra ID. While users can register their FIDO2 keys fairly easily with a Temporary Access Pass, the new API allows admins to register keys on behalf of a user. This can be extremely handy in onboarding scenarios or in case a new key needs to be shipped to a vendor or contract worker.
The Microsoft APIs support every vendor of FIDO2 (passkeys), but Yubico has made some extra effort to provide a sample Python script that uses the Yubikey Manager under the hood.
How does this work?
The provisioning of security keys happens in three steps.
Source: Microsoft strengthens phishing-resistant security for Entra ID with FIDO2 provisioning APIs | Yubico
First, we ask for the creation options from Graph API. This will give us all the required information to create the credentials on the Yubikey. The script will provide this step, but if we run it using Graph Explorer, we can get a sense of what it looks like.
The next step is the ‘local’ part, where we need to add that credential to the Yubikey, using the information from the relying party (Microsoft). For this, we use a sample script that Yubico provided. This script will take care of the magic and talks to the Yubikey directly to create the new PIN and a new cryptographic keypair. This is done using the CTAP protocol.
After this step, we can finally register the key to Entra ID, using Graph API.
I expected this to be very hard to do or understand, but I got this up and running in a few minutes. Let’s take a look together, shall we?
What do we need?
- A Yubikey. For a smooth process, reset the key so it is clean.
- An app registration in Entra ID is needed to provide the correct permissions and tokens.
- An Entra ID group that holds the user(s) that you want to (bulk)provision.
- Visual Studio Code
- Yubikey Manager
- Python
- FIDO2 python module
- Yubico sample scripts
Now, I assume you can install the software requirements without guidance, but in case you need help with the Python modules, here are the commands:
pip install yubikey-manager
pip install fido2
I recommend running the script or Visual Studio terminal as an administrator.
Yubico sample scripts
Download the ZIP file from GitHub and put it somewhere on your local drive. Open the folder with Visual Studio Code and open the configs.json file. This is where we must put in our credentials, the group, and other parameters. Let’s take care of the credentials first.
Prepare Entra ID
First, let’s create a new app registration in Entra ID, and add the following permissions:
AuthenticationMethod.ReadWrite.All to create (and delete) the FIDO keys.
GroupMember.Read.All to read the provisioning group.
We then create a new secret and copy the value into the configs.json file, along with the app registration’s client ID and the tenant’s name.
The group can be a new or existing group with your test user(s).
Needless to say, the users must also be enabled for passkeys in Entra ID. In this demo, it is enabled for all users. Please check your current config.
I’ve also configured the other parameters to create a random PIN, and to delete any existing FIDO keys that exist for my user(s).
Here’s what my config file looks like:
{
"tenantName": "M365x341716.onmicrosoft.com",
"client_id": "e5d678ad-36a4-428a-8f4f-c8088401ca37",
"client_secret": "****************************************",
"usersInScopeGroup": "FIDO Provisioning",
"challengeTimeoutInMinutes": 60,
"deleteExistingUserFIDOCredentials": true,
"useRandomPIN": true,
"useCTAP21Features": false
}
Let’s go!
Cool! That was the hardest part. Now, we can see if the Python script runs. You might encounter a few missing modules, so you might want to do some trial and error.
Let’s quickly explain what the script does:
Step 1: Start with step1GetFIDO2Challenges.py. This will request a token from Entra ID using the app registration and then read the group members.
It will then delete any existing keys (if you set the deleteExistingUserFIDOCredentials parameter to ‘true’) for the user, and request the new creation options. This information will be added to the usersToRegister.csv file.
Step 2: The next and final step is to run step2CreateAndActivateCredential.py. This will read the lines from the usersToRegister.csv file and create a new credential for the key. This is where you input the Yubikey.
The information will then be stored in the keysRegistered.csv file. If you set the useRandomPIN parameter to ‘true’, the PIN will also be provided here.
The passkey has been added to the account and is also visible in Entra ID.
I’ve also created a quick video to explain the steps, so I hope that helps!
CTAP2.1 features
As you might have spotted, the script also provides a CTAP2.1 flag. When we set this to ‘true,’ we can enforce a specific PIN length and create a provisional PIN for our users.
After reading this marvelous blog post, I ordered a Yubikey BIO to test the script, and it works like a charm.
The first time the FIDO key is used with the temporary PIN, the PIN needs to be changed.
Let’s wrap up
I hope this post was valuable to you.
I’m happy to see that Yubico provided this sample code, as it will help me better understand the possibilities.
With some small adjustments, these scripts can be used with any FIDO2 key. If you’re a developer, I’m sure you can even build a nice front-end for this!
Here are the resources that I used:
Microsoft strengthens phishing-resistant security for Entra ID with FIDO2 provisioning APIs | Yubico
Public preview: Microsoft Entra ID FIDO2 provisioning APIs – Microsoft Community Hub
YubicoLabs/entraId-register-passkeys-on-behalf-of-users: Sample code using Microsoft Graph APIs to register FIDO2 security keys for Entra ID users (github.com)
Stay safe!
That is great! Can you do the same with passkeys in the authenticator app? We add the app via Intune to all our endusers, but passkey registration is tricky for our non-techsavvy users. Would be great if we could hand out phones with registered passkeys directly.