OpenAM integration with WSO2 APIM 3.2.0 as 3rd Party Key Manager

Dushan Abeyruwan
6 min readNov 28, 2020

One of the newest features of APIM 3.2.0 and beyond is the abstract interfaces that allow you to connect with any 3rd party Key managers. The flow goes as when a Key Manager is added via the Admin Portal, it is persisted in the APIM DB as well as an event is triggered to the Traffic Manager. As a result, the Gateway will receive the event and register the Key Manager in the Gateway. Therefore, the Key Manager will be registered as another Key Manager and it will be available for the APIs that are created within the tenant.

As of now, WSO2 offers standard config APIs to connect 3rd Party Key Managers such as Auth0, Keylock, Okta, PingIdentity. In this blog, I will try to walk you through how to integrate OpenAM, personally, I have seen there were some requests asking how this can be done. The scenario I’m explaining has been tested with OpenAM 13+ (applicable for OpenAM 13.0 or 13.5).

First, what you should do, understanding the type of APIs OpenAM offers, I had to walk through some public resources such as [1][2] to understand sort APIs offers whether it has default OpenID client registration operations available to get help my self for custom implementation, but it turns out to be the way OpenAM RestAPIs working bit different to other KeyManagers.

e.g 2.1.3.1.5. OAuth 2.0 Client Administration Endpoint does not really provide the exact CURD operations required.

Anyway, let's get into the setup process (this will little bit lengthy so hang on..)

  1. Download the OpenAM from [3]

2. Setup admin user, openAM 13 supports Tomcat 8, JDK 8 (you need to setup admin username, a password which requires when configuring the 3rd party Key Manager)

4. Download WSO2 APIM

5. You need to setup APIM to connect with MSSQL (will explain why it requires, and why this won’t be working with H2 DB)

6. Download the 3rd Party KM connector written from [4]

7. Compile the code and copy to the APIM_HOME/repository/components/dropins

8. Login to the admin portal of the APIM then navigate to KeyManagers-> then click add New Key Manager add information listed below then save it

8.1 You may paste the following (keep special attention to the context of frrest)

9 . Run the following SQL to create a table under AM_DB, this is required for OAuth 2.0 client information persistence, which was required since OpenAM does not offer a GET API to retrieve client applications created.

CREATE TABLE IF NOT EXISTS OPENAM_CLIENT (CLIENT_ID VARCHAR (100),PAYLOAD VARCHAR (2000),PRIMARY KEY (CLIENT_ID))ENGINE INNODB;

10. Then navigate to APIM_HOME/bin you may start the APIM. Then, log in to the publisher you may publish a sample API. In this case, I would use default API sample PizzaShackAPI

11. Login to devportal navigate to applications, then create an application

12. Click Generate Keys Button

13. To verify what has happened at the OpenAM side, login to openAM, navigate to default realm

14. Navigate to Agents, under OAuth 2.0 /OpenID Connect Client, you will notice the application created from APIM is generated at the Autherziation Server end.

15. Subscribe the API to the application created from APIM

16. Generate Access token

17. You may use the try it a tool to test the API invocation or use the curl command. It should work! (if not you may drill down the code to understand what has happened during the token validation) https://github.com/dushansachinda/openam-demo/blob/main/openam.key.manager/src/main/java/org/wso2/openam/client/OpenAMOAuthClient.java#L348

18. Additionally this use case has tested to validate the scope with 3rd party Authorization server too, to check that you do the following steps

19. Add a scope to the application you have created a login to the openAM. In this case, I have added “read” scope

20. Login to the API provides scope restriction to the API resources. For this demo, I have provided “read” sope the menu

21.1 Generate token without scopes you will notice the following error;

