Method
One of the constraints is that the unattended process' user identity will not exist in Azure Active Directory; so we will use OAuth 2.0 client credentials grant flow for this scenario.
Step 1: Gather Information
First, identify the following pieces of information:
- Client ID
- Tenant ID
- Authority Url
- Resource Url
- Client Secret
You probably already have most of these if you've got OAuth working for users and roles. If not, here is what they are and where to find them.
1a: Finding the Client ID
The client ID is a GUID, and is the application's ID in Azure Active Directory. It is not the Object ID (which is different).
Azure Portal: Azure Active Directory > App registrations > [your app] > Overview blade > Application (client) ID field.
PowerShell, from a logged-in context:
$(Get-AzADApplication -DisplayName "[your app name]").ApplicationId.Guid
1b: Finding the Tenant ID
The Azure tenant ID is a GUID.
Azure Portal: Azure Active Directory > App registrations > [your app] > Overview blade > Directory (tenant) ID field.
PowerShell, from a logged-in context:
$(Get-AzContext).Tenant.Id
Azure CLI, from a logged-in context:
az account show --query 'tenantId' -o tsv
1c: Finding the Authority Url
The Authority Url is the URL of the OAuth authorization server. It looks something like this: https://login.microsoftonline.com/[your-tenant-id]/oauth2/v2.0/token
Azure Portal: Azure Active Directory > App registrations > [your app] > Endpoints button > OAuth 2.0 token endpoint (v2) field.
1d: Finding the Resource Url
The Resource Url is the URL of the Web API service. It probably looks like this: https://[yourdomain].onmicrosoft.com/[guid]
Azure Portal: Azure Active Directory > App registrations > [your app] > Expose an API blade > Application ID URI field.
It is also located in the application manifest in the identifierUris
field.
Azure Portal: Azure Active Directory > App registrations > [your app] > Manifest.
Manifest attribute example:
"identifierUris": [
"https://[yourdomain].onmicrosoft.com/[guid]"
]
PowerShell, from a logged-in context:
$(Get-AzADApplication -ApplicationId [ClientId]).IdentifierUris
Azure CLI, from a logged-in context:
az ad app show --id [ClientId] --query 'identifierUris' -o tsv
1e: Creating the Client Secret
The client secret can be a client secret (key/password) or a certificate. Here is how to create a client secret.
Azure Portal:
- Go to Azure Active Directory > App registrations > [your app] > Certificates & secrets blade > Client secret section.
- Press the New client secret button and complete this process.
- Copy the key value; this is the client secret. Don't lose it.
PowerShell: use the New-AzADAppCredential cmdlet.
Step 2: Configure the Azure Active Directory Application
Since you are using AuthorizeAttribute
Roles to control access, you must add the application to at least one of those roles. Roles are defined in the application manifest under the appRoles
attribute.
2a: Make roles that Applications can belong to
Each role has an allowedMemberTypes
attribute. If you've already configured this application for users, then you already have something like this:
"allowedMemberTypes": [
"User"
],
To allow your application to be added to a role, modify it like this:
"allowedMemberTypes": [
"User",
"Application"
],
Alternately, you could have a role that allows only applications.
"allowedMemberTypes": [
"Application"
],
2b: Add Application to its Roles
Now that there are roles that the application can belong to, you must add the application to those roles.
Azure Portal: Azure Active Directory > App registrations > [your app] > API permissions blade.
- Press the Add a permission button.
- Select the APIs my organization uses tab.
- Find and select your application.
- Press the Application permissions box.
- Select the permissions (roles) for this application.
- Finally, press the Add permissions button.
2c: Grant admin consent
If these roles require admin consent, then you will need to grant admin consent now.
Azure Portal: Azure Active Directory > App registrations > [your app] > API permissions blade > Grant consent section. Press the Grant admin consent for [your org] button, and confirm Yes.
If you don't have permissions to do this, find someone in the Application Administrator role or someone else with similar permissions to do this for you.
Step 3: Verify
At this point you should be able to use the OAuth 2.0 client credentials flow to obtain an access token, present it as a Bearer token with your request to your Web API service, and succeed.
If you want to verify using Postman or similar tool, use this guide to create the requests.
When you get your hands on a token, you can examine the contents using this tool: https://jwt.io/ Verify that there is a roles
attribute in the token, and that it is populated with the roles you assigned in the previous step.
For example:
{
…
"azpacr": "1",
"roles": [
"Approver",
"Reader"
],
"ver": "2.0"
…
}
Here is a PowerShell script showing how to do this using the ADAL.PS module:
Import-Module ADAL.PS
$tenantId = "[tenant id]"
$authority = "https://login.microsoftonline.com/$tenantId/oauth2/v2.0/authorize"
$resourceUrl = "[resource url]"
$clientId = "[client id]"
$secret = ConvertTo-SecureString -String [client secret] -AsPlainText -Force
$response = Get-ADALToken -Authority $authority -Resource $resourceUrl -ClientId $clientId -ClientSecret $secret
$token = $response.AccessToken
$response
$restResponse = Invoke-RestMethod -Method Get -Uri "[your web api uri]" -ContentType "application/json; charset=utf-8" -Headers @{ Authorization = "Bearer $token" } -Verbose -Debug
$restResponse
Step 4: Secure your Secret
Now you've got this secret in your unattended script or job. That's probably not a great idea, so secure that somehow. How you do it is outside the scope of this answer.