Skip to main content

How to protect your APIs with self contained access token (JWT) using WSO2 API Manager and WSO2 Identity Server


In a typical enterprise information system, there is a high chance that people will use different types of systems built by different vendors to implement certain types of functionalities. The APIs might be hosted in an API Manager developed by vendor A and the user management can be implemented using a different vendor (vendor B). In this type of a situation, one system will not be able to directly contact the other system but they want to use both systems in tandem.

Self-contained access tokens are used in these types of situations where applications can get the token from one system and use that in another system to access protected resources. In this scenario, the second system does not need to make a contact to the first system over the network to validate the user information since the token is self-contained and it has relevant details about the user. This will improve the token processing time significantly since it completely removes the network interaction.

The below figure showcases a scenario where the client application receives a JWT (self-contained token) from the WSO2 Identity Server and then use that token to consume an API protected by WSO2 API Manager.




To implement the above use case, first, we need to download WSO2 Identity Server and the WSO2 API Manager from the WSO2 web site.



Configure WSO2 Identity Server to issue JWT self-contained tokens

Once you download and extract the WSO2 Identity Server, you need to configure it to generate JWT tokens. Follow the steps mentioned below.

  • Open the <IS_HOME>/repository/conf/identity/identity.xml file and set the <Enabled> element (found under the <OAuth>,<AuthorizationContextTokenGeneration> elements) to true as shown in the code block below.


<AuthorizationContextTokenGeneration>

<Enabled>true</Enabled> <TokenGeneratorImplClass>org.wso2.carbon.identity.oauth2.authcontext.JWTTokenGenerator</TokenGeneratorImplClass> <ClaimsRetrieverImplClass>org.wso2.carbon.identity.oauth2.authcontext.DefaultClaimsRetriever</ClaimsRetrieverImplClass>

<ConsumerDialectURI>http://wso2.org/claims</ConsumerDialectURI>

<SignatureAlgorithm>SHA256withRSA</SignatureAlgorithm>

<AuthorizationContextTTL>15</AuthorizationContextTTL>

</AuthorizationContextTokenGeneration>


Note: 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 in the identity.xml file.
<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>

  • Configure the “audiences” parameter as mentioned below so that the token includes information about the intended audiences who can use the generated token for authenticating the user.


<EnableAudiences>true</EnableAudiences>

<!-- Comment out to add Audience values to the JWT token (id_token) -->

<Audiences> <Audience>${carbon.protocol}://${carbon.host}:${carbon.management.port}/oauth2/token</Audience>

</Audiences>


  • Configure a meaningful value to the <IDTokenIssuerID> parameter in the identity.xml file

<IDTokenIssuerID>apim-idp</IDTokenIssuerID>
Now you can start the WSO2 Identity Server by executing the following command within the IS_HOME/bin directory.

$ sh wso2server.sh

Configure WSO2 API Manager to work with JWT token issued by WSO2 Identity Server

  • Since we are running both the server on the same machine, we need to change the port offset value to 1 in the carbon.xml file located in APIM_HOME/repository/conf directory
<Offset>1</Offset>
Now you can start the WSO2 API Manager by executing the following command within the APIM_HOME/bin directory.

$ sh wso2server.sh



Configure service provider within the WSO2 Identity Server

Now we need to configure a service provider who is going to get JWT tokens on behalf of the users. You can log in to the WSO2 IS management console under following URL with default admin:admin username/password pair.


Go into Service Providers->Add and give a name for the service provider as depicted below and click on register.


Then configure the service provider by clicking on the edit button of the service provider you just created. Select Inbound Authentication Configuration->OAuth OpenID Connect Configuration section and click on “configure” button. Fill the callback URL with some dummy value as depicted below and click update.


That’s all you have to do in the WSO2 Identity Server. You need to take a note of client key and client secret of this service provider which is now showing under OAuth/OpenID Connect configuration section as depicted below.



Configure Identity Provider within WSO2 API Manager

Now you need to log in to the WSO2 API Manager console and configure the identity provider which is issuing the JWT tokens. In this case, it is WSO2 Identity Server. You can log in with default username/password pair using the below URL.


Go into Identity-> Identity Providers and click on “Add”. You will get a window similar to below figure. You need to configure the identity provider with the below mentioned values.


