/images/resources/code-examples/azure-oauth-proxy-apim-policy.jpg

OAuth Proxy for Azure API Management

On this page

The OAuth Proxy is an extension to your API gateway that you need when your single page applications (SPAs) call OAuth-secured APIs using the Token Handler pattern. The SPA sends an encrypted proxy cookie that transports an access token. The OAuth Proxy plugin decrypts the cookie to extract the access token.

When the OAuth Proxy work completes, Azure API Management routes the request to the target API, which uses the access token to implement its OAuth security.

Download the OAuth Proxy

You get the OAuth Proxy by downloading the latest ZIP file version from the Curity Developer Portal, with a filename of the following form. This zip file contains a Java 17 Azure function, an Azure API Management policy fragment and a README file with detailed instructions.

text
1
curity-token-handler-proxy-azure-<version>.zip

Prepare Decryption

You need an asymmetric keypair as part of your overall token handler deployment. To create one, follow the instructions in the Configure Cryptographic Keys section of the Create a Token Handler tutorial. This results in a PKCS#8 file with an encrypted private key, and also a private key password.

Deploy the OAuth Proxy

You must deploy the OAuth Proxy to a gateway that runs in your SPA's backend for frontend domain. If a deployment uses the following URLs, the OAuth Proxy executes in a gateway at https://bff.product.example:

  • SPA Web Origin: https://www.product.example
  • Backend for Frontend Base URL: https://bff.product.example
  • Target API Base URL: https://api.example.com

To deploy the OAuth Proxy, first define settings in the configure.bicepparam file. You must configure the cookie decryption key for the OAuth Proxy, using the content of the PKCS#8 file, and the PKCS#8 file's password. An example configuration is shown here:

text
1234567
using './lib/configure.bicep'
param apiManagementServiceName = 'myServiceName'
param functionAppName = 'myFunctionApp'
param restrictFunctionAppToApiManagementIp = true
param cookieKey = loadTextContent('key.pem')
param cookieKeyPassword = 'myS3cret'

If the OAuth Agent uses a different prefix for cookie names than the default value th-, you should also configure a cookiePrefix that matches the value from the OAuth Agent. You can find further details on parameters in the lib/configure.bicep file. Also, locate the policy fragment file at lib/policy-fragment.xml.

Next, apply the configuration to a resource group for services in the gateway domain. You can run the following command using the Azure CLI:

bash
12345
az login
az deployment group create --resource-group <name-of-resource-group> \
--template-file lib/configure.bicep \
--parameters configure.bicepparam \
--mode incremental

Finally, upload the Azure function using the following command:

bash
12
cd bin/func
func azure functionapp publish <functionAppName>

Configure API Routes

You must configure the OAuth Proxy for all API routes that the SPA calls. Also, add a route such as /oauthuserinfo if the SPA calls the authorization server's OpenID Connect userinfo endpoint.

In Azure API Management you configure API routes using policies. You must enable CORS to instruct the browser to allow requests with cookies from the SPA's web origin, and deny access to untrusted origins. Enable settings such as these, so that your SPA can send cross-origin JSON requests:

xml
123456789101112131415161718
<policies>
<inbound>
<cors allow-credentials="true">
<allowed-origins>
<origin>https://example.com</origin>
</allowed-origins>
<allowed-methods preflight-result-max-age="86400">
<method>*</method>
</allowed-methods>
<allowed-headers>
<header>*</header>
</allowed-headers>
<expose-headers>
<header>*</header>
</expose-headers>
</cors>
</inbound>
</policies>

You must then configure the route to use the OAuth Proxy, so that the main cookie processing logic is applied when Azure API Management receives requests from your SPA:

xml
1234567
<policies>
<inbound>
<cors>...</cors>
<include-fragment fragment-id="CURITY-TOKEN-HANDLER"/>
</inbound>
...
</policies>

OAuth Proxy Output

At runtime, the OAuth Proxy processes cookies in incoming requests from SPAs and returns a result. On success, the policy fragment from the download applies the result to the HTTP request, setting the access token in the HTTP authorization header. You can then route the access token to the target API, which uses it for authorization.

xml
123
<set-header name="Authorization" exists-action="override">
<value>@($"Bearer {context.Variables["thProxyAccessToken"]}")</value>
</set-header>

If the OAuth Proxy experiences an invalid cookie error, it returns a 400 response to the gateway, or throws an exception in the event of an unexpected error. The policy fragment transforms error results and returns responses with an HTTP 401 status code for invalid cookie errors. If required, you can customize the gateway error responses.

xml
123456789101112
<choose>
<when condition="@(((IResponse)context.Variables["thProxyCookieResponse"]).StatusCode == 400)">
<return-response>
<set-status code="401" reason="Unauthorized" />
</return-response>
</when>
<when condition="@(((IResponse)context.Variables["thProxyCookieResponse"]).StatusCode != 200)">
<return-response>
<set-status code="500" reason="Internal error" />
</return-response>
</when>
</choose>

Conclusion

The OAuth Proxy is part of your API gateway. It enables your SPAs to use the correct browser security and also make direct calls to API URLs. The OAuth Proxy plugin deals with the cookie complexity so that you do not need to implement it in your API code.

Join our Newsletter

Get the latest on identity management, API Security and authentication straight to your inbox.

Start Free Trial

Try the Curity Identity Server for Free. Get up and running in 10 minutes.

Start Free Trial