curl -v -X GET "http://localhost:8280/pizzashack/1.0.0/menu" -H  "accept: application/json" -H  "Authorization: Bearer 65fff596-6e2e-4a4f-9153-f48e9ab7bd27"
Note: Unnecessary use of -X or --request, GET is already inferred.
* Trying ::1...
* TCP_NODELAY set
* Connection failed
* connect to ::1 port 8280 failed: Connection refused
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8280 (#0)
> GET /pizzashack/1.0.0/menu HTTP/1.1
> Host: localhost:8280
> User-Agent: curl/7.64.1
> accept: application/json
> Authorization: Bearer 65fff596-6e2e-4a4f-9153-f48e9ab7bd27
>
< HTTP/1.1 403 Forbidden
< Access-Control-Expose-Headers:
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET
< Access-Control-Allow-Headers: authorization,Access-Control-Allow-Origin,Content-Type,SOAPAction,apikey,testKey,Authorization
< accept: application/json
< Content-Type: application/json; charset=UTF-8
< Date: Sat, 28 Nov 2020 06:56:32 GMT
< Transfer-Encoding: chunked
<
* Connection #0 to host localhost left intact
{"fault":{"code":900910,"message":"The access token does not allow you to access the requested resource","description":"Access failure for API: /pizzashack/1.0.0, version: 1.0.0 status: (900910) - The access token does not allow you to access the requested resource"}}* Closing connection 0

22. Login to API devportal generate token with scope;

23. Invoke the token

curl -v -X GET "http://localhost:8280/pizzashack/1.0.0/menu" -H  "accept: application/json" -H  "Authorization: Bearer 2d10a73f-dafd-4b98-b556-1124ef5f3864"
127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8280 (#0)
> GET /pizzashack/1.0.0/menu HTTP/1.1
> Host: localhost:8280
> User-Agent: curl/7.64.1
> accept: application/json
> Authorization: Bearer 2d10a73f-dafd-4b98-b556-1124ef5f3864
>
< HTTP/1.1 200
< Access-Control-Expose-Headers:
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET
< Access-Control-Allow-Headers: authorization,Access-Control-Allow-Origin,Content-Type,SOAPAction,apikey,testKey,Authorization
< Content-Type: application/json
< Date: Sat, 28 Nov 2020 07:04:48 GMT
< Transfer-Encoding: chunked
<
* Connection #0 to host localhost left intact
[{"name":"BBQ Chicken Bacon","description":"Grilled white chicken, h.....,"description":"Rich and creamy blend of spinach and garlic Parmesan with Alfredo sauce","price":"21.99","icon":"/images/5.png"},{"name":"Tuscan Six Cheese","description":"Six cheese blend of mozzarella, Parmesan, Romano, Asiago and Fontina","price":"16.99","icon":"/images/4.png"}]* Closing connection 0

if you enable debug logs for OpenAM component you should be able to see what has happened internally

e.g

[2020-11-27 23:04:47,887] DEBUG - OpenAMOAuthClient Getting access token metadata from authorization server. Access token 2d10a73f-dafd-4b98-b556-1124ef5f3864
[2020-11-27 23:04:48,028] INFO - OpenAMOAuthClient 200
[2020-11-27 23:04:48,030] DEBUG - OpenAMOAuthClient HTTP Response code : 200
[2020-11-27 23:04:48,032] INFO - OpenAMOAuthClient parsedObject{"redirectURI":[],"parent":[],"clientID":["openAMDemoApplication_PRODUCTION"],"auditTrackingId":["c65ec0f7-b011-4d4d-a5ca-00b8da724ffc"],"_rev":"1606547088023","tokenName":["access_token"],"userName":["openAMDemoApplication_PRODUCTION"],"nonce":[],"expireTime":["1606550672471"],"grant_type":["client_credentials"],"scope":["read","am_application_scope"],"realm":["\/"],"_id":"id","id":["2d10a73f-dafd-4b98-b556-1124ef5f3864"],"tokenType":["Bearer"]}
[2020-11-27 23:04:48,097] INFO - DataBridge user admin connected

This is a bit long, but yes, there is an obvious learning part here, the token validation process works as follows;

under the hood WSO2 APIM navigates through the registered key managers and identify the token pattern and handover to the relevant key manager to validate the token refer following

https://github.com/wso2/carbon-apimgt/blob/master/components/apimgt/org.wso2.carbon.apimgt.keymgt/src/main/java/org/wso2/carbon/apimgt/keymgt/handlers/DefaultKeyValidationHandler.java#L241

Thanks for reading, post me any question

[1] https://backstage.forgerock.com/knowledge/kb/book/b66926033

[2] https://backstage.forgerock.com/docs/openam/13/dev-guide/index.html#rest-api-oauth2-client-admin-endpoint

[3] https://backstage.forgerock.com/downloads/browse/am/all/productId:openam/minorVersion:13/version:13.0.0/releaseType:full

[4] https://github.com/dushansachinda/openam-demo

--

--