DEV Community

Wilfried Woivré
Wilfried Woivré

Posted on • Originally published at woivre.com on

Generate an Azure AD Token using the REST API

Recently, I had to access to a storage account using an application account, so I set up a SPN which has an RBAC right on my storage account, as I show in this blog post: https://woivre.com/blog/2020/01/login-to-your-storage-accounts-using-azure-active-directory

Now I need to generate my access token, thing that may be easy using ADAL libraries, however for my usecase I had the following constraints :

  • Application account and a certificate authentication
  • No additional libraries (Ciao ADAL)
  • Powershell

First, we need to generate a JWT Token. As a reminder a JWT Token has the following syntax : base64(header).base64(payload).base64(signature)

Let’s start by building our header. To achieve this, we need to get the hash of our certificate :

$cert = Get-Item Cert:\CurrentUser\My\$ThumbprintValue

$hash = $cert.GetCertHash()
$hashValue = [System.Convert]::ToBase64String($hash) -replace '\+','-' -replace '/','_' -replace '='

Enter fullscreen mode Exit fullscreen mode

Now, it’s possible to build our header and payload as following :

[hashtable]$header = @{alg = 'RS256'; typ= "JWT"; x5t = $thumprintValue}
[hashtable]$payload = @{aud = "https://login.microsoftonline.com/$TenantUrl/oauth2/token"; iss = $applicationId; sub=$applicationId; jti = "22b3bb26-e046-42df-9c96-65dbd72c1c81"; exp = $exp; nbf= 1536160449}

Enter fullscreen mode Exit fullscreen mode

Now that we have all the information, we need to generate our signature and construct the token :

$headerjson = $header | ConvertTo-Json -Compress
$payloadjson = $payload | ConvertTo-Json -Compress

$headerjsonbase64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($headerjson)) -replace '\+','-' -replace '/','_' -replace '='
$payloadjsonbase64 = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($payloadjson)) -replace '\+','-' -replace '/','_' -replace '='

$jwt = $headerjsonbase64 + "." + $payloadjsonbase64
$toSign = [System.Text.Encoding]::UTF8.GetBytes($jwt)

$Signature = [Convert]::ToBase64String($rsa.SignData($toSign,[Security.Cryptography.HashAlgorithmName]::SHA256,[Security.Cryptography.RSASignaturePadding]::Pkcs1)) -replace '\+','-' -replace '/','_' -replace '='

$token = "$headerjsonbase64.$payloadjsonbase64.$Signature"

Enter fullscreen mode Exit fullscreen mode

You can check that the creation the JWT Token on some sites such as : https://jwt.io/

Here is it. We have the JWT Token which allows us to get the Access Token :


$url = "https://login.microsoftonline.com/$TenantUrl/oauth2/token"
$body = "resource=https%3A%2F%2F$storageAccountName.blob.core.windows.net%2F&client_id=$applicationId&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer&client_assertion=$token&grant_type=client_credentials"
$responseToken = Invoke-WebRequest -Method POST -ContentType "application/x-www-form-urlencoded" -Headers @{"accept"="application/json"} -Body $body $url -Verbose

$accessToken = ($responseToken.Content | ConvertFrom-Json).access_token

Enter fullscreen mode Exit fullscreen mode

After generating the token, it is possible to add it to the headers so we can call the storage account’s REST API.

$headerSMA = @{"Authorization" = "Bearer " + $accessToken; "x-ms-version" = "2017-11-09"}
Invoke-WebRequest -Headers $headerSMA -Method GET "https://$storageAccountName.blob.core.windows.net/$containerName/$blobName" -OutFile $outFile

Enter fullscreen mode Exit fullscreen mode

That’s how we request the Azure API without using the ADAL. even if it is more easier using ADAL and you have less things to know.

Top comments (0)