When you are configuring this section, you need to give values which are compatible with the identity provider which is WSO2 Identity Server.
  • Identity Provider Name - This needs to be the same value as the <IDTokenIssuerID> value you configure at the identity.xml file since this value will be the issuer ID of the JWT token. Here the value is given as “apim-idp” to match the above mentioned parameter. 
  • Identity Provider Public Certificate - Here you need to upload the public certificate of the WSO2 Identity Server in a pem file format. The Identity Provider Public Certificate is the public certificate belonging to the identity provider. Uploading this is necessary to authenticate the response from the identity provider. This can be any certificate. Since we are using WSO2 Identity Server as the IDP we can generate the certificate using the below mentioned commands.

To create the identity provider certificate from the wso2carbon.jks file, follow the steps below.



1. Open your Command Line interface, go to the <IS_HOME>/repository/resources/security/directory. Run the following command.

keytool -export -alias wso2carbon -file wso2.crt -keystore wso2carbon.jks -storepass wso2carbon

2. Once you run this command, the wso2.crt file is generated and can be found in the <IS_HOME>/repository/resources/security/ directory.

Click Choose File and navigate to this location in order to select and upload this file.

  • Alias - You need to give the clientID (client key) of the service provider which you have configured in the WSO2 Identity Server here. This will be checked when verifying the JWT token within the WSO2 API Manager. 

Now you are all set to access the API using a JWT token which is issued by WSO2 Identity Server.


Access the API using the JWT token issues by WSO2 Identity Server

Now let’s log in to the API manager publisher portal and create a sample API which connects to a simple hello world service which is running in the local machine.


The created API looks similar to below.


Once you create the API, you can log into the API manager store portal and sign up as a new user (testuser) with the self-sign up option.



This username and password will be used to get the JWT token for this user.

After that, you need to log in to the store portal and subscribe to the API using the default application.



Then you need to get the client id and the client secret of the default application.



Now you are all set.

  • You need to first get a JWT token from the WSO2 identity server by using the token endpoint with the password grant type. You can use the below mentioned curl command to get a JWT token
curl -u <clientID>:<clientSecret> -k -d "grant_type=password&username=testuser&password=testuser" -H "Content-Type:application/x-www-form-urlencoded" https://localhost:9443/oauth2/token


Here you need to replace the <clientID>:<clientSecret> with the relevant values of the service provider which is configured at WSO2 Identity Server. This will return the JWT token with a response similar to below.
{"access_token":"eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJqb2huZG9lQGNhcmJvbi5zdXBlciIsImF1ZCI6WyJpcGtXTnlGMWZYdTRNYlNoRTZ2YUpHTkdrRElhIl0sImF6cCI6Imlwa1dOeUYxZlh1NE1iU2hFNnZhSkdOR2tESWEiLCJpc3MiOiJhcGltLWlkcCIsImV4cCI6MTUyODM2ODEwMCwiaWF0IjoxNTI4MzY0NTAwLCJqdGkiOiIxOTQxYmY5YS1jMTJkLTQ3NjYtOTMzMi02ZTg1YTNlNzI2MTIifQ.MiAZkGcOrog6KKYs5V1zED_ojQVs0vxZyFjPVjk29CPATaAEgpmH2Rq56kHJqhE3uQk4oSgMDJzp-Zk2CNPIRJYzy8pJaeP-gEE54NvRfDe1WHZJl72AAtEz9wEIQiKxkI4ZFdMlsnqmIdv8c0_lEfU4BXpH8Uho_Vatsvklv54WLEbSvHzf3M-0dioRnBDEf7xsImkcTGEsbulcKMNw9DOQFxlGLUv7r-qJIh9NUNlf0V7vXE9lVPaBSS8YDGKsjOV-PqnMAtmF6uL4eN36vcqMT5QP0C0s3pFJdz_YxEoN8xnrEn8_UNiJlZ-IxWooRFqQxFJri7fd4hlveoAKIQ","refresh_token":"f723c75a-dd06-3b5e-99a6-b5291f3cab28","token_type":"Bearer","expires_in":3600}

  • Now with this JWT token, we can call the WSO2 API Manager with the JWT grant type to get an access token. You need to copy the JWT token and use that within this request.
