Thursday, January 2, 2014

SAML2.0 Assertion with WSO2 Identity Server


In this blog post I will discuss the steps forCreating SAML2.0 Bearer Assertion profile for OAuth 2.0 with WSO2 Identity Server”.

  1. Download latest IS release from http://wso2.com/products/identity-server/.
    (Here I use WSO2 IS 4.6.0 since it is the latest release at the time of writing this blog post.)
  2. Create a SAML2 Assertion. You can use the command line client program (SAML2AssertionCreator) from here. Extract the ZIP file and navigate to the lib folder and execute the following command in the command linejava -jar SAML2AssertionCreator.jar <issuer> <username> <recipient> <requestedAudiences> <keyStoreFile> <keyStorePassword> <alias> <privateKeyPassword> <comma seperated user calimvalue pairs(claim:value)>
    ex:
    java -jar SAML2AssertionCreator.jar SAML2AssertionCreator shashika https://localhost:9443/oauth2/token https://localhost:9443/oauth2/token /home/shashika/Downloads/saml-oauth/wso2is-4.6.0/repository/resources/security/wso2carbon.jks wso2carbon wso2carbon wso2carbon FirstName|shashika,LastName|Ubhayaratne,Country|SriLanka


Note the “base64-url Encoded Assertion String” from the reply above and copy the part “PD.......3D”. This needs to be used in step 5.
  1. Register new Trusted Identity Provider.
  • Go to Configure -> Trusted Identity Providers.
  • Click on ‘Add New Trusted Identity Provider’.
  • Enter a unique identifier for this Trusted Identity Provider across the tenant.
    ex :
  • Identity Provider Name: sampleidp
  • Identity Provider Issuer: SAML2AssertionCreator
  • Identity Provider Public Certificate: << attach the certificate “wso2pem.pem” >> (You can generate this public certificate using kytool: (keytool -export -alias wso2cert -file wso2pem.pem -keystore wso2carbon.jks)
  • Identity Provider Audience: https://localhost:9443/oauth2/token


  1. Create a new OAuth2.0 application under Main -> Manage -> OAuth
    SAML should be selected as “Allowed Grant Types”.
  2. Execute the following HTTP request to the https://localhost:9443/oauth2/token endpointcurl -X POST -k -u "<Client Id>:<Client Secret>" -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -d "grant_type=urn:ietf:params:oauth:grant-type:saml2-bearer&scope=openid&assertion=<base64-url Encoded Assertion from step 2>" https://localhost:9443/oauth2/token/
    curl -X POST -k -u "noEnn5tvU5tgEJfHImicSApBMAwa:RMauKZY7H1GAWFJ77vffMI8Pv9ka" -H "Content-Type: application/x-www-form-urlencoded;charset=UTF-8" -d "grant_type=urn:ietf:params:oauth:grant-type:saml2-bearer&scope=openid&assertion=PD94bWwg<<.....>>9uPg%3D%3D" https://localhost:9443/oauth2/token/
    Note: assertion=PD94bWwg<<.....>>9uPg%3D%3D. This should be taken from Step2.
  3. In the response from above step you will get the base64 encoded id token
    ex: {"token_type":"bearer","expires_in":481,"refresh_token":"71df5c5a5ca2b6dc84c2cf2d64183342","id_token":"eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0=\r\n.eyJleHAiOi0zNzcyNjI5NywiYXpwIjoiZklFa1p0aW5yYnBMQlh4WDgzbXdEekNQOEFBYSIsInN1\r\nYiI6ImlzaGFyYSIsImF1ZCI6ImZJRWtadGlucmJwTEJYeFg4M213RHpDUDhBQWEiLCJpc3MiOiJo\r\ndHRwczpcL1wvbG9jYWxob3N0Ojk0NDNcL29hdXRoMmVuZHBvaW50c1wvdG9rZW4iLCJGaXJzdE5h\r\nbWUiOiJJc2hhcmEiLCJMYXN0TmFtZSI6IkthcnVuYXJhdGhuYSIsIkNvdW50cnkiOiJTcmlMYW5r\r\nYSIsImlhdCI6LTQxMzI2Mjk3fQ==\r\n.","access_token":"466d19d052acd21aec3ce045cb46329b"}

  4. Decoding the id_token value you can get the user claims. (Id token contains two values separated by '.')
    Refer bold part from the response, Remove “/r/n” parts and paste it on decoder.
    Go to “http://www.base64decode.org/
    Paste the copied text here.
    Text should be prepared as follows: eyJleHAiOi0zNzcyNjI5NywiYXpwIjoiZklFa1p0aW5yYnBMQlh4WDgzbXdEekNQOEFBYSIsInN1YiI6ImlzaGFyYSIsImF1ZCI6ImZJRWtadGlucmJwTEJYeFg4M213RHpDUDhBQWEiLCJpc3MiOiJo\r\ndHRwczpcL1wvbG9jYWxob3N0Ojk0NDNcL29hdXRoMmVuZHBvaW50c1wvdG9rZW4iLCJGaXJzdE5hbWUiOiJJc2hhcmEiLCJMYXN0TmFtZSI6IkthcnVuYXJhdGhuYSIsIkNvdW50cnkiOiJTcmlMYW5rYSIsImlhdCI6LTQxMzI2Mjk3fQ==
    Decoded String:
    {"exp":170653649,"azp":"noEnn5tvU5tgEJfHImicSApBMAwa","sub":"shashika","aud":"noEnn5tvU5tgEJfHImicSApBMAwa","iss":"https:\/\/localhost:9443\/oauth2endpoints\/token","FirstName":"shashika","LastName":"ubhayaratne","Country":"SriLanka","iat":167053649}

Thursday, July 18, 2013

How to Start WSO2 ESB with external LDAP


How to Start WSO2 ESB with external LDAP


WSO2 ESB is a fast, light-weight, and versatile Enterprise Service Bus. Using WSO2 ESB you can perform a variety of enterprise integration patterns, including filtering, transforming, and routing SOAP, binary, plain XML, and text messages that pass through your business systems by HTTP, HTTPS, JMS, mail, etc.

By default, ESB uses embedded jdbc user store as user management data source.
Default configuration as follows:
<UserStoreManager class="org.wso2.carbon.user.core.jdbc.JDBCUserStoreManager">
<Property name="ReadOnly">false</Property>
<Property name="MaxUserNameListLength">100</Property>
<Property name="IsEmailUserName">false</Property>
<Property name="DomainCalculation">default</Property>
<Property name="PasswordDigest">SHA-256</Property>
<Property name="StoreSaltedPassword">true</Property>
<Property name="UserNameUniqueAcrossTenants">false</Property>
<Property name="PasswordJavaRegEx">^[\S]{5,30}$</Property>
<Property name="PasswordJavaScriptRegEx">^[\\S]{5,30}$</Property>
<Property name="UsernameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\&lt;&gt;,\'\"]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">^[^~!#$;%^*+={}\\|\\\\&lt;&gt;,\'\"]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="maxFailedLoginAttempt">0</Property>
</UserStoreManager>

Now, I'll explain how to use external LDAP for ESB user-management user store.

WSO2 IS has its embedded LDAP and here I am going to use it as ESB's external LDAP.

Prerequisites: You need WSO2 ESB and WSO2 IS.
Any version you can choose as per the requirement and extract them
Step 1: Start IS with default port.

Step 2: Change ESB offset (since WSO2 IS uses the default port as per Step 1)
  1. Navigate to ESB_HOME/repository/conf/carbon.xml
    ex: <Offset>1</Offset>
Step 3: Chage user-mgt.xml (ESB_HOME/repository/user-mgt.xml
  1. <Property name="MultiTenantRealmConfigBuilder">org.wso2.carbon.user.core.config.multitenancy.CommonLDAPRealmConfigBuilder</Property>
  2. Comment default internal JDBC user store configurations ( showed in the beginning of this article)
  3. Uncomment external LDAP section
<!-- If product is using an external LDAP as the user store in read/write mode, use following user manager
In case if user core cache domain is needed to identify uniquely set property <Property name="UserCoreCacheIdentifier">domain</Property> -->
<UserStoreManager class="org.wso2.carbon.user.core.ldap.ReadWriteLDAPUserStoreManager">
<Property name="ConnectionURL">ldap://localhost:10389</Property>
<Property name="ConnectionName">uid=admin,ou=system</Property>
<Property name="ConnectionPassword">secret</Property>
<Property name="passwordHashMethod">PLAIN_TEXT</Property>
<Property name="UserNameListFilter">(objectClass=person)</Property>
<Property name="UserEntryObjectClass">inetOrgPerson</Property>
<Property name="UserSearchBase">ou=system</Property>
<Property name="UserNameSearchFilter">(&amp;(objectClass=person)(uid=?))</Property>
<Property name="UserNameAttribute">uid</Property>
<Property name="UsernameJavaRegEx">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="PasswordJavaScriptRegEx">^[\\S]{5,30}$</Property>
<Property name="ReadLDAPGroups">true</Property>
<Property name="WriteLDAPGroups">true</Property>
<Property name="EmptyRolesAllowed">false</Property>
<Property name="GroupSearchBase">ou=system</Property>
<Property name="GroupNameListFilter">(objectClass=groupOfNames)</Property>
<Property name="GroupEntryObjectClass">groupOfNames</Property>
<Property name="GroupNameSearchFilter">(&amp;(objectClass=groupOfNames)(cn=?))</Property>
<Property name="GroupNameAttribute">cn</Property>
<Property name="MembershipAttribute">member</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="ReplaceEscapeCharactersAtUserLogin">true</Property>
<Property name="maxFailedLoginAttempt">0</Property>
<Property name="DomainName">domain.com</Property>
</UserStoreManager>


  1. You need to change some properties according to IS user-mgt.xml (Refer the IS user-mgt/xml and its default LDAP settings)
  • No need to change the LDAP Port if IS started on default port
    (Othereise: 10389+<offset value>)
    ie: <Property name="ConnectionURL">ldap://localhost:10389</Property>
  • <Property name="ConnectionPassword">admin</Property>
  • <Property name="passwordHashMethod">SHA</Property>
  • <Property name="UserEntryObjectClass">identityPerson</Property>
  • <Property name="UserSearchBase">ou=Users,dc=wso2,dc=org</Property>
  • <Property name="GroupSearchBase">ou=Groups,dc=wso2,dc=org</Property>

Step 4: Start ESB

Wednesday, May 15, 2013

How to Convert JMeter Responses' Content-Type Header to any Format



How to Convert JMeter Responses' Content-Type Header to any Format: 


There are situations where you will get different formatted responses in JMeter.

As an example you will get binary response which is not readable. i.e: "Content-Type: application/octet-stream"
 Yet, you want to convert them to human readable format such as "Content-Type: application/xml"

To Convert the content-Type format, "Accept" header in HTTP Header Manager can be used.
ex:
Accept: application/xml or Aceept: text/xml, application/xhtml+xml

Send JMeter requests such as POST, PUT, GET, DELETE and view the message format with TCPMON.
(TCPMon is a utility that allows the messages to be viewed and resent. It is very much useful as a debug tool. http://ws.apache.org/tcpmon/)

tcpmon response from backend:

HTTP/1.1 200 OK
Set-Cookie: JSESSIONID=83A7EAF464474482FAB4ACE810E14592; Path=/jaxrs_basic_44/; HttpOnly
Date: Thu, 16 May 2013 04:51:13 GMTfr
Content-Type: application/octet-stream
Content-Length: 115
Server: WSO2 Carbon Server

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
   <Customer>
      <id>123</id>
      <name>method : test1</name>
   </Customer>


Binary format Response at user level: 

HTTP/1.1 200 OK
Content-Type: application/xml; charset=UTF-8
Server: WSO2 Carbon Server
Set-Cookie: JSESSIONID=83A7EAF464474482FAB4ACE810E14592; Path=/jaxrs_basic_44/; HttpOnly
Date: Thu, 16 May 2013 04:51:13 GMT
Transfer-Encoding: chunked
Connection: keep-alive

fb
<axis2ns11:binary xmlns:axis2ns11="http://ws.apache.org/commons/ns/payload">PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxDdXN0b21lcj48aWQ+MTIzPC9pZD48bmFtZT5tZXRob2QgOiB0ZXN0MTwvbmFtZT48L0N1c3RvbWVyPg==</axis2ns11:binary>0


After Using the "Accept" header in JMeter HTTP Header Manager (Refer the screenshot to add the Accept header):




Response at user level:
HTTP/1.1 200 OK
Content-Type: application/xml; charset=UTF-8
Server: WSO2 Carbon Server
Set-Cookie: JSESSIONID=78A769D448B58BC8D0F2D7858AB20E63; Path=/jaxrs_basic_44/; HttpOnly
Date: Thu, 16 May 2013 06:16:36 GMT
Transfer-Encoding: chunked
Connection: keep-alive

3c
<Customer>
   <id>123</id>
   <name>method : test1</name></Customer>0


Friday, May 10, 2013

Step by step guide to configure multiple ActiveMQ instances in one Server


Step by step guide to configure multiple ActiveMQ instances in one Server:

Prerequisites:
1. Download ActiveMQ binary file
(ex: apache-activemq-5.4.2-bin.tar.gz from http://activemq.apache.org/activemq-542-release.html)
2. untar the .tar.gz file
tar -zxvf apache-activemq-5.4.2-bin.tar.gz

Create and Start instance 1:
1.  Navigate to ActiveMQ folder:
cd /home/test/apache-activemq-5.4.2
2. Create an ActiveMQ instance as instance1:
bin/activemq create instance1
(This will create a folder as instance1: "/home/test/apache-activemq-5.4.2/instance1")
3.  bin/activemq setup ~/.activemqrc-instance-instance1
4.  ln -s activemq bin/activemq-instance-instance1
5.  Give executable permission to instance:
chmod 755 instance1/bin/instance1
6.  cd instance1/bin (i.e: /home/test/apache-activemq-5.4.2/instance1/bin)
7.  Start intsnace1
./instance1 console

Create and Start instance 2:
8.   cd /home/test/apache-activemq-5.4.2
9.   bin/activemq create instance2
10. bin/activemq setup ~/.activemqrc-instance-instance2
11. ln -s activemq bin/activemq-instance-instance2
12. chmod 755 instance2/bin/instance2
13. Edit activemq.xml file and jetty.xml in /<instance>/conf folder
  • cd instance2 (i.e: /home/test/apache-activemq-5.4.2/instance2)
  • vi conf/activemq.xml
  • Edit “transportConnectors” port:
    (ex:<transportConnector name="openwire" uri="tcp://0.0.0.0:61617"/>)
Default setting as follows:
<transportConnectors> <transportConnector name="openwire" uri="tcp://0.0.0.0:61616"/> </transportConnectors>
  • save and exit

  • vi conf/jetty.xml
  • Edit “Connector” port
    (ex: <property name="port" value="8162" />
Default setting as follows:
<property name="connectors"> <list>
<bean id="Connector" class="org.eclipse.jetty.server.nio.SelectChannelConnector">
<property name="port" value="8161" />
</bean>
</list>
</property>
  • save and exit
14. cd instance2/bin (i.e: /home/test/apache-activemq-5.4.2/instance2/bin)
15. Start intsnace2
./instance2 console

Note: Any number of instances can be configured and started accordingly.