Featured image of post Configuring Azure VDI & AVD infrastructure to work with Device Trust

Configuring Azure VDI & AVD infrastructure to work with Device Trust

A quick chirp about how to enable Device Trust on Azure VDI Environment.


How Okta SCEP Certificates are distributed to Windows devices can cause issues with Device Trust when assigned to multiple users or when not assigned to any user, and those users lack Administrator rights.

While our initial deployment of Device Trust worked fine for our 1:1 assigned laptops, some of our other infrastructure could not use FastPass & Device Trust configurations.

This post will help you review how to correct some of these issues - that you would otherwise need to pay for Okta Professional Services.

No Assigned User for a VDI

Because no user is assigned to the VDI device in Azure AD or Intune, it is impossible to deploy User Level Certificates. This creates a challenge, as the only other way to deploy the certificate using the Okta & MEM Dynamic Challenge is at the device level.

Since our initial Okta rollout, which I have described in my previous blog post, the intent was to roll the certificates out to the assigned users of the device, we didn’t experience this problem, as we don’t have shared devices or any 1:many devices except for the VDI system on the Windows Side.

However, if your employees are not local Administrators on their devices, they wouldn’t be able to use the device-scoped certificate to enable device trust. We want authorized users on the device to use these private keys, not just random users. The next challenge is how do we get our users who are not local admins to read or have access to the private key?

How did we find out private key access was the issue?

You will need to first enable Debug Logging on Okta Verify. Once enabled, you will want to search for (but not limited to), the following phrases/words in the Event Viewer:

[LoopbackRequest][IntegrationSignalCollection][CachedStoreCertificateFetcher.CacheUnknownCertificateIssuers]: Using cached certificates for
[LoopbackRequest][DeviceContextManager.InitializeToken]: Generating device token of type DeviceChallengeTokenResponsePayload
[LoopbackRequest][KeyAccess][CryptoLib.OpenKey]: Successfully loaded existing key pair

From the Splunk logs from Okta, we need to search for Signing certificates is invalid followed by a jwt=base64 encoded string.

If you see a combination of these, your user is likely unable to access the private key.

How do we solve this?

Manual method

It is quite easy to solve this via the point and click method:

Manage Private Key Access

Default Permissions to access Private Key

While this is sorta counter intuitive, you would need to modify the existing users listed and include the designated permissions for each key, then add the user or group, and specify their permissions as well.

But how do we do this automatically?

This led us to go down the rabbit hole on how to enable the device level certificate, combing through the Okta Verify Logs on Windows, asking for Splunk logs from Okta, and started searching StackOverflow.

We tried most of the scripts in the above thread. Still, unfortunately - the scripts had syntax errors or were meant for other situations, displaying issues about Keys, Crypto, file paths, or other random problems.

PowerShell Script

When searching online, I eventually stumbled on this gist:

It seemed to be a great start, and was recent enough, but, we consistently were hitting issues every time we ran the script. This portion:

$rsaCert = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
[string] $uniqueName = $rsaCert.key.UniqueName
[string] $keyFilePath = "$env:ALLUSERSPROFILE\Microsoft\Crypto\RSA\MachineKeys\$uniqueName"
$acl = Get-Acl -Path $keyFilePath

Would output:

Get-Acl : Cannot find path
'C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys\C:\ProgramData\Microsoft\Crypto\PCPKSP\OMIT\OMIT.PCPKEY' because it does not exist.

Strange that it is using the wrong formatting and concatenating two folder path strings. I am not sure of the original design decision to use "$env:ALLUSERSPROFILE\Microsoft\Crypto\RSA\MachineKeys\ but this seems to be a standard across the internet / Stack Overflow.

Well, given that situation, and that the output of the $uniqueName also had what we needed for the $keyFilePath variable, let’s just replace the original keyFilePath with uniqueName

We end up with this:


  • Fixes the above error by bypassing the hardcoded folder path
  • Not needing to know the certificate thumbprint before the cert is deployed, and use the Certificate Subject for the device instead

If you still prefer to use the certificate’s Thumbprint, you can uncomment lines 15 and 25 and comment out the lines relating to Subject. You could also incorporate several StackOverflow script sections, to make the script more modular for your need.

Running the script

So, now we have a working script that doesn’t obliterate the ACL for the certificate’s private key; how do we ensure it gets run securely for those that need it.

Pretty simple, incorporate a currently active user session lookup using either whoami or some other alternative within the script, scheduled task, or alternative. Or use a group that is scoped on the VDI to all of those that need access, and run that either once or continuously with the following powershell command:

.\certificate-test.ps1 -certSubjectPart '$YOUR_CERTIFICATE_SUBJECT_NAME' -user '$UESERNAME_OR_GROUP' -permission 'Read'

comments powered by Disqus
Thanks for stopping by!
Built with Hugo