On this page
The IBM API Connect Gateway is a powerful API Gateway that is used to protect APIs and Microservices. It is possible to extend the capabilities of the gateway using many of the provided policies. Using a couple of these policies in conjunction with a Lambda Authorizer function can implement the Phantom Token Pattern in a secure way.
This article describes how to configure IBM API Connect to use a Lambda Authorizer that is exposed using a Function URL. The Lambda Authorizer introspects an opaque access token and returns a JWT that is used to access the upstream API. The API Gateway adds the JWT to the Authorization header and forwards the request to the upstream API.
The details of the OAuth Introspection and Phantom Tokens is a useful read before diving fully into how to set up this integration.
Lambda Authorizer for Other API Gateways
Although this article describes how to leverage a Lambda Authorizer with the IBM API Connect Gateway, it is possible to use the same approach and the same Lambda Authorizer with other API Gateways that supports the use of Lambda Authorizers.
Prerequisites
- An installation of the Curity Identity Server
- An IBM API Connect Gateway
- Basic understanding of Lambda functions
If you do not have an installation of the Curity Identity Server, you can follow the Install using Docker tutorial and then follow the First Configuration tutorial to make OAuth endpoints available.
Configure the Curity Identity Server
The Curity Identity Server needs to be set up to handle introspection. This is the case by default but review the configuration of the system in use before continuing and also make sure you have a Client configured for introspection.
This article assumes that the Curity Identity Server is set up to handle the application/jwt
approach of introspection as outlined in the OAuth Introspection and Phantom Tokens article.
Build, Deploy and Configure the Lambda Authorizer Function
The code for the Phantom Token Lambda Authorizer function is available in the GitHub repository. Full details on building, deploying and configuring the Lambda Authorizer function itself is outlined in the README.
Configure the IBM API Connect Gateway
The steps below outlines the flow that is implemented in the IBM API Connect Gateway. These steps assume that you already have an API configured that the gateway is proxying.
- Extract the opaque access token from the Authorization header of the incoming request and store it in a variable
- Build the payload for the Lambda Authorizer function and add the access token
- Call the Lambda Authorizer function and pass on the payload
- Parse the response from the Lambda Authorizer function and store the JWT in a variable
- Inject the JWT into the Authorization header of the request to the upstream API
An example policy snippet that implements the above steps is available in Appendix A at the end of this article. The example is a YAML configuration that can be used in the IBM API Connect Gateway.
Test Using OAuth Tools
- In OAuth Tools, create a flow to obtain an Access Token.
- Create a Call External API flow. Enter the URL of the IBM API Connect Gateway exposed API. Configure the method according to what’s possible with the API. Select the token retrieved in the previous step from the drop-down list and click Send.
Access Token Expiry
When you use the phantom token plugin, access token expiry responses can originate either from upstream APIs or the plugin itself. In either case, clients receive an HTTP 401
response and can deal with that condition resiliently. Typically, the client runs a token refresh operation and retries the API request with a new access token. To ensure the correct expiry response, the plugin returns statusCode: 401
and the gateway configuration captures that and returns the same status code.
Resources
Useful resources that cover the topics of this article.
- An article on OAuth Introspection and Phantom Tokens
- IBM API Connect
Appendix A - IBM API Connect Example Configuration
assembly:execute:- set-variable:version: 2.0.0title: Extract Access Tokenactions:- set: access_tokenvalue: >-substring-after(context.get('request.headers.authorization'),'Bearer ')type: any- set-variable:version: 2.0.0title: Build Lambda Request Payloadactions:- set: lambda_payloadvalue: >-json-stringify({type: 'TOKEN',authorizationToken: concat('Bearer', $(access_token))})type: any- set-variable:version: 2.0.0title: Set Payload for Lambda (via message.body)actions:- set: message.bodyvalue: $(lambda_payload)type: any- invoke:version: 2.3.0title: Call Lambda (Phantom Token)backend-type: jsonheader-control:type: blocklistvalues: []parameter-control:type: allowlistvalues: []http-version: HTTP/1.1timeout: 60verb: POSTchunked-uploads: truepersistent-connection: truecache-response: no-cachecache-ttl: 900websocket-upgrade: falsetarget-url: [your-lambda-function-url]headers:- name: Content-Typevalue: application/jsonoutput: lambdaResponse- parse:version: 2.2.0title: Parse Lambda Responseinput: lambdaResponseparse-mode: jsonoutput: lambdaJsonuse-content-type: trueparse-settings-reference:parse-settings:document_type: json- switch:version: 2.1.0title: switchcase:- condition: lambdaResponse.status.code = 401execute:- throw:version: 2.1.0title: throwerror-status-code: '401'name: Introspection errorerror-status-reason: Unauthorizedmessage: Invalid token- set-variable:version: 2.0.0title: Inject JWT in upstream requestactions:- set: message.headers.Authorizationvalue: Bearer $(lambdaJson.body.access_token)type: string- invoke:title: invokeversion: 2.0.0verb: keeptarget-url: $(target-url)follow-redirects: falsetimeout: 60parameter-control:type: allowlistvalues: []header-control:type: blocklistvalues: []inject-proxy-headers: truechunked-uploads: truepersistent-connection: true
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