Assessing Azure API Management authorisation approaches
Introduction
As part of our consulting engagements, it is common that our customers ask us to provide guidance on the different authentication and authorisation approaches available on API Management and how they meet their security needs while offering support to existing legacy API clients. While many people now know that OAuth 2.0 is the industry protocol for HTTP authorisation, there are cases where some API consumers don’t provide support for it. Thus, organisations need to know when alternative controls can be implemented.
In this post, I will share our starting position for this type of assessment. It’s worth noting that each organisation has different needs and there is always the need to tailor this assessment accordingly.
Context
Before assessing each of the different authorisation approaches available on API Management, it’s important to understand the difference between authentication and authorisation. We also need to understand who is meant to be calling the API and the type of data being exposed. Let’s explore these topics in more detail.
API client authentication use cases
To classify an API consumer, first, we can consider different use cases. Do we need to authorise an application or an end user? Shall we allow an anonymous client to call the API? Three main use cases are described in the table below.
Use case |
Description |
Examples |
Anonymous |
No authentication is required to call an API. |
Any unauthenticated client |
End-user authentication |
Permissions are granted at user level. |
A user accessing their own data via an API |
Application authentication |
An application needs to authenticate to gain access to an API. |
A web application needs to authenticate against a database to get access to data. A service running in the background needs to authenticate to call an API. |
API client trust level
Depending on who owns and manages the API client and where it is deployed, different security controls will need to be in place. We can use the model below to classify API clients based on their trust level.
Trust level |
Description |
Examples |
First-party internal |
A trusted application that belongs to the organisation and is deployed within a trusted private network, either on-premises or on the cloud. |
A service running in the background and deployed on-premises A serverless function deployed in the organisation’s cloud private network. |
First-party external |
A trusted system that is owned and controlled by the organization but deployed outside the private network. |
A cloud-hosted SaaS application owned by the organisation, e.g., a SaaS CRM or ERP. A corporate mobile app developed internally. |
Third-party |
Any system that is not trusted. |
A strategic customer’s application A vendor’s system An application configured by an end user. |
API client types
It is important that we also consider if the API client is a mobile application, a client-side web application, or a server-side application. This is relevant to understand how the API credentials are going to be managed and stored.
Trust level |
Description |
Examples |
Client-side web application |
A single-page web application that directly calls the APIs. |
A javascript application that runs in the user's browser |
Native mobile application |
A native mobile application that calls the APIs. |
An Android app An iOS app |
Server-side application |
A server application that calls APIs in another system. |
A cloud based serverless application that calls APIs hosted on another service |
Data confidentiality and integrity
When protecting an API, it’s crucial to understand the type of information that is being exposed by the API and the type of operations the API consumer can perform against the data.
When implementing authorisation on an API, we are dealing with two key data security pillars.
- Confidentiality ensures that only allowed consumers can access the exposed data. We should have a data-classification framework in place to understand the level of sensitivity of the information being exposed and an access control model that dictates who has access to what.
- Integrity ensures that the data exposed by the API cannot be altered by clients that are not authorised to do so. We need to understand if different API consumers have different access levels to the information being exposed. For instance, while some users have read-only access, others can modify their own records, and some privileged users are able to perform read and write operations on all records.
A secure API must be able to guarantee the confidentiality and integrity of the information it exposes. Understanding the confidentiality level of the data and the data operations being exposed by the API would help us to better define the authorisation approach required for the API.
We have explored the different authentication use cases, client trust levels and types, and discussed the importance of understanding the data classification and the type of operations API clients can perform against the exposed data. Let’s now explore the different authentication and authorisation approaches available on API Management.
Available Approaches
Let’s start by describing the authentication and authorisation approaches available on API Management. In the table below I describe different authentication and authorisation approaches and give a summary of how they can be implemented on API Management.
Approach |
Description |
Authentication |
Authorisation |
Anonymous |
Anonymous access allows any user or application to access an API without requiring authentication |
N/A |
N/A |
Client IP address |
The API client authenticates against the API using its own IP address |
Source IP address in the IP packets or the X-Forwarded-For header for requests going through a proxy. |
ip-filter policy for direct calls. Using the check-header policy for calls going through a proxy to validate the X-Forwarded-For header |
API key |
The client application authenticates by adding a key to each API request. API keys can be sent as query parameters or HTTP headers. API keys are relatively easy for legacy API clients to implement. |
API key in the query parameters or HTTP headers |
Requires a subscription at product or API level and the corresponding subscription scope assignment. |
HTTP basic authentication |
The basic HTTP authentication scheme transmits credentials as user-id/password pairs, encoded in Base64. The standard is documented in the Internet Engineering Task Force's RFC7617. |
User-id/password pair encoded in Base64 via the Authorization header as described in the official documentation. |
Using the check-header policy and checking that the “Authorization” header contains “Basic” + the base64 encoded user-id/password pair.
When dealing with secrets on API Management, these must be stored as secret name values in Key Vault. |
Client certificate |
Client certificate authentication is an authentication approach, where the client provides its client certificate to the server to prove its identity as a part of the TLS handshake. |
The client provides a client certificate message excluding the private key. The client is authenticated by using its private key to sign a hash of all the messages. The recipient verifies the signature using the public key of the signer, thus ensuring it was signed with the client’s private key. Refer to RFC 5246 for more details. |
Using the validate-client-certificate policy or validating context variables. |
OAuth 2.0 client credentials flow |
The OAuth 2.0 client credentials grant flow is part of the open authorisation standard and permits an application to use its own credentials – instead of impersonating a user – to authenticate when calling an API. It is commonly used for server-to-server interactions that must run in the background. |
The client application authenticates against an identity provider to get an access token that is passed to the API for authorisation following a standard flow. |
Using the validate-azure-ad-token policy for validating JWTs provided by Azure AD and validate-jwt policy for third-party identity providers.
|
OAuth 2.0 authorization code flow |
The OAuth 2.0 authorization code flow is described in section 4.1 of the OAuth 2.0 specification. It's used to perform authentication and authorization in the majority of application types, including single-page applications, server-side web applications, native mobile apps, and daemons and server-side apps. The flow enables applications to securely acquire end-user access tokens that can be used to access secured resources. |
An end user authenticates against an identity provider to get a token that is passed to the API for authorisation following a standard flow. |
Using the validate-azure-ad-token policy for validating JWTs or ID tokens provided by Azure AD and validate-jwt policy for third-party identity providers.
|
Assessment
Once we understand the different authorisation approaches available on API Management, let’s assess them against different scenarios and define when these approaches are recommended or if not, when they can be leveraged as tolerated approaches under certain circumstances. In the table below, I describe when the scenarios for which these approaches are not applicable, when they are recommended, the conditions under which they can be tolerated and additional considerations for each. As mentioned previously, this assessment should be used just as a starting position but must be tailored to each organisation’s needs.
Approach |
Not applicable scenarios |
Recommended scenarios |
Tolerated scenarios |
Additional notes |
Anonymous |
N/A |
Not recommended |
For 1st party internal clients and read-only APIs that do not expose sensitive or confidential information. When required for external clients, for read-only and minimal risk APIs that only expose information classified as public. |
When exposing anonymous APIs, additional security controls must be in place, such as a firewall for thread detection & protection, DDoS protection, a web application firewall, rate-limiting policies, etc. |
Client IP address |
End-user authentication Client-side web application Native mobile applications |
Not recommended |
1st party internal clients using a private IP address when recommended authorisation approaches are not available to the API consumer. As an additional security control on top of endorsed authorisation approaches or security measures. |
IP spoofing can be easily leveraged to overcome security controls. |
API key |
For client-side web applications or native mobile apps, as API keys can be easily leaked. While end users can get API keys, keys are typically used for application authentication scenarios. |
Not recommended |
For APIs that do not expose sensitive or confidential information and a recommended authorisation method is not supported by the clients. Not as an authorisation approach, but for rate limiting or usage statistics. |
When used for authentication purposes, always use HTTP headers to pass an API key. Secrets must never be passed in URL query strings as there are many risk factors.
|
HTTP basic authentication |
For client-side web applications or native mobile apps, as secrets can be easily leaked. |
Not recommended |
For APIs that do not expose sensitive or confidential information and a recommended authorisation method is not supported by API clients. |
When using this approach, avoid storing plain text credentials in an API Management policy. Instead, use secret named values stored on Key Vault.
|
Client certificate |
End-user authentication Client-side web application |
For application authentication scenarios, where certificates are preferred over client ids and client secrets.
|
N/A |
When client certificates are preferred over client secrets, consider leveraging the OAuth 2.0 client credentials flow with certificate-based request. While certificate authentication can be used for end-users, it is not recommended as authentication policies on API Management expect to authorise a single certificate. The same restriction applies to client-side web applications. Consider the operational overhead of managing client certificates. |
OAuth 2.0 client credentials flow |
End-user authentication Client-side web application Native mobile application |
Recommended for server-side application authorisation |
N/A |
When validating JWTs, it is important to validate not only the audience but role claims as well to ensure the application has the right level of access as documented here. |
OAuth 2.0 authorization code flow |
Application authentication |
Recommended for end-user authorisation |
N/A |
When validating JWTs, it is important to validate not only the audience but role claims as well to ensure the end user has the right level of access. |
An additional note on OAuth 2.0 client credentials.
When discussing the different authorisation approaches with customers, a couple of times I’ve faced some skepticism about the OAuth 2.0 client credentials flow. Their main arguments have typically been:
- MFA cannot be enabled for applications. Once the client ID and client secret are leaked, then it’s practically the same level of security as basic authentication.
- TLS protects the basic authentication credentials on every request.
- JWT access tokens cannot be revoked on Azure AD.
- Service principals in the Azure Active Directory tenant can be over-permissioned
So, what are really the benefits of the OAuth 2.0 client credentials flow over basic authentication? Below are the arguments I present.
- Even though TLS is protecting every single request, it’s always better to ensure that credentials do not travel very frequently. The less frequently secrets travel over the wire, the lower the chances of getting them compromised by a man-in-the-middle (MITM) attack.
- If an access token gets compromised, the access token will expire. On the contrary, when credentials get compromised by a MITM attack, they could be unnoticedly used for a longer period.
- Delegating the authentication to a trusted and robust identity provider brings many benefits.
- Centralised and built-in sign-in audit logs and threat detection and protection features.
- Centralised secret strength and expiry policies.
- Secret rotation policies and capabilities.
- Secrets don’t have to be managed and asserted on the API layer.
- Besides validating the token’s audience and the role claims (authorisation), the API is fully abstracted from the authentication process.
- Azure AD and other identity providers support not only a shared secret but also certificates and federated credentials for the client credentials flow.
- Azure AD supports managed identities for the OAuth 2.0 client credentials flow. When the API consumers are an Azure resource within the same tenant, managed identities remove the need to manage secrets.
- The scoping features of the JWTs. Having well-defined audience and roles claims, allows for fine-grained privilege bracketing. When authorising an API client, we can validate not only the target audience in the JWT, but the roles the client has against to on the API, e.g., read, write, etc.
- It’s also worth recognising that currently on Azure AD, JWT access tokens cannot be revoked. And while refresh tokens (long-lived) can be revoked, the OAuth 2.0 client credentials flow only relies on access tokens. Thus, considering that we can’t revoke access tokens, we must configure the access token lifetime according to the organisation’s needs. Furthermore, if an access token gets compromised by a MITM attack, it’s highly likely that it will go unnoticed or if we become aware of it, by the time we can action a revocation procedure, the access token is most likely expired.
- To avoid over-permissioned service principals, we need to follow the least privilege principle and apply the right audience and role claims when granting access to the service principal.
Conclusions
In this post, I discussed and assessed the different authentication and authorisation approaches available in API Management based on general principles. If you’re planning to endorse authorisation approaches for your own project or organisation, please consider this as a baseline. Always make your own assessment based on the organisation’s unique situation and needs.
Furthermore, API authorisation is just one of the many security controls you must consider when protecting your APIs on API Management. I’d recommend you to be familiar with the API Management security baseline and make sure you have the right security controls in place. Other key security controls to consider are:
- Implement network protection:
- Segregate public-facing and internal-facing APIs.
- Protect against common web exploits and vulnerabilities by deploying a Web Application Firewall (WAF) in front of API Management.
- Implement DDoS protection.
- For higher security, consider thread detection and protection via a firewall.
- Always ensure data encryption in transit.
- Implement rate-limiting or throttling
- Define and implement role-based access control (RBAC) that includes privilege access management.
- Ensure zero trust end-to-end protection for APIs and backend services.
I hope you’ve found this post useful and that it has provided some guidance to make your APIs more secure.
Happy clouding!
Cross-posted on Deloitte Engineering
Follow me on @pacodelacruz