An Introspection Tale involving IBM API Connect and an external Authorization Server

Manglu Balasubramanian
5 min readAug 21, 2020

Manglu Balasubramanian, Senior IT Architect, IBM
Tapan Verma,
Senior IT Architect, IBM

Introduction

OAuth2 Specification clearly articulates how a resource server (such as IBM API Connect, Apigee, Kong, etc ) can work with Authorization Servers (e.g ForgeRock, Ping, Okta, etc) to perform delegated authorizations. A typical interaction between the Client, Authorization Server and Resource Server is shown below.

Figure 1: Typical OAuth2 Interaction — Client, Resource Server, and Authorization Server

a) Clients receive the tokens via the “/token” endpoints

b) Clients send the access token and client_id to the Resource Server

c) Resource Server works with the Introspection endpoint on the Authorization Servers to validate the access token.

Numerous solutions have been built over the years using this pattern.

In this article we are looking at a very specific scenario:

  • Client does not send a client_id to the resource server during an API request
  • Access Token is Opaque/reference Token ( This is not uncommon even today as some of the specifications such as Financial API (FAPI) Read-Only API Security Profile states this requirement for an Auth Server: The Authorization Server shall provide opaque non-guessable access tokens with a minimum of 128 bits … as per [RFC6749] section 10.10;)
  • IBM API Connect (hereinafter referred to as APIc) acts as the resource server

What happens in this Scenario?

Surprise!!. Surprise!!!

The API request is rejected with an error message returned to the Client. The request processing fails at the step mentioned X in the Figure below.

Figure 2: client_id not sent by the client makes the flow stop at API Client identification step

Let’s explore in detail what happens in step b.

  • The API Client sends the Access Token to APIc
  • APIc looks at request to see where this request should be routed (Step 1 in Figure 3 )
  • Once APIc has determined where this request should be routed to, it performs CORS check (Step 2 in Figure 3)
  • APIc wants to perform client authentication and it attempts to look at the client_id in the X-IBM-Client-Id header (Step 3 in Figure 3)

The Journey an API Request takes in IBM APIc v2018

Figure 3: IBM APIc v2018 — API request processing flow

As the client has not sent the client_id, APIc terminates the request flow.

Even though the client presents a valid access token, APIc will not proceed with the introspection call (which is performed in Step 5 in Figure 3).

What are the options that we have here then?

Option # 1: Get the Client to send the client-id in the X-IBM-Client-Id HTTP header.

This is feasibly only if the client agrees to send the client_id. You can’t mandate or force the clients to specify this value particularly if the solution is built on specifications that will work with multiple Resource Servers. A classic example is an Open Banking client such as Third Party Provider Apps which will work with the same APIs against a huge variety of API gateways that are used by different Banks.

Option #2: Interception pattern

Figure 4: Intercepting request processing flow to inject client_id

This pattern assumes that a hook (highlighted in Figure 4 as Step c)is made available by the resource server (APIc in this article) to intercept the API request flow. The authorization server generates an Opaque token that consists of two parts (the first part is the client_id, separated from the rest of the content using “:::” as the separator in the Figure above). The interceptor extracts the client_id and sets in the X-IBM-Client-Id HTTP header and this allows APIc to perform API client identification checks. The rest of the flow continues like the typical API request processing flow scenario.

This option requires the Authorization Server to changes its default implementation of generating a completely opaque token which may or may not be feasible.

This option is not supported in APIc v2018 as it does not support the pre-request extension. This option can be implemented in APIc v10 (the latest version) by customizing the pre-flow policies. If you are still using the APIc v5 (the version prior to APIc v2018) then you would use the pre-request extension capability to implement this pattern.

Option #3: Use a Proxy API Layer in front of the actual Business APIs

Figure 5: Option#3 Proxy API Layer

The Business APIs is/are fronted with a Proxy API. The Proxy API is a public API (i.e supports anonymous access and does not require a client_id to be sent by the caller). Once it receives the API request, it makes a call to the Authorization Server’s introspection endpoint. The Auth Server validates the token and if the token is good it returns an introspection response which will include among others the client_id that corresponds to the access token.

This client_id is set to the X-IBM-Client-Id HTTP Header and then the business API is invoked. APIc receives the client_id (for the Business API) and it executes it’s typical request process flow as described in Figure 3.

The approach has its downsides too. It introduces an additional API Layer where we initiate the introspection call. Also, the Business API is not secured with OAuth2 it is secured with a client_id.

Thanks to Shiu-Fun Poon, Chris Norton, and Anuradha Harit for their review comments and suggestions on this article.

Conclusion

OAuth2 has progressed a lot from its initial days when we needed hordes of security geeks to help implement a good, working solution. However, even in 2020, there are still a few things that surprise us on and off when we work with different combinations of Authorization and Resource Servers. Though the options presented in this article are not the only solutions, they represent the typical high-level patterns that form the basis of various solutions

--

--

Manglu Balasubramanian

CDR/Open Banking Solution architect working with one of the large Australian banks. Skilled in general solution architecture and an early adopter of technology.