Azure API Management’s default security mechanism is built on top of subscriptions. Whilst this is a very simple way to protect your APIs, it’s often not secure enough. Many scenarios require the APIs to be protected with OAuth2, which is perfectly possible with Azure API management. It is important to understand that API Management does not come with its own Identity Provider, but you can use any OAuth2 or Open ID Connect compliant IdP. This blog post takes Azure Active Directory as an example, but the concept can be implemented with the Identity Provider of your choice.
Requirements
Recently, I had a customer with the following requirements.
- Access control is managed in the IdP, not in API Management
- The API consumers can be users or daemons
- The API consumers use standardized OAuth2 authentication flows
- The API consumers can authenticate with client secret or certificate
- For each API, read and/or write access can be granted.
The solution that I describe in this blog post, is a simple answer to these requirements. If your scenario has similar requirements, it might be beneficial for you.
Solution
Create an App Registration for APIM
- In Azure AD, we create an App Registration that represents our complete API Management instance
- In the Manifest JSON, set the accessTokenAcceptedVersion to 2. This ensures you are using Azure AD’s latest implementation that adheres more to the standards.
- For each API, create two roles. One for read and one for write access.
- The naming convention is <api-id>.<read/write>.
- Ensure that you allow Users/Groups and Applications.
- The result looks like this:
- In the Expose an API tab, change the Application ID URI to a meaningful URI. In my case: https://apis.yourazurecoach.com
Create an App Registration for the API consumer
In this blog, we will assume that a daemon want to access the API. Bear in mind that this perfectly works for users too.
- Create an App Registration that represents the API consumer
- In the API Permissions tab, add the permission to read from the Order API
- Because this is an Application permission, administrator consent must be granted.
- In the Certificates & secrets tab, create a client secret. Copy the client id and secret for later use.
- Request an Access Token to the Azure AD token endpoint:
- Grant Type: Client Credentials
- Token URL: https://login.microsoftonline.com/<tenant-id>/oauth2/v2.0/token
- Client id: copied from App Registration
- Client secret: copied from App Registration
- Scope: https://apis.yourazurecoach.com/.default
- When we inspect the Access Token, you can see the roles claim array.
Configure the global API Management policy
- Configure the following policy on the global level (All APIs):
- For GET operations, the <api-id>.read role must be present
- For other operations, the <api-id>.write role must be present
<validate-jwt header-name="Authorization" failed-validation-httpcode="401"> <openid-config url=https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration /> <audiences> <audience>https://apis.yourazurecoach.com</audience> </audiences> <required-claims> <claim name="roles" match="any"> <value>@(context.Request.Method == "GET" ? $"{context.Api.Id}.read" : $"{context.Api.Id}.write")</value> </claim> </required-claims> </validate-jwt>
- From now on, API consumers that don’t have the required role, will get a 401 Unauthorized
Conclusion
To be honest, I am really proud of this generic solution and I’m applying it at more and more projects.
Remember: sharing is caring!
Toon