curl -i -X POST -u <clientID>:<clientSecret> -k -d 'grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJqb2huZG9lQGNhcmJvbi5zdXBlciIsImF1ZCI6WyJpcGtXTnlGMWZYdTRNYlNoRTZ2YUpHTkdrRElhIl0sImF6cCI6Imlwa1dOeUYxZlh1NE1iU2hFNnZhSkdOR2tESWEiLCJpc3MiOiJhcGltLWlkcCIsImV4cCI6MTUyODM2ODEwMCwiaWF0IjoxNTI4MzY0NTAwLCJqdGkiOiIxOTQxYmY5YS1jMTJkLTQ3NjYtOTMzMi02ZTg1YTNlNzI2MTIifQ.MiAZkGcOrog6KKYs5V1zED_ojQVs0vxZyFjPVjk29CPATaAEgpmH2Rq56kHJqhE3uQk4oSgMDJzp-Zk2CNPIRJYzy8pJaeP-gEE54NvRfDe1WHZJl72AAtEz9wEIQiKxkI4ZFdMlsnqmIdv8c0_lEfU4BXpH8Uho_Vatsvklv54WLEbSvHzf3M-0dioRnBDEf7xsImkcTGEsbulcKMNw9DOQFxlGLUv7r-qJIh9NUNlf0V7vXE9lVPaBSS8YDGKsjOV-PqnMAtmF6uL4eN36vcqMT5QP0C0s3pFJdz_YxEoN8xnrEn8_UNiJlZ-IxWooRFqQxFJri7fd4hlveoAKIQ' -H 'Content-Type: application/x-www-form-urlencoded' https://localhost:9444/oauth2/token


Here you need to replace the <clientID>:<clientSecret> with the values related to the “default application” which you have used to subscribe to the API within the store. This will return the access token which you can use to access the API. A sample response is given below.

{"access_token":"400f2a54-53d8-3146-88e3-be1bf5e7450d","refresh_token":"c2656286-449f-369f-9793-2cee9132de9f","scope":"default","token_type":"Bearer","expires_in":3600}

  • You can use this access token to consume the API with the below mentioned curl request.

curl -v -H "Authorization: Bearer 400f2a54-53d8-3146-88e3-be1bf5e7450d" http://172.18.0.1:8281/jwt/1.0.0

Comments

Post a Comment

Popular posts from this blog

WSO2 ESB tuning performance with threads

I have written several blog posts explaining the internal behavior of the ESB and the threads created inside ESB. With this post, I am talking about the effect of threads in the WSO2 ESB and how to tune up threads for optimal performance. You can refer [1] and [2] to understand the threads created within the ESB. [1] http://soatutorials.blogspot.com/2015/05/understanding-threads-created-in-wso2.html [2] http://wso2.com/library/articles/2012/03/importance-performance-wso2-esb-handles-nonobvious/ Within this blog post, I am discussing about the "worker threads" which are used for processing the data within the WSO2 ESB. There are 2 types of worker threads created when you start sending the requests to the server 1) Server Worker/Client Worker Threads 2) Mediator Worker (Synapse-Worker) Threads Server Worker/Client Worker Threads These set of threads will be used to process all the requests/responses coming to the ESB server. ServerWorker Threads will be used to pr

How puppet works in your IT infrstructure

What is Puppet? Puppet is IT automation software that helps system administrators manage infrastructure throughout its lifecycle, from provisioning and configuration to orchestration and reporting. Using Puppet, you can easily automate repetitive tasks, quickly deploy critical applications, and proactively manage change, scaling from 10s of servers to 1000s, on-premise or in the cloud. How the puppet works? It works like this..Puppet agent is a daemon that runs on all the client servers(the servers where you require some configuration, or the servers which are going to be managed using puppet.) All the clients which are to be managed will have puppet agent installed on them, and are called nodes in puppet. Puppet Master: This machine contains all the configuration for different hosts. Puppet master will run as a daemon on this master server. Puppet Agent: This is the daemon that will run on all the servers, which are to be managed using p

How to configure timeouts in WSO2 ESB to get rid of client timeout errors

WSO2 ESB has defined some configuration parameters which controls the timeout of a particular request which is going out of ESB. In a particular  scneario, your client sends a request to ESB, and then ESB sends a request to another endpoint to serve the request. CLIENT->WSO2 ESB->BACKEND The reason for clients getting timeout is that ESB timeout is larger than client's timeout. This can be solved by either increasing the timeout at client side or by decreasing the timeout in ESB side. In any of the case, you can control the timeout in ESB using the below properties. 1) Global timeout defined in synapse.properties (ESB_HOME\repository\conf\) file. This will decide the maximum time that a callback is waiting in the ESB for a response for a particular request. If ESB does not get any response from Back End, it will drop the message and clears out the call back. This is a global level parameter which affects all the endpoints configured in ESB. synapse.global_timeout_inte