Configuring Azure AD App for AppOnly permissions with PowerShell

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.

image

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.

image

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.

image

And to be precise, in the KeyCredentials section (line 14).

image

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.

image

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.

Share

Leave a Reply

Your email address will not be published. Required fields are marked *