Friday, July 7, 2017

Debugging "API authentication failure due to Unclassified Authentication Failure" on WSO2 API Manager

One of the common issues you could get when setting up WSO2 API Manager in a clustered setup is "failure due to Unclassified Authentication Failure" error when invoking the api.

WARN APIAuthenticationHandler API authentication failure due to Unclassified Authentication Failure 

This error happens when the gateway node fails to validate the token. Following are some of the tips you could use to debug this issue

1. Check the errors in KeyManager node.
   First thing you should do is to see if there are any errors in the Keymanager error logs. If there are errors, then we could rule out the connection related issues from Gateway to Keymanager node.

2. Check configurations.
   There could be configuration issue in <APIKeyValidator> section in api-manager.xml file in both servers. Check the urls and see whether they point to the correct endpoint. Aslo check whether <KeyValidatorClientType> property is same in both gateway and keymanager. You could swith the client type (WSClient or ThriftClient) and check as well. (Need to configure the thrift ports correctly)

3. Enable debug logs
 
   Add following entries to the log4j.properties in  repository/conf file in the given node

   In gateway node

       log4j.logger.org.wso2.carbon.apimgt.gateway.handlers.security=DEBUG

   In keymanager node

        log4j.logger.org.wso2.carbon.apimgt.keymgt=DEBUG

From these logs you could get more idea on the issue happening

Saturday, June 24, 2017

Extract payload information using custom sequence - WSO2 API Manager

Anyone can easily plug in a custom logic to WSO2 API manager to process request/response payloads using Mediation Extensions feature. Following two custom sequences can be used to evaluate payload with content type application/x-www-form-urlencoded and application/json

1. application/x-www-form-urlencoded


<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="form_data">
  <property name="LastName" expression="//xformValues//lastName/text()"/> 

  <log level="custom">
    <property name="Log: LastName" expression="get-property('LastName')" />
  </log>
</sequence>
Sample request
curl -k -X POST -H 'Authorization: Bearer 95b59dfc-aae1-3b85-aec7-93a0471fea42' -H "Content-Type: application/x-www-form-urlencoded" 'https://172.21.0.1:8243/test/1/*' -d 'lastName=chamila' 

2. application/json


<?xml version="1.0" encoding="UTF-8"?>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="json_payload">
 
  <property expression="json-eval($.lastName)" name="LastName"/>

  <log level="custom">
    <property name="Log: LastName" expression="get-property('LastName')" />
  </log>
</sequence>


Sample request
curl -k -X POST -H 'Authorization: Bearer 95b59dfc-aae1-3b85-aec7-93a0471fea42' -H "Content-Type: application/json" 'https://172.21.0.1:8243/test/1/*' -d '{"lastName":"chamila"} 

WSO2 API Manager: Access user attributes from a custom sequence


For some use cases, API developer may want to access the API invoker's user information (such as his email address, roles etc). Easiest method to access these information is by getting the user claims for that user. Following method describes how to access user claims and extract a selected claim using a custom sequence

1. Enable JWT token as mentioned in here. This token contains the user related claims and it is set to the X-JWT-Assertion header during the authentication process.

2. Create a custom mediator sequence using Mediation extension feature. Following is a sample mediation sequence that can be used to extract the claim from jwt token.


<sequence xmlns="http://ws.apache.org/ns/synapse" name="jwt_decoder">

<property name="jwt-header" expression="get-property('transport','X-JWT-Assertion')"/>

<script language="js">
var jwt = mc.getProperty('jwt-header').trim();
var jwtPayload = jwt.split("\\.")[1];
var jsonStr = Packages.java.lang.String(Packages.org.apache.commons.codec.binary.Base64.decodeBase64(jwtPayload));

var jwtJson = JSON.parse(jsonStr);

var roles = jwtJson['http://wso2.org/claims/role'];
mc.setProperty("roles",JSON.stringify(roles));
</script>

<log level="custom">
  <property name="USER_ROLES" expression="$ctx:roles"/>
</log>

</sequence>