Roles. For example:[Authorize(Roles = "Reader,Requester,Editor,Approver,Administrator")]
In my specific scenario, this is because we don't sync our numerous on-premises AD service accounts to AAD, and this script will be running from an on-premises service principal identity.
AuthorizeAttribute to control our script's access to controllers/actions within the Web API.How can I make this work?
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.
First, identify the following pieces of information:
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.
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
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
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.
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
The client secret can be a client secret (key/password) or a certificate. Here is how to create a client secret.
Azure Portal:
PowerShell: use the New-AzADAppCredential cmdlet.
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.
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"
],
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.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With