APIs protected with
self contained access token
(JWT) using
WSO2 API Manager and
WSO2 Identity Server
Index
1. Introduction
2. Configure IS to issue JWT self contained token
3. Configure service provider within the WSO2 Identity Server
4. Configure Identity Provider within WSO2 API Manager
5. Create backend mock service
6. Create an API on WSO2 API Publisher
7. Subscribe to the API on WSO2 API Store and tokens generation
8. Getting access to the API using JWT token
9. Summary of all interactions
10. Conclusion
4. Configure Identity Provider within WSO2 API Manager
5. Create backend mock service
6. Create an API on WSO2 API Publisher
1. Introduction
On this architecture one application needs to get access to a set of APIs, but to do so it needs an access token generated in another system. The token is self contained and because of that the API Manager does not need to validate the token connecting to the system who generated that token. For this PoC I have used SOAP UI as the Client and the Back end. This solution is the continuation of the blog: https://integration-wso2.blogspot.com/2019/11/apim-is-configuring-wso2-identity.htmlIt uses WSO2 Identity Server with the Key Manager and WSO2 APIManager.
This is what I am going to achieve:
2. Configure IS to issue JWT self contained token
File: <IS_HOME>/repository/conf/identity/identity.xmlSet the <Enabled> element (found under the <OAuth>,<AuthorizationContextTokenGeneration> elements) to true.
By default, the user claims are retrieved as an array. To retrieve the claims as a string instead of an array, add the following property under the
<AuthorizationContextTokenGeneration> tag: <UseMultiValueSeparator>false</UseMultiValueSeparator>
Add the following property under <OAUTH> section to use the JWT Token Builder instead of the default Token Builder:
<IdentityOAuthTokenGenerator>org.wso2.carbon.identity.oauth2.token.JWTTokenIssuer</IdentityOAuthTokenGenerator>
The “audiences” parameter can be configured so that the token includes information about the intended audiences who can use the generated token for authenticating the user:
<IDTokenIssuerID> name of the issuer of the token:
3. Configure service provider within the WSO2 Identity Server
This service provider is going to get JWT tokens on behalf of the users. Log in to WSO2IS as admin:admin, that is username and password.https://localhost:9443/carbon
Now, go to Service Providers->Add:
Type name as: jwt-tester and Register.
Configure the service provider, push Edit button:
Select Inbound Authentication Configuration->OAuth OpenID Connect Configuration section and click on Configure button:
Type the option as they are selected on the image. The callback URL has a random value. For this PoC I have typed: http://localhost:8080/playground2/oauth2
Take note of client key (OAuth Client Key) and client secret (OAuth Client Secret) of this service provider. That is shown under OAuth/OpenID Connect configuration section:
4. Configure Identity Provider within WSO2 API Manager
Now, register into WSO2API Manager the IdP that issue the JWT tokens, that is: the Identity Server.Login in https://localhost:9444/carbon
Go into Identity-> Identity Providers and click on Add:
Identity Provider Name: apim-idp, This needs to be the same value as the <IDTokenIssuerID> value you configure at the identity.xml file of the IS. This value will be the issuer ID of the JWT token. Identity Provider Public Certificate, It is the public certificate of the WSO2 Identity Server in a pem file format. It is necessary to authenticate the response comingg from the identity provider (IdP). On this PoC WSO2 Identity Server is the IdP.
To create the public certificated from wso2carbon.jks file from IS:
<IS_HOME>/repository/resources/security/
type:
keytool -export -alias wso2carbon -file wso2.crt -keystore wso2carbon.jks -storepass wso2carbon
That wso2.crt public certificated can be imported with the button Choose File. Alias, this is the value of the clientID (client key) of the service provider configured in the WSO2 Identity Server. This will be checked when verifying the JWT token within the WSO2 API Manager.
Now, we can get access to the API with the JWT token issued by the IS.
5. Create backend mock service
The service that I am going to use is a GET call to this end point:http://api.worldbank.org/countries/AW
As a response I get:
<data contentType="text/xml; charset=UTF-8" contentLength="611">
<![CDATA[?<?xml version="1.0" encoding="utf-8"?>
<wb:countries page="1" pages="1" per_page="50" total="1" xmlns:wb="http://www.worldbank.org">
<wb:country id="ABW">
<wb:iso2Code>AW</wb:iso2Code>
<wb:name>Aruba</wb:name>
<wb:region id="LCN">Latin America & Caribbean </wb:region>
<wb:adminregion id="" />
<wb:incomeLevel id="HIC">High income</wb:incomeLevel>
<wb:lendingType id="LNX">Not classified</wb:lendingType>
<wb:capitalCity>Oranjestad</wb:capitalCity>
<wb:longitude>-70.0167</wb:longitude>
<wb:latitude>12.5167</wb:latitude>
</wb:country>
</wb:countries>]]>
</data>
That endpoint can be tested using a browser or SOAPUI. This call is done with the browser:
And this one with SOAPUI:
To generate the Mock Service, select the url and right buttom and now select Generate REST Mock Service. I rename the mock as WorldBankWiremock:
This image shows the final result:
I am going to use port 8089 for this mock:
To test the mock service I have built another call to the mock: GET http://localhost:8089/countries/AW
Now, run the mock:
and call the mock service:
Now, I am ready to create the api in the API Manager.
6. Create an API on WSO2 API Publisher
I am going to login to the API Manager Publisher portal to create an API with the mock as a back end.https://localhost:9444/publisher
Now, select ADD NEW API:
Select Desing a New REST API:
In the Design API page, type:
Name: WorldBank
Context: wb
Version: 1.0.0
URL Pattern: /countries/{code}
Select GET and Add:
Type Next: Implement >, to go to the Implement page.
Select as an Endpoint Type: HTTP/REST Endpoint
And as an End Point: http://localhost:8089
Type: Next: Manage >
Type Next: Manage > and select Transports: HTTPS, HTTP
Subscription Tiers: Gold
And Save & Publish
This is the final result when the API has been created:
7. Subscribe to the API on WSO2 API Store and tokens generation
After the API has been created now it is time to subscribe it through the API Store.Try to get access to the Store with a new user, like: testuser.
This new user will be stored in the User Store (WSO2UM_DB) and this database is shared with the IS. This user and password will be used when requesting for a JWT to the IdP. To subscribe to the API, it is needed to do it through an Application.
Select the API:
Now, select Default Application and Subscribe, as image shows:
As a final step the keys to get access to the API must be generated, to do it, select the DefaultApplication, select Production Keys and Generate keys button:
The Consumer Key, Consumer Secret and Test Access Token are generated:
Take note of the client id and client secret. Those credentials are going to be used to get the access token with the JWT grant type.
8. Getting access to the API using JWT token
I am going to send a set of request with SOAPUI in order to get access to the API.Do not forget to maintain Mock Server running.
Steps:
1) Get a JWT token from IS.
Grant type is password, what means is that the request will use username and password in base 64 format as credentials. This request contains clientID and Client Secret in base 64 format of the Service Provider that was configured into IS.
Service Provider:
ClientId = gzV_0BRHXC4FuY7XqxjL3MMP7iEa
Client Secret= zkeiTP6JOX4nKiMmxKf0WGazK6Ia
ClientId:Client Secret = gzV_0BRHXC4FuY7XqxjL3MMP7iEa:zkeiTP6JOX4nKiMmxKf0WGazK6Ia
Base 64 format = Z3pWXzBCUkhYQzRGdVk3WHF4akwzTU1QN2lFYTp6a2VpVFA2Sk9YNG5LaU1teEtmMFdHYXpLNklh (Used in the request for JWT token)
Authorization: Base Z3pWXzBCUkhYQzRGdVk3WHF4akwzTU1QN2lFYTp6a2VpVFA2Sk9YNG5LaU1teEtmMFdHYXpLNklh
The image shows this request made in SOAPUI with the access_token as a response, that is the JWT token.
To decode JWT copy it and paste it here: https://jwt.io/
Response with the JWT token as access_token:
{"access_token":"eyJ4NXQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJraWQiOiJOVEF4Wm1NeE5ETXlaRGczTVRVMVpHTTBNekV6T0RKaFpXSTRORE5sWkRVMU9HRmtOakZpTVEiLCJhbGciOiJSUz I1NiJ9.eyJzdWIiOiJ0ZXN0dXNlckBjYXJib24uc3VwZXIiLCJhdWQiOiJnelZfMEJSSFhDNEZ1WTdYcXhqTDNNTVA3aUVhIiwiYXpwIjoiZ3pWXzBCUkhYQzRGdVk3WHF4akwzTU1QN2lFYSIsInNjb3BlIjoiZGVmYXVsdCIsImlzcyI6ImFwaW0taWRwIiwiZXhw IjoxNTc1MzczODM4LCJpYXQiOjE1NzUzNzAyMzgsImp0aSI6ImEzYzY0OThmLWRiNGUtNGJhMy05MzA4LTYxYWI3YTQ4MDJhNiJ9.UnoUe-S3CymxXiz2gbuPznU9XisJ8k1bGQeMU36L_YZ8YX8s6NI571f1iKvC9hREzF0vGZH30EXDktfM_4ja3VVPomSSJnWU1eZ9EIifUtucxBrD96Ya5a9gqbAipfhMzA0Qm9NDvdPjrdeUmbN0QzNI7bWNOHvVJnitganLlBuecN89p0nWef3wPOTORMx1HpKW5EFGbb9h_LD91OgNUg6KwJnb6mQGxDvdSLYIzDXmiv8XMq7aCHX6DRlKfpDFv5wSawcZft1O6heOkagk3MJ_iRxMDY9kDoHYQxyoeg9MxS-V7ofIigql2zfQAAMpi2zJtNCzeJ7N2hA4jQFF4w","refresh_token":"abf2efd0-7c7b-3f2a-9326-9865d3893d03","scope":"default","token_type":"Bearer","expires_in":3600}
As it can be seen, JWT has the ClientId of the SP that was configured into the IS. This value has been stored in the API Manager too to be compared or validated against the one store in the JWT.
2) Call the WSO2 API Manager with the JWT grant type, from the previous response, to get an access token. For this request use clientID and clientSecret in base 64 format of the Application used to subscribe to the API.
grant_type: urn:ietf:params:oauth:grant-type:jwt-bearer
assertion: <JWT from previous request>
Consumer Key = tIIquZ2gUwywsT5mnU56ANqpftoa
Consumer Secret= dp5PqY6gLfQMEP1UOS1MRmNeX5Qa
Consumer Key:Consumer Secret = tIIquZ2gUwywsT5mnU56ANqpftoa:dp5PqY6gLfQMEP1UOS1MRmNeX5Qa
Base 64 format = dElJcXVaMmdVd3l3c1Q1bW5VNTZBTnFwZnRvYTpkcDVQcVk2Z0xmUU1FUDFVT1MxTVJtTmVYNVFh
Authorization: Base dElJcXVaMmdVd3l3c1Q1bW5VNTZBTnFwZnRvYTpkcDVQcVk2Z0xmUU1FUDFVT1MxTVJtTmVYNVFh
The image shows this request made in SOAPUI with the access_token as a response, to get access to the API.
Response with the access_token:
{"access_token":"3c874bef-9430-3dd7-84bb-a2c95b684868",
"refresh_token":"4e3cead2-31a4-3cfb-9544-c608bf3c3e8a",
"scope":"default",
"token_type":"Bearer",
"expires_in":3600}
3) Use the access token to consume the API:
This is the response of the API Gateway:
<data contentType="text/xml; charset=UTF-8" contentLength="611"><![CDATA[?<?xml version="1.0" encoding="utf-8"?>
<wb:countries page="1" pages="1" per_page="50" total="1" xmlns:wb="http://www.worldbank.org">
<wb:country id="ABW">
<wb:iso2Code>AW</wb:iso2Code>
<wb:name>Aruba</wb:name>
<wb:region id="LCN">Latin America & Caribbean </wb:region>
<wb:adminregion id="" />
<wb:incomeLevel id="HIC">High income</wb:incomeLevel>
<wb:lendingType id="LNX">Not classified</wb:lendingType>
<wb:capitalCity>Oranjestad</wb:capitalCity>
<wb:longitude>-70.0167</wb:longitude>
<wb:latitude>12.5167</wb:latitude>
</wb:country>
</wb:countries>]]></data>
9. Summary of all interactions
As a brief description, I have written this interaction diagram to understand better the requests/responses between main components.10. Conclusion
On this PoC I have used the Key Manager of the Identity server, but can be replicated with other 3rd party Key Manager. The same exercise can be done with WSO2 Micro Gateways where this component is able by itself, without connecting to external components like the Key Manager, to validate the token.Download config files




































No comments:
Post a Comment