Securing APIs using OpenID Connect in API Gateway 10.3

Author: Ramesh Ganesan
Supported Versions: 10.3 and above

For securing APIs using OpenID Connect in API Gateway for versions 10.2 and below please refer https://tech.forums.softwareag.com/t/securing-apis-using-openid-connect-in-api-gateway/236951

webMethods API Gateway tutorial

Overview of the tutorial

API Gateway offers several ways to secure your APIs from unauthorized access. One of them is using the OpenID Connect protocol. OpenID Connect adds an Identity layer on top of the OAuth2 protocol, thus it introduces a new type of token called ID Tokens. 

This tutorial will discuss the following topics in detail.

  • When to use OpenID Connect
  • Configurations required in API Gateway
  • ID Token flow, that is exclusive to OpenID Connect
  • Access Token flow, which is similar to OAuth2
  • Detailed walkthrough on how to use these feature

Required knowledge

A basic understanding of OAuth2 protocol is recommended. For securing APIs using OAuth2 in API Gateway please refer Securing APIs using OAuth 2 in API Gateway

Why?

OpenID Connect protocol clearly separates the Identification and Authorization responsibilities. When using OpenID Connect's ID Tokens, the external authorization server just owns the responsibility of Identification to validate if the request comes from a valid user or not. Another system (in this case API Gateway) takes the responsibility of the Authorization part  - which APIs can be accessed for this ID token. This allows the API Gateway user, to define access permissions in only one place i.e in the API Gateway. These permissions can be modified in the API Gateway as and when needed without making any further updates in the Authorization server.

Prerequisite steps

The following prerequisites are expected to be completed.

  • An external Authorization server that supports OpenID Connect protocol is available
  • API Gateway 10.3 or above is installed (for on-premise setup)
  • Install the attached package WmEmployeeManagementSample.zip in Integration Server

Details

Configurations required in API Gateway

In this section, we will see the configurations required in API Gateway to set up an OpenID connect use case 

  • External auth server
  • API
  • OAuth Scope (API - scope mapping)
  • Application 

Step 1: Configure external OAuth provider

If not already available, you need to create a provider config for your external authorization server. In API Gateway, provider configuration is already pre-configured for OKTA and PingFederate authorization servers. For other authorization servers, you need to create the provider configuration. Go to Administration > Security tab > Providers > + Add Provider. Just provide a name (e.g. KeycloakProvider) for the provider and save with default options.

Step 2: Configure the external authorization server

Configure the external authorization server. Go to Administration > Security tab > JWT/OAuth/OpenID > External Authorization Servers > + Add authorization server

If you have the Discovery URL for your authorization server, use that and most of these details will be automatically populated. Alternatively, you can fill the details manually. Values you see in the below images are representative, please replace with actual details of your authorization server. For this tutorial, it is enough to populate the fields shown in below images

Auth server Basic details

Auth server Introspection details

Auth server DCR details

Auth server Scope details

Step 3: Configure JWT settings

Step 4: Create API

As mentioned in the Prerequisites section, ensure you have deployed the native service WmEmployeeManagementSample in Integration Server. Create a new API called "emp" in API Gateway using EmployeeManagementSwagger.json. Activate the newly created "emp" API. Add the OpenID Connect security policy for this API. This is done by adding the "Identify & Authorize Application" policy to this API

Step 5: Create scope mapping

OAuth scopes are used to assign permissions for APIs. You can think of scopes as named permissions. (e.g. "Sales", "Admin", "RestrictedAccess" ). Before assigning the scope to an API, that scope should be available under the External Auth Server configuration in API Gateway. Go to Administration > Security > JWT / OAuth / OpenID > External Authorization servers > click your Auth server > Scopes > add scope if they are not available yet.

Now map this scope to the "emp" API created in the previous step. Go to OAuth / OpenID Scopes (from the home page dropdown) >  + Map Scope > Search for the scope and choose from drop-down

In the next page, select the API

Step 6: Create an Application

The application we create here serves two purposes,

  1. It maps the API's to which we want to grant permissions
  2. It also creates a new OpenID client in the external auth server (by creating a strategy).      If you already have an OpenID client in your auth server, this application need not have any strategies.

Go to Applications > + Create Application

Map the API's

Create a strategy which will create a new OpenID client in your external auth server (If you already have an OpenID client in your auth server, you can skip this step)

Add the strategy and then Save the application.

Now open the application and note these details.

  • API Key of this application
  • Client Id & Client Secret of the newly created client. (If you are using an already existing client you can get the client id & client secret from external auth server itself)

ID Token flow

