Wednesday, April 29, 2015

WSO2 API Manager relationship between timestamp skew, token validity period and cache expiration time

Let me explain how time stamp skew works and how it effect to token generation.
First  time stamp skew is there to fix the issues due to small time differences in system clock values of servers. 
Let say you have 2 key managers and you generate token from one and authenticate with other. 
When first key manager generates token(say life span is 3600sec), time stamp skew value(say 300sec) will be deducted from token life time(client will notify that 3300sec is token validity period). 
Then he call to second key manager with that token exactly after 3200 secs and there is time different between key managers(second key manager has +300 sec time difference). 
In such cases time stamp skew will take care of those small gaps.

So theoretically 
time stamp skew should never large than token life time
It should be very small comparing to token validity period.
Token cache duration should never large than token validity period.

You can change configuration values according to requirements but you cannot put any random numbers as you need because those are inter related :-)

Wednesday, April 15, 2015

How to use cxf intercepter to pre-process requests to JAX-RS services - Apply security for JAX_RS services


When we use jax-rs services sometimes we need to add request pre processors to services. In this post i will discuss how we can use cxf interceptor in jax-rs services.
You may find more information from this url[http://cxf.apache.org/docs/interceptors.html]
package demo.jaxrs.server;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.cxf.message.Message;
import org.apache.cxf.phase.AbstractPhaseInterceptor;
import org.apache.cxf.phase.Phase;

public class CustomOutInterceptor extends AbstractPhaseInterceptor {

    public CustomOutInterceptor() {
        //We will use PRE_INVOKE phase as we need to process message before hit actual service
        super(Phase.PRE_INVOKE );
    }

    public void handleMessage(Message outMessage) {
        System.out.println("Token: "+ ((TreeMap) outMessage.get(Message.PROTOCOL_HEADERS)).get("Authorization"));
  // Do your processing with Authorization transport header.
    }
}

Then we need to register Interceptor by adding entry to webapp/WEB-INF/cxf-servlet.xml file. Then it will execute before request dispatch to actual service.


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:jaxrs="http://cxf.apache.org/jaxrs"
       xsi:schemaLocation="
         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
         http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
    <jaxrs:server id="APIService" address="/">
        <jaxrs:serviceBeans>
            <ref bean="serviceBean"/>
        </jaxrs:serviceBeans>

        <jaxrs:inInterceptors>
            <ref bean="testInterceptor"/>
        </jaxrs:inInterceptors>
    </jaxrs:server>
    <bean id="testInterceptor" class="demo.jaxrs.server.CustomOutInterceptor" />
    <bean id="serviceBean" class="demo.jaxrs.server.APIService"/>
</beans>




Then compile web app and deploy in application server. Once you send request with Authorization header you will noticed that it printed in server logs.

See following sample curl request
curl -k -v -H "Authorization: Bearer d5701a8ed6f677f215fa4d65c05e361" http://127.0.0.1:9763/APIManager/qqqq-1.0.0-admin/

And server logs for request
Token: [Bearer d5701a8ed6f677f215fa4d65c05e361]
API Service -- invoking getAPI, API id is: qqqq-1.0.0-admin

Tuesday, April 7, 2015

How to generate custom error message with custom http status code for throttled out messages in WSO2 API Manager.

In this post we will discuss how we can override the throttle out message HTTP status code. APIThrottleHandler.handleThrottleOut method indicates that the _throttle_out_handler.xml sequence is executed if it exists. If you need to send custom message with custom http status code we may execute additional sequence which can generate new error message. There we can override message body, http status code etc.

Create convert.xml with following content

<?xml version="1.0" encoding="UTF-8"?><sequence xmlns="http://ws.apache.org/ns/synapse" name="convert">
    <payloadFactory media-type="xml">
        <format>
            <am:fault xmlns:am="http://wso2.org/apimanager">
                <am:code>$1</am:code>
                <am:type>Status report</am:type>
                <am:message>Runtime Error</am:message>
                <am:description>$2</am:description>
            </am:fault>
        </format>
        <args>
            <arg evaluator="xml" expression="$ctx:ERROR_CODE"/>
            <arg evaluator="xml" expression="$ctx:ERROR_MESSAGE"/>
        </args>
    </payloadFactory>
    <property name="RESPONSE" value="true"/>
    <header name="To" action="remove"/>
    <property name="HTTP_SC" value="555" scope="axis2"/>
    <property name="NO_ENTITY_BODY" scope="axis2" action="remove"/>
    <property name="ContentType" scope="axis2" action="remove"/>
    <property name="Authorization" scope="transport" action="remove"/>
    <property name="Access-Control-Allow-Origin" value="*" scope="transport"/>
    <property name="Host" scope="transport" action="remove"/>
    <property name="Accept" scope="transport" action="remove"/>
    <property name="X-JWT-Assertion" scope="transport" action="remove"/>
    <property name="messageType" value="application/json" scope="axis2"/>
    <send/>
</sequence>


Then copy it to wso2am-1.6.0/repository/deployment/server/synapse-configs/default/sequences directory or use source view to add it to synapse configuration.
If it deployed properly you will see following message in system logs. Please check the logs and see is there any issue in deployment process.

[2015-04-13 09:17:38,885]  INFO - SequenceDeployer Sequence named 'convert' has been deployed from file : /home/sanjeewa/work/support/wso2am-1.6.0/repository/deployment/server/synapse-configs/default/sequences/convert.xml

Now sequence deployed properly then we may use it in _throttle_out_handler_ sequence. Add it as follows.

<?xml version="1.0" encoding="UTF-8"?><sequence xmlns="http://ws.apache.org/ns/synapse" name="_throttle_out_handler_">
    <sequence key="_build_"/>
    <property name="X-JWT-Assertion" scope="transport" action="remove"/>
    <sequence key="convert"/>
    <drop/>
</sequence>



Once _throttle_out_handler_ sequence deployed properly you will see following message in carbon logs. Check carbon console and see is there any errors with deployment.

[2015-04-13 09:22:40,106]  INFO - SequenceDeployer Sequence: _throttle_out_handler_ has been updated from the file: /home/sanjeewa/work/support/wso2am-1.6.0/repository/deployment/server/synapse-configs/default/sequences/_throttle_out_handler_.xml


Then try to invoke API until requests get throttled out. You will see following response.

curl -v -H "Authorization: Bearer 7f855a7d70aed820a78367c362385c86" http://127.0.0.1:8280/testam/sanjeewa/1.0.0


* About to connect() to 127.0.0.1 port 8280 (#0)
*   Trying 127.0.0.1...
* Adding handle: conn: 0x17a2db0
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x17a2db0) send_pipe: 1, recv_pipe: 0
* Connected to 127.0.0.1 (127.0.0.1) port 8280 (#0)
> GET /testam/sanjeewa/1.0.0 HTTP/1.1
> User-Agent: curl/7.32.0
> Host: 127.0.0.1:8280
> Accept: */*
> Authorization: Bearer 7f855a7d70aed820a78367c362385c86
>
< HTTP/1.1 555
< Access-Control-Allow-Origin: *
< Content-Type: application/json
< Date: Mon, 13 Apr 2015 05:30:12 GMT
* Server WSO2-PassThrough-HTTP is not blacklisted
< Server: WSO2-PassThrough-HTTP
< Transfer-Encoding: chunked
<
* Connection #0 to host 127.0.0.1 left intact
{"fault":{"code":"900800","type":"Status report","message":"Runtime Error","description":"Message throttled out"}}

Thursday, April 2, 2015

How to use custom passowrd validation policy in WSO2 API Manager and update sign-up UI to handle new policy




In this article we will discuss how we can change password policy by using identity server specific configurations. Also we will discuss about updating API store sign-up page according to custom password policy. So when new users sign-up in API store it will be easy for them.


Please follow below instructions to change password policy by updating identity-mgt.properties file available in repository/conf/security directory.
You can find more information from this url - https://docs.wso2.com/display/IS450/Password+Policies

Do necessary changes in identity-mgt.properties file
# Identity listener is enable

Identity.Listener.Enable=true

# Define password policy enforce extensions

Password.policy.extensions.1=org.wso2.carbon.identity.mgt.policy.password.DefaultPasswordLengthPolicy
Password.policy.extensions.1.min.length=6
Password.policy.extensions.1.max.length=32
Password.policy.extensions.2=org.wso2.carbon.identity.mgt.policy.password.DefaultPasswordNamePolicy
Password.policy.extensions.3=org.wso2.carbon.identity.mgt.policy.password.DefaultPasswordPatternPolicy
Password.policy.extensions.3.pattern=^((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%&*])).{0,100}$
Password should contain a digit 0-9, a lower case letter a-z, an upper case letter A-Z, one of !@#$%&* characters as in Password.policy.extensions.3.pattern. But sign-up process has issue with this pattern.

Then we can customize sign-up process of store by adding sub theme.

1. create a folder call custom-signup in below path of store. You can give any preferable name.
wso2am-1.7.0/repository/deployment/server/jaggeryapps/store/site/themes/fancy/subthemes/custom-signup

2. copy following folders to above location.
wso2am-1.7.0/repository/deployment/server/jaggeryapps/store/site/themes/fancy/js folder to wso2am-1.7.0/repository/deployment/server/jaggeryapps/store/site/themes/fancy/subthemes/custom-signup
wso2am-1.7.0/repository/deployment/server/jaggeryapps/store/site/themes/fancy/templates folder to wso2am-1.7.0/repository/deployment/server/jaggeryapps/store/site/themes/fancy/subthemes/custom-signup

3. Open below file. This file contain password validation function of sign-up.
wso2am-1.7.0/repository/deployment/server/jaggeryapps/store/site/themes/fancy/subthemes/custom-signup/js/lib/jquery.validate.password.js
You can change validation logic written in $.validator.passwordRating = function(password, username) according to above pattern or whatever pattern you want.

Please find the attach jquery.validate.password.js modified according to above pattern.

(function($) {
       function rating(rate, message) {
        return {
            rate: rate,
            messageKey: message
        };
    }
    function uncapitalize(str) {
        return str.substring(0, 1).toLowerCase() + str.substring(1);
    }
    $.validator.passwordRating = function(password, username) {
            var minLength = 6;
            var passwordStrength   = 0;
            if ((password.length >0) && (password.length <=5)) passwordStrength=0;
            if (password.length >= minLength) passwordStrength++;
            if ((password.match(/[a-z]/)) && (password.match(/[A-Z]/))) passwordStrength++;
            if (password.match(/\d+/)) passwordStrength++;
            if (password.match(/.[!,@,#,$,%,^,&,*]/)) passwordStrength++;
            if (password.length > 12) passwordStrength++;
            if (username && password.toLowerCase()== username.toLowerCase()){
                passwordStrength = 0;
            }
            $('#pwdMeter').removeClass();
            $('#pwdMeter').addClass('neutral');
            switch(passwordStrength){
            case 1:
                return rating(1, "very-weak");
              break;
            case 2:
                return rating(2, "weak");
              break;
            case 3:
                return rating(3, "weak");
              break;
            case 4:
                return rating(4, "medium");
              break;
            case 5:
                 return rating(5, "strong");
              break;
            case 6:
                 return rating(5, "vstrong");
              break;
            default:
                return rating(1, "very-weak");
            }
    }
    $.validator.passwordRating.messages = {
        "similar-to-username": "Too similar to username",
        "very-weak": "Very weak",
        "weak": "Weak",
        "medium": "Medium",
        "strong": "Strong",
        "vstrong": "Very Strong"
    }
    $.validator.addMethod("password", function(value, element, usernameField) {
        // use untrimmed value
        var password = element.value,
        // get username for comparison, if specified
            username = $(typeof usernameField != "boolean" ? usernameField : []);        
        var rating = $.validator.passwordRating(password, username.val());
        // update message for this field
        var meter = $(".password-meter", element.form);
        meter.find(".password-meter-bar").removeClass().addClass("password-meter-bar").addClass("password-meter-" + rating.messageKey);
        meter.find(".password-meter-message")
        .removeClass()
        .addClass("password-meter-message")
        .addClass("password-meter-message-" + rating.messageKey)
        .text($.validator.passwordRating.messages[rating.messageKey]);
        // display process bar instead of error message
        return rating.rate > 3;
    }, "Minimum system requirements not met");
    // manually add class rule, to make username param optional
    $.validator.classRuleSettings.password = { password: true };
   
})(jQuery);


Also make sure return rating.rate > 2; of $.validator.addMethod("password", function(value, element, usernameField) will give you the expected strength of password.
We can modify it as follows
return rating.rate > 3;
to make sure that entered password adhere above pattern.


4. If you want to change above Password.policy.extensions.3.pattern to different pattern and show password tips to user when entering password you need to edit following files.
wso2am-1.7.0/repository/deployment/server/jaggeryapps/store/site/themes/fancy/subthemes/custom-signup/templates/user/sign-up/template.jag

Below section correspond to display password tips
  
<div class="help-block" id="password-help" style="display:none">
 <%=i18n.localize("pwHelpMsgLine1")%>
 <ul>
 <li>This is new changed TIP :-) </li>                
<li><%=i18n.localize("pwHelpMsgLine3")%></li> 
<li><%=i18n.localize("pwHelpMsgLine4")%></li>
<li><%=i18n.localize("pwHelpMsgLine5")%></li>
</ul>
</div>
                 
  
Please change text as you want in below file accroding to above keys.
wso2am-1.7.0/repository/deployment/server/jaggeryapps/store/site/conf/locales/jaggery/locale_default.json


5. Finally, do below config to enable above changes in store.
Open wso2am-1.7.0/repository/deployment/server/jaggeryapps/store/site/conf/site.json
Add sub theme folder as below
    "theme" : {
        "base" : "fancy",
        "subtheme" : "custom-signup"
    },
  
This will override current user sign-up validation by above changes as well as if you did any changes to password tips text.