Integrating With the Broadcom CA Layer7 API Gateway
On this page
This tutorial describes how to integrate the Broadcom CA Layer7 API Gateway with the Curity Identity Server. The Broadcom CA Layer7 API Gateway is a security gateway that proxies HTTP traffic and performs security checks on the data and identity layers.
The Gateway will be configured to use access tokens issued by the Curity Identity Server to protect API access. In this example architecture, the Curity Identity Server sits behind the Gateway as well. But, that is not a requirement, and it does not affect the implementation of the API protection.
This integration uses the concept of Phantom Tokens. The introspect endpoint will return a JWT version of the incoming access token referred to as a Phantom Token. To configure the introspect endpoint to return Phantom Tokens see Introspection and Phantom Tokens.
The API is protected by having the Gateway check for an access token in the incoming request’s Authorization header. For the Gateway to validate the incoming access token, it must do two things:
- If the token hasn't been seen before, the Gateway must ping the OAuth server (Introspection).
- The Gateway must cache the response from the OAuth server in the Gateway cache (but not in the Gateway DB, which is considerably more resource-consuming).
- The Web-Backend makes a request towards the OAuth-protected API.
- The Gateway first tries to find the Access Token in the cache. If there's a miss, it calls the OAuth server’s Introspect endpoint.
- The OAuth server responds with token information and an Access Token in JSON Web Token format (JWT).
- The Gateway caches the response for the lifetime of the token.
- The Gateway forwards the request to the OAuth-protected service (the API), passing the JWT instead of the original access token in the Authorization header back to the protected service.
Setting up the Gateway to Validate Access Tokens
To validate an access token, a new policy fragment must be created. Its task is to perform the operations described in the previous section. The benefit of the policy fragment is that it can be included in any service published by the gateway.
The steps described to create this policy are made using the Broadcom CA Layer7 API Gateway version 9.1. The same tasks are possible with any version 8.x of the gateway, with minor differences on where to find the assertions, and the look and feel.
1. Create a New Policy
Use the Create Policy option in the policies window, and select Included Fragment as policy type. Name it
Require OAuth Token.
2. Define Cluster Properties
To make the policy portable between environments, it's recommended to use cluster properties when applicable. There are three variables and one credential that need to be defined in this policy.
From the Tasks menu, open Global Settings -> Manage Cluster-Wide Properties and add:
oauth_server_host= the hostname of the Curity Identity Server (e.g.,
oauth_server_introspection_path= the path of the introspection endpoint as configured in the Curity Identity Server (eg: /oauth/v2/oauth-introspect)
From the Task menu, open Certificates, Keys and Secrets -> Manage Stored Passwords and add:
oauth_introspect_clientsecret = the client secret
3. Add the Policy Content
To add the policy content, open the newly created Require OAuth Token policy and copy the XML from the Appendix A: – Require OAuth Token fragment in this document and paste it into the window. This should create a structure that looks like the following:
After saving and activating, the policy fragment is ready to use.
If self-signed certificates or an internal CA is used for issuing the certificates for the Curity Identity Server, it must be imported into the Gateway’s trust store before the policy can be used.
4. Create Encapsulated Assertion
This step is optional but makes the enforcement easier to use. To create an encapsulated assertion, right-click on the Require OAuth Token policy in the service window and select Create Encapsulated Assertion. Enter the
oauth.* variables (
oauth.scope) as output variables and place the assertion in the Access Control section.
Enforcing Access Token in API Policies
Now that the Require OAuth Token policy is configured, it can be included in all services that it should protect.
The included fragment (or the encapsulated assertion) should be placed at the beginning of the service policy after the Require SSL or TLS transport assertion.
The Require OAuth Token fragment will export the following variables:
This assumes that The Curity Identity Server is configured to respond with a JWT from the introspection endpoint. See Introspection and Phantom Tokens for more details about the introspection endpoint and how to include a JWT.
Passing the JWT to Backend APIs
After a successful lookup of the Access Token, the service will eventually route to a backend API. At this point, it should pass on the internal JWT it received from the introspect endpoint. This is done by adding the
oauth.jwt to the Authorization header of the routed request.
Introspect With application/jwt as Accept Header
The Curity Identity Server can also respond to requests in the introspection endpoint with the
Accept: application/jwt header. When introspecting a valid access token, The Curity Identity Server responds with 200 OK and the JWT in the response body. An expired or invalid access token causes The Curity Identity Server to respond with 204 No Content. This means that the gateway doesn’t need to parse the JSON (as when using normal introspection), making the proxying even faster. Appendix B: – Require OAuth Token, introspect with application/jwt contains a policy fragment that uses
application/jwt. Also, the Curity Identity Server’s status codes on the introspection request are considered, and the Gateway responds accordingly. This fragment only exports the variable
oauth.jwt, which can replace the access token in the Authorization header forwarded to the API.
For the Broadcom CA Layer 7 API Gateway to be able to parse the response from Curity (which in this case includes the header
Content-type: application/jwt), you will need to add another cluster-wide variable with key contentType.otherTextualTypes and value