In the modern digital era, securing APIs is essential. OAuth 2.0 is a trusted method for managing access, and the Proof Key for Code Exchange (PKCE) adds an extra layer of security, especially for mobile and single-page applications.
This blog will walk you through implementing OAuth 2.0 with PKCE in Azure API Management (APIM) to enhance security and prevent code interception attacks.
Why PKCE:
PKCE mitigates the risk of authorization code interception by using a dynamically generated secret instead of a static client secret. It works by introducing:
- Code Verifier: A randomly generated string by the client.
- Code Challenge: A hashed version of the code verifier, sent during authorization.
- Code Exchange: The client sends the original code verifier to validate the request.
This ensures that only the legitimate client that initiated the request can exchange the authorization code for an access token.
OAuth2.0:
OAuth, short for "Open Authorization," allows users grant third-party applications access to their data without sharing credentials. The term "grant type" in OAuth 2.0 refers to how an application obtains an access token, with several types defined.
APIM supports following grant types:
- Authorization code
- Authorization code + PKCE
- Implicit (deprecated)
- Resource owner password
- Client credentials
Reference https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-oauth2
How Authorization code grant flow works?
Consider a scenario where the developer portal acts as the client, Microsoft Entra as identity provider and the developer portal is attempting to access the API in APIM. The user selects an authorization type on the developer portal to request access to a resource. The portal redirects the user to the Microsoft Entra Authorization Server for login and authorization.
After the user authenticates and grants permission, the server generates an authorization code and redirects the user back to the application. The developer portal exchanges this code, along with the application's credentials, for an access token from the Authorization Server.
Once verified, the server issues an ID token, access token, and optionally a refresh token.
The developer portal then uses the access token to make authenticated requests to the API in APIM, accessing the protected resource.
How Authorization code + PKCE grant flow works?
Below is a step-by-step breakdown of how it works -
1.User Initiates Access Request: The user clicks on a drop-down button and selects authorization type on the developer portal that requests access to a resource.
2.Code Verifier and Challenge Creation: The client app (developer portal) creates a cryptographically-random codeverifier and generates a codechallenge from it.
- code_verifier is a random key that prevents the authorization code from being intercepted. code_verifier is generated by the client application for every authorization request and transformed into code_challenge according to the code_challenge_method set for the client application in advance. It’s mandatory to set the code_challenge_method value to S256, where possible.
3.Redirection to Authorization Server: The developer portal redirects the user to the Microsoft Entra Authorization Server through the /authorize endpoint, along with the code_challenge.
4.User Authentication and Consent: The user is prompted to log in and authorize.The Authorization Server prompts the user to log in and authorize. The user authenticates themselves and grants permission to the developer portal.
5.Authorization Code Generation: The Authorization Server stores the code_challenge and redirects the user back to the application with a single-use authorization code using the specified redirect URI.
6.Exchange Authorization Code for Access Token: The developer portal sends the authorization code and the code_verifier (created in step 2) to the Authorization Server's /oauth/token endpoint.
7.Verification and Token Issuance: The Authorization Server verifies the codechallenge and codeverifier. It then responds with an ID token, access token, and optionally, a refresh token.
8.Accessing the Protected Resource: The developer portal uses the obtained access token to make authenticated requests to the API in APIM, accessing the protected resource.
Let's visualize the Authorization Code + PKCE Grant Flow with a pictorial representation:
* Highlighted the steps different from authorization code grant flow.
Implementation:
For a detailed step-by-step guide on implementing OAuth 2.0, refer to the official documentation:
Protecting Backend APIs with Azure AD
Additionally, there is an extra configuration step:
You need to include the following redirect URI in the Single-Page Application Redirect URIs section of the client app registration, as shown in the screenshot:
https://<<apim service name>>.developer.azure-api.net/signin-oauth/code-pkce/callback/<<authservername>>
Troubleshooting utilities
1.Fiddler for OAuth Debugging
To troubleshoot OAuth-related issues in the Developer Portal, you can use the Fiddler tool. It helps capture the complete session, allowing you to analyse requests, responses, and potential errors.
2.Troubleshooting with Chrome
1.If you need to troubleshoot using Chrome, you can enable popup inspection in Developer Tools: Open Developer Tools (F12 or Ctrl + Shift + I).
2.Go to Settings → Preferences → Global.
3.Enable "Auto-open DevTools for popups."
This will automatically open Developer Tools alongside any popups. However, note that this method does not display popups as part of the browser’s trace stack.
Common problems with authorization code+ pkce setup:
Scenario1: Incorrect redirect URI:
Solution: Copy the redirect URI from the error and include in the client application app registration under authentication ->single page applications.
Scenario2:
Solution: Add single page application as type in authentication section of client app
Scenario3: CORS issue.
Solution: Apply CORS policy to resolve this error. You can either add the policy manually or configure cors policy automatically. More details in : https://learn.microsoft.com/en-us/azure/api-management/enable-cors-developer-portal
Scenario4: Authorization Request Fails.
Solution: When an authorization request fails, it often means there is an issue with the endpoint URL or the parameters being sent. Verify that the authorization endpoint URL is correct and that all required parameters (such as clientid, responsetype, redirect_uri, scope, and state) are included and correctly formatted. Additionally, ensure that the redirect URI registered with the identity provider matches the one being used in the request.
Scenario5: Access Token Not Issued.
Solution: If an access token is not issued, it could be because the identity provider does not support PKCE or it is not enabled. Check the identity provider's documentation to confirm that PKCE is supported and ensure it is enabled in the configuration settings. Also, verify that the code challenge method (S256 or plain) is correctly specified in the authorization request.
Scenario6: Token Validation Fails in APIM.
Solution: In Azure API Management (APIM), token validation can fail if the validate-jwt policy is not properly configured or token sent is invalid. This policy checks the JSON Web Token (JWT) for validity. Ensure that the issuer (iss) claim in the token matches the expected issuer configured in the validate-jwt policy. Additionally, verify that the audience (aud) claim and other relevant claims are correctly set. Check the signing keys and algorithms used to sign the token to ensure they match the configuration in APIM.
Additional Resources
For a detailed explanation of other OAuth 2.0 grant types, refer to this blog post: https://techcommunity.microsoft.com/blog/azurepaasblog/protect-apis-using-oauth-2-0-in-apim/2309538
Conclusion
By implementing OAuth 2.0 with PKCE in Azure API Management, you enhance the security of your APIs by preventing authorization code interception.
This approach is ideal for mobile and single-page applications, ensuring a secure and scalable authentication process.