I am trying to get a list of all devices from Intune and their associated bitlocker keys, if there is one. I am able to get a list of all devices no problem, but I can not find the correct permissions to get the bitlocker keys. I am using Powershell for 2 methods: one using the Graph cmdlets provided by Microsoft, and another using the API and Invoke-RestMethod
. Both methods are using the same service principal for authentication.
Method 1:
C:\> Get-MgInformationProtectionBitlockerRecoveryKey
Get-MgInformationProtectionBitlockerRecoveryKey_List1: Failed to authorize, token doesn't have the required permissions.
Method 2:
C:\> $Params = @{
>> Uri = "https://graph.microsoft.com/beta/informationProtection/bitlocker/recoveryKeys"
>> Headers = @{
>> Authorization = "Bearer $Token"
>> ConsistencyLevel = "eventual"
>> }
>> ErrorAction = 'Stop'
>> }
C:\> (Invoke-RestMethod @Params)
Invoke-RestMethod: {"error":{"code":"authorization_error","message":"Failed to authorize, token
doesn't have the required permissions.","innerError":{"date":"2023-11-10T19:18:31",
"request-id":"xxxxxxxxxxxxxxxx","client-request-id":"xxxxxxxxxxxxxxxxxxxx"}}}
The service principal we are using has always worked in the past. The service principal was granted both the Global Reader and Intune Administrator roles, as well as the BitlockerKey.Read.All
app permission. Note that the BitlockerKey.Read.All
had to be set to Delegated, as no Application permissions were available. I have been following the instructions from this documentation from Microsoft saying that it has to be set to Delegated but you must grant certain role access, however I am still unable to get authorization.
Does anybody know how to properly authenticate, or know of a way to get the bitlocker keys?
Edit: I am providing the Powershell used to authenticate for both methods.
Method 1: Connect-MgGraph
The $ClientId
is the id of the service principal, found in Entra > Identity > Applications > App Registrations. The $ClientSecret
is password.
$Params = @{
ClientId = $ClientId
ClientSecret = $ClientSecret
TenantId = $TenantId
ForceRefresh = $true
ErrorAction = 'Stop'
}
$AccessToken = (Get-MsalToken @Params).AccessToken
Connect-MgGraph -AccessToken $AccessToken -ErrorAction Stop |Out-Null
Method 2: Invoke-RestMethod
with the Graph API
The $Credential
variable is the credentials of the same service principal used in Method 1.
$Params = @{
Uri = "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token"
Body = @{
'client_id' = $Credential.UserName
'scope' = 'https://graph.microsoft.com/.default'
'client_secret' = $Credential.GetNetworkCredential().password
'grant_type' = 'client_credentials'
}
Method = 'Post'
ContentType = 'application/x-www-form-urlencoded'
ErrorAction = 'Stop'
}
$GraphAccessToken = Invoke-RestMethod @Params |Select-Object -ExpandProperty access_token
[pscustomobject]@{
GraphAccessToken = $GraphAccessToken
}
Edit 2: I tried the steps in the verified answer of this Stackoverflow forum about adding the additional Uri in the Authentication page in Entra, but with no luck. It still yields the exact same results. I also tried using Get-MsalToken
instead of Invoke-RestMethod
to get the access token. This had no impact as well.
I found a solution for those wondering. Since I was only doing a one-time export, I just ran it from my own personal account, although a service account may work just as fine. I did not use the service principal to authenticate. Here is the basic code:
Connect-MgGraph -Scopes 'BitLockerKey.Read.All' -TenantId 'xxxxxxxxxxxxxx'
$BitLockerKeys = Get-MgInformationProtectionBitlockerRecoveryKey -All