In my previous posts (here and here) I have described how to create your Azure AD App Registration with PowerShell along with required permissions. There is one thing left when it comes to application permissions: how to configure this to authorize your code using these required resources?
As a user you probably provide a user name and a password claiming it’s you. If you have some code that is not running in the context of a user, such as a Azure Web Job or Azure Function, you do not have a username and password. So, your code needs an AppOnly access token. For this you typically use a certificate to request such access.
Azure KeyVault
Where to better store the certificate? Right, in an Azure KeyVault. You can create certificates using the Azure Portal.
Azure PowerShell has some awesome cmdlet’s to create a certificate for an Azure KeyVault. Take a look at the following code snippet:
$keyVaultName = "OCHA-KV-BLOG-DEMO-WE" ## Creating a self signed certificate Write-Host "`tCreating self-signed certificate..." $keyVaultCertificateName = "MyCertificateName" $validityInMonths = 12 $policy = New-AzureKeyVaultCertificatePolicy -SubjectName "CN=$keyVaultCertificateName" -IssuerName Self -ValidityInMonths $validityInMonths Write-Host "`tAdding certificate to the Key Vault..." $keyVaultCertificate = Add-AzureKeyVaultCertificate -VaultName $keyVaultName -Name $keyVaultCertificateName -CertificatePolicy $policy $certOp = Get-AzureKeyVaultCertificateOperation -VaultName $keyVaultName -Name $keyVaultCertificateName while ($certOp.status -eq "inProgress") { Start-Sleep 5 $certOp = Get-AzureKeyVaultCertificateOperation -VaultName $keyVaultName -Name $keyVaultCertificateName } $keyVaultCertificate = Get-AzureKeyVaultCertificate -VaultName $keyVaultName -Name $keyVaultCertificateName
First, with New-AzureKeyVaultCertificatePolicy we create a certificate policy defining validity and the issuer. In our case it is Self. Thus, it will be a self-signed certificate.
Then with this certificate policy we create and add a certificate to the KeyVault using the cmdlet Add-AzureKeyVaultCertificate. The certificate is not available instantly. We need to monitor the creation process using the cmdlet Get-AzureKeyVaultCertificateOperation. As long as the status is still “inProgress” the certificate is yet not available.
Once ready, we retrieve the newly created certificate. We need some info for the Azure AD App Registration.
Manifest
In the end, the certificate information needs to be registered in the Azure AD App’s manifest.
And to be precise, in the KeyCredentials section (line 14).
Now, if you search around on the net, you’ll find some samples that you need to have the following lines for this section. (like here https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread )
"keyCredentials": [ { "customKeyIdentifier": "<$base64CertHash>", "keyId": "<$KeyId>", "type": "AsymmetricX509Cert", "usage": "Verify", "value": "<$base64Cert>" } ],
But we are doing PowerShell. The cmdlet New-AzureRmADAppCredential to the rescue.
# # Application Key Credentials # $base64Cert = [System.Convert]::ToBase64String($keyVaultCertificate.Certificate.GetRawCertData()) $appKeyCred = New-AzureRmADAppCredential -ApplicationId $AADApplication.AppId -CertValue $base64Cert -EndDate $keyVaultCertificate.Certificate.NotAfter -StartDate $keyVaultCertificate.Certificate.NotBefore
With this cmdlet we supply the Azure AD App Id, the certificate value (a base64 string value) and the certificate’s start date and end date.
When you open the manifest, you’ll see all data except the value. That’s always hidden.
Now your code is ready to request an AppOnly Access token using the certificate.
// Get the certificate from the KeyVault var certificateBytes = await _keyvaultService.GetCertificateBytes(SigningCertificateName); var certificate = new X509Certificate2(certificateBytes, string.Empty, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.Exportable); // Create your credentials based on the certificate var cac = new ClientAssertionCertificate(_clientId, certificate); // Request an access token authResult = await _authContext.AcquireTokenAsync(resourceId, cac); string token = authenticationResult.AccessToken;
Summary
Azure PowerShell provides several cmdlets to configure AppOnly access for your custom code. It is based on a certificate stored in the Azure KeyVault. Once configured your code can create the correct set of credentials to require an access token.