Now have set up all the configurations required for OpenID based authentication. To access the API we will now do the following.

  • Get an ID token from the external auth server (ID Token that defines the Identifiation is provided by external auth server)
  • Pass this ID token to the API Gateway and get an Access Token from API Gateway (Access Token that defines the access permissions is provided by API Gateway)
  • Access the API using the Access Token received from API Gateway

Step 1: Get ID Token from external auth server

This particular call is made to an external auth server, and the interface may be different for different auth servers. Follow the steps as prescribed by your external auth server. Below is a sample illustrated using the Keycloak auth server. Using a REST client make a POST call to the Keycloak external auth server.

POST http://authserver:8080/auth/realms/master/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

Request Body (x-www-form-urlencoded variables):

grant_type : client_credentials
client_id : <client_id>
client_secret : <client_secret>
scope: openid

From the response, note the value of "id_token".

Note: Replace the <client_id> and <client_secret> values with the values we have noted from the Create Application step

Step 2: Exchange ID Token - Get Access Token from API Gateway

Using a REST client make a POST call to the API Gateway :

POST http://apigateway:5555/gateway/security/exchangeIDToken
Content-Type: application/json
x-Gateway-APIKey: <ApiKey>

Request Body (JSON):

{
"gatewayScopes": ["<OAuthScopeName>"],
"idToken": "<IdTokenValue>",
"expiry": 3000
}

apigateway:5555          with the server:port value of your API Gateway instanceNote : Replace following values in the POST request
<ApiKey>                     with the API key value noted in the Create Application section. Sample value : 9aea6149-1985-477c-85ce-b5ffd25a4df9
<OAuthScopeName>  with the OAuthScope name created in Create scope mapping section. Sample value : "AuthServerName:scope1"
<IdTokenValue>           with the "id_token" value noted in the previous step 

From the response, note down the value of "accessToken".

Step 3: Access the API

Using a REST client make a POST call to the API Gateway :

POST http://apigateway:5555/gateway/emp/1.0.0/employee

Content-Type: application/json
Authorization: Bearer <AccessTokenValue>

Request Body (JSON): 
{ "employeeName" : "emp1" }

Replace the <AccessTokenValue> with the value of "accessToken" from the previous step.

A successful response validates the complete ID Token flow:
Identity data was provided by the auth server - ID Token
Access data was provided by the API Gateway - Access Token
Using the Access Token we were able to consume the API.

Access Token flow

Access Token flow is the same as using regular OAuth2 access token. So here we will get the access token directly from the auth server and then access the API. We expect appropriate scope claims in the access token received from the external auth server. So for this client, scopes should have been mapped in the external auth server. 

  • Get an Access token from the external auth server (unlike the ID Token this token will also have the access permissions - scopes)
  • Access the API using the Access Token received from auth server

As you can see, the step where we exchange the ID Token to get an Access Token is not required here.

Note: When using Google as external auth server, you can not use their Access Token. Their Access Tokens are meant to access Google APIs. So when using Google as external auth server, please use ID Token flow.

Step 1: Get Access Token from external auth server

This particular call is made to an external auth server, and the interface may be different for different auth servers. Follow the steps as prescribed by your external auth server. Below is a sample illustrated using the Keycloak auth server. Using a REST client make a POST call to the Keycloak external auth server.

POST http://authserver:8080/auth/realms/master/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

Request Body (x-www-form-urlencoded variables):

grant_type : client_credentials
client_id : <client_id>
client_secret : <client_secret>
scope : <phone>

Note: Replace the <client_id> and <client_secret> values with the values we have noted from the Create Application step.
Replace the value <phone> with the actual scope value.
From the response, note the value of "access_token".

Step 2: Access the API

Using a REST client make a POST call to the API Gateway.

POST http://apigateway:5555/gateway/emp/1.0.0/employee

Content-Type: application/json
Authorization: Bearer <AccessTokenValue>

Request Body (JSON): 
{ "employeeName" : "emp1" }

Replace the <AccessTokenValue> with the value of "access_token" from the previous step.

A successful response validates the Access Token flow: the Identity & Access data was provided by the auth server using this token we were able to consume the API.

Troubleshooting

Context Issue Solution

Exchange ID Token 

(Get Access Token from API Gateway)

Error message : JWT configuration missing Refer section 1.3
Exchange ID Token
(Get Access Token from API Gateway)
Error message : At lease one scope should be included Ensure the API has been mapped to scope (section 1.5)and the Application has been mapped API (section 1.6)
Check section 2.2 if all the values are being supplied correctly
Exchange ID Token
(Get Access Token from API Gateway)
Error message : Unable to uniquely identify an application Ensure to pass the API key of the application (section 2.2) to uniquely identify the application

References

Downloadable artifacts

WmEmployeeManagementSample.zip (58.5 KB)

EmployeeManagementSwagger.json (10 KB)