Showing posts with label wso2 identity server. Show all posts
Showing posts with label wso2 identity server. Show all posts

Wednesday, June 26, 2013

WSO2 ESB talk to WSO2 Identity Server and get the authentication decision to invoke the proxy service

This is very good and simple example. let me explain the exact requirement.

If we need to secure the proxy service with UT (Username Token) in WSO2 ESB but all users and roles are maintained in the WSO2 Identity Server so when the users are going to invoke this service it should talk to WSO2 IS and get authenticated. In order to do this we have to implement Password Callback handler as follows.You can checkout total source here

[code language="java"]
package org.wso2.is.callback;


import org.apache.axis2.client.Options;
import org.apache.axis2.client.ServiceClient;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.transport.http.HttpTransportProperties;
import org.apache.ws.security.WSPasswordCallback;
import org.wso2.carbon.authenticator.stub.AuthenticationAdminStub;
import org.wso2.carbon.um.ws.api.WSUserStoreManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import java.io.IOException;


public class ISCallBackHandler implements CallbackHandler {
private static final Log log = LogFactory.getLog(ISCallBackHandler.class);
private String serverUrl = "https://localhost:9443/services/";

private AuthenticationAdminStub authstub = null;
private ConfigurationContext ctx;
private String authCookie = null;
private WSUserStoreManager remoteUserStoreManager = null;
@Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
try {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof WSPasswordCallback) {
WSPasswordCallback passwordCallback = (WSPasswordCallback) callbacks[i];
String username = passwordCallback.getIdentifer();
String receivedPasswd = passwordCallback.getPassword();

ctx = ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, null);
String authEPR = serverUrl + "AuthenticationAdmin";
authstub = new AuthenticationAdminStub(ctx, authEPR);
ServiceClient client = authstub._getServiceClient();
Options options = client.getOptions();
HttpTransportProperties.Authenticator authenticator = new HttpTransportProperties.Authenticator();
authenticator.setUsername("admin");
authenticator.setPassword("admin");
authenticator.setPreemptiveAuthentication(true);
options.setProperty(HTTPConstants.AUTHENTICATE, authenticator);
client.setOptions(options);

boolean status = authstub.login(username,receivedPasswd,"localhost");
if(status){
//Login Successful
} else{
throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
}

}
}

}catch (UnsupportedCallbackException e){
if(log.isDebugEnabled()){
log.debug(e.getMessage(), e); //logging invlaid passwords and attempts
throw e;
}
throw e;
} catch (Exception e){
log.error(e.getMessage(), e);
//can't build an unsupported exception.
throw new UnsupportedCallbackException(null, e.getMessage());
}

}
}

[/code]

1. First of all you have to build the above project and place the created jar file in to $ESB_HOME/repository/components/lib
2. Create the proxy service as follows and secured by UT
esb

esb1

esb2

esb3

2. Now you have to engage the created Password Call back handler. This is simply do with the policy configuration.
Go to policy configuration and insert the following line into the rampart configuration as follows.
"org.wso2.is.callback.ISCallBackHandler"

esb

esb1

esb2

esb3

3. Now you can invoke the service with username and password which is located in WSO2 Identity server.
(If you are going to run ESB and IS on same machine please consider the port offset as well as change the call back handler server url)

Tuesday, May 28, 2013

SCIM Bulk Endpoint Operations in WSO2 Identity Server

SCIM - (System for Cross-Domain Identity Management)
WSO2 Identity server has exposed the three major endpoints for SCIM operation as follows.
/Users , /Groups, /Bulk

Lets look at the SCIM Bulk operations supported by the Identity Server.
1. Create Users
Request -
[code language="java"]
curl -v -k --user admin:admin -H "Accept: application/json" -H "Content-type: application/json" -X POST -d "{\"failOnErrors\":2,\"schemas\":[\"urn:scim:schemas:core:1.0\"],\"Operations\":[{\"data\":{\"schemas\":[\"urn:scim:schemas:core:1.0\"],\"path\":\"/Users\",\"userName\":\"hasini\",\"method\":\"POST\",\"emails\":[{\"value\":\"hasini@gmail.com\"},{\"value\":\"hasinig@yahoo.com\"}],\"phoneNumbers\":[{\"value\":\"0772508354\"}],\"displayName\":\"Hasini\",\"externalId\":\"hasini@wso2.com\",\"password\":\"dummyPW1\",\"preferredLanguage\":\"Sinhala\",\"bulkId\":\"bulkIDUser1\"},\"path\":\"/Users\",\"method\":\"POST\",\"bulkId\":\"bulkIDUser1\"},{\"data\":{\"schemas\":[\"urn:scim:schemas:core:1.0\"],\"path\":\"/Users\",\"userName\":\"dinuka\",\"method\":\"POST\",\"emails\":[{\"value\":\"dinuka.malalanayake@gmail.com\"},{\"value\":\"dinuka_malalanayake@yahoo.com\"}],\"phoneNumbers\":[{\"value\":\"0772508354\"}],\"displayName\":\"Dinuka\",\"externalId\":\"dinukam@wso2.com\",\"password\":\"myPassword\",\"preferredLanguage\":\"Sinhala\",\"bulkId\":\"bulkIDUser2\"},\"path\":\"/Users\",\"method\":\"POST\",\"bulkId\":\"bulkIDUser2\"}]}" https://localhost:9443/wso2/scim/Bulk
[/code]
is

Response -
[code language="java"]
{"schemas":["urn:scim:schemas:core:1.0"],"Operations":[{"status":{"code":"201"},"location":"https://localhost:9443/wso2/scim/Users/bcbc6fed-6519-4eeb-a1ff-9b643fdab1b5","method":"POST","bulkId":"bulkIDUser1"},{"status":{"code":"201"},"location":"https://localhost:9443/wso2/scim/Users/ce6cf606-c4de-4260-bfdf-a751161eeae0","method":"POST","bulkId":"bulkIDUser2"}]}
[/code]
is2

2. Create Groups - Here you need to change the existing user IDs.
Request -
[code language="java"]
curl -v -k --user admin:admin -H "Accept: application/json" -H "Content-type: application/json" -X POST -d "{\"failOnErrors\":2,\"schemas\":[\"urn:scim:schemas:core:1.0\"],\"Operations\":[{\"data\":{\"schemas\":[\"urn:scim:schemas:core:1.0\"],\"path\":\"/Groups\",\"method\":\"POST\",\"displayName\":\"engineer\",\"externalId\":\"engineer\",\"members\":[{\"value\":\"b1b03cf2-470f-4a73-b517-ae4faed8e61b\"},{\"value\":\"8e2c7178-e5bf-4013-b526-1193e0611d9a\"}],\"bulkId\":\"bulkGroup1\"},\"path\":\"/Groups\",\"method\":\"POST\",\"bulkId\":\"bulkGroup1\"},{\"data\":{\"schemas\":[\"urn:scim:schemas:core:1.0\"],\"path\":\"/Groups\",\"method\":\"POST\",\"displayName\":\"doctor\",\"externalId\":\"doctor\",\"members\":[{\"value\":\"8e2c7178-e5bf-4013-b526-1193e0611d9a\"},{\"value\":\"b1b03cf2-470f-4a73-b517-ae4faed8e61b\"}],\"bulkId\":\"bulkGroup2\"},\"path\":\"/Groups\",\"method\":\"POST\",\"bulkId\":\"bulkGroup2\"}]}" https://localhost:9443/wso2/scim/Bulk
[/code]
is

Response -
[code language="java"]
{"schemas":["urn:scim:schemas:core:1.0"],"Operations":[{"status":{"code":"201"},"location":"https://localhost:9443/wso2/scim/Groups/6f008b6c-e990-4f67-9048-0fbcb3b52d5c","method":"POST","bulkId":"bulkGroup1"},{"status":{"code":"201"},"location":"https://localhost:9443/wso2/scim/Groups/1b7c44a8-26b8-4e81-9961-26d90fe68ac5","method":"POST","bulkId":"bulkGroup2"}]}
[/code]
is2

3. Delete Users
Request -
[code language="java"]
{"failOnErrors":2,"schemas":["urn:scim:schemas:core:1.0"],"Operations":[{"path":"/Users/6f3fc3ee-f39c-4d53-bc4d-649775313e29","method":"DELETE"},{"path":"/Users/b75bdb63-a36d-436d-8462-edd1db7e6b29","method":"DELETE"}]}
[/code]
is

Response -
[code language="java"]
{"schemas":["urn:scim:schemas:core:1.0"],"Operations":[{"status":{"code":"200"},"location":"/Users/bcbc6fed-6519-4eeb-a1ff-9b643fdab1b5","method":"DELETE"},{"status":{"code":"200"},"location":"/Users/ce6cf606-c4de-4260-bfdf-a751161eeae0","method":"DELETE"}]}
[/code]
is2

Friday, January 11, 2013

Multiple User Stores configuration in WSO2 Identity Server

You know wso2 products are very smart and customizable products. Here I'm going to explain one of another smart features came up with wso2 products. As a example will take WSO2 Identity server as a product.

Lets look at one of simple business scenarios.

1. I need connect multiple user stores.
ex/ different domain users in different databases to one single product.
2. All users can access same wso2 product (IS).

Multiple User Stores

First of all we need to do some configuration in Identity Server. Refer this post for additional information about data base configuration with wso2 products.

You have to create two databases in Mysql as FOO and BAR with database table structure. You can simply do this as follows.
Go to mysql command line and create two databases.
[sourcecode language="sql"]
mysql > create database FOO;
mysql > create database BAR;
[/sourcecode]

Go to command line and run the following commands to create the table structure.
[sourcecode language="bash"]
> mysql -u username -p FOO < $IS_HOME/dbscripts/mysql.sql
[/sourcecode]

[sourcecode language="bash"]
> mysql -u username -p BAR < $IS_HOME/dbscripts/mysql.sql
[/sourcecode]

Now we created databases properly.

1. master-datasource.xml - we have to configure three data sources for H2, FOO, BAR databases.

[sourcecode language="xml"]
<datasources>      
        <datasource>
            <name>WSO2_CARBON_DB</name>
            <description>The datasource used for registry and user manager</description>
            <jndiConfig>
                <name>jdbc/WSO2CarbonDB</name>
            </jndiConfig>
            <definition type="RDBMS">
                <configuration>
                    <url>jdbc:h2:repository/database/WSO2CARBON_DB;DB_CLOSE_ON_EXIT=FALSE;LOCK_TIMEOUT=60000</url>
                    <username>wso2carbon</username>
                    <password>wso2carbon</password>
                    <driverClassName>org.h2.Driver</driverClassName>
                    <maxActive>50</maxActive>
                    <maxWait>60000</maxWait>
                    <testOnBorrow>true</testOnBorrow>
                    <validationQuery>SELECT 1</validationQuery>
                    <validationInterval>30000</validationInterval>
                </configuration>
            </definition>
        </datasource>

       <datasource>
            <name>WSO2_MySQL_FOO_DB</name>
            <description>The datasource used for user manager bar.com</description>
            <jndiConfig>
                <name>jdbc/WSO2MySqlFooDB</name>
            </jndiConfig>
            <definition type="RDBMS">
                <configuration>
                    <url>jdbc:mysql://localhost:3306/FOO</url>
                    <username>root</username>
                    <password>root</password>
                    <driverClassName>com.mysql.jdbc.Driver</driverClassName>
                    <maxActive>50</maxActive>
                    <maxWait>60000</maxWait>
                    <testOnBorrow>true</testOnBorrow>
                    <validationQuery>SELECT 1</validationQuery>
                    <validationInterval>30000</validationInterval>
                </configuration>
            </definition>
        </datasource>

       <datasource>
            <name>WSO2_MySQL_BAR_DB</name>
            <description>The datasource used for user manager bar.com</description>
            <jndiConfig>
                <name>jdbc/WSO2MySqlBarDB</name>
            </jndiConfig>
            <definition type="RDBMS">
                <configuration>
                    <url>jdbc:mysql://localhost:3306/BAR</url>
                    <username>root</username>
                    <password>root</password>
                    <driverClassName>com.mysql.jdbc.Driver</driverClassName>
                    <maxActive>50</maxActive>
                    <maxWait>60000</maxWait>
                    <testOnBorrow>true</testOnBorrow>
                    <validationQuery>SELECT 1</validationQuery>
                    <validationInterval>30000</validationInterval>
                </configuration>
            </definition>
        </datasource>
[/sourcecode]

2. user-mgt.xml - Have to refer created data sources for specific domains.
The first user store configuration take as primary user store and others are secondary.
In the primary user store we are not going to specify the domain name.

[sourcecode language="xml"]
<UserStoreManager class="org.wso2.carbon.user.core.ldap.ReadWriteLDAPUserStoreManager">
<Property name="defaultRealmName">WSO2.ORG</Property>
<Property name="kdcEnabled">false</Property>
<Property name="ConnectionURL">ldap://localhost:${Ports.EmbeddedLDAP.LDAPServerPort}</Property>
<Property name="ConnectionName">uid=admin,ou=system</Property>
<Property name="ConnectionPassword">admin</Property>
<Property name="passwordHashMethod">SHA</Property>
<Property name="UserNameListFilter">(objectClass=person)</Property>
<Property name="UserEntryObjectClass">scimPerson</Property>
<Property name="UserSearchBase">ou=Users,dc=wso2,dc=org</Property>
<Property name="UserNameSearchFilter">(&amp;(objectClass=person)(uid=?))</Property>
<Property name="UserNameAttribute">uid</Property>
<Property name="PasswordJavaScriptRegEx">^[\\S]{5,30}$</Property>
<Property name="ServicePasswordJavaRegEx">^[\\S]{5,30}$</Property>
<Property name="ServiceNameJavaRegEx">^[\\S]{2,30}/[\\S]{2,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="UsernameJavaRegEx">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="ReadLDAPGroups">true</Property>
<Property name="WriteLDAPGroups">true</Property>
<Property name="EmptyRolesAllowed">true</Property>
<Property name="GroupSearchBase">ou=Groups,dc=wso2,dc=org</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="UserDNPattern">uid={0},ou=Users,dc=wso2,dc=org</Property>
<Property name="SCIMEnabled">true</Property>
<Property name="maxFailedLoginAttempt">0</Property>
</UserStoreManager>

<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">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="maxFailedLoginAttempt">0</Property>
<Property name="dataSource">jdbc/WSO2MySqlFooDB</Property>
<Property name="DomainName">foo.com</Property>
</UserStoreManager>

<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">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="UsernameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="RolenameJavaRegEx">[a-zA-Z0-9._-|//]{3,30}$</Property>
<Property name="RolenameJavaScriptRegEx">^[\\S]{3,30}$</Property>
<Property name="UserRolesCacheEnabled">true</Property>
<Property name="maxFailedLoginAttempt">0</Property>
<Property name="dataSource">jdbc/WSO2MySqlBarDB</Property>
<Property name="DomainName">bar.com</Property>
</UserStoreManager>
[/sourcecode]

Once you done above configurations you can start the Identity server.

3. Log in to the IS (username :admin, password : admin)
Configuration ->Users and Roles
is

Select Users->Add new Users
is

Now you can create the user in different domains.

[username :test password :test123] - it will store at primary user store.
as well as you can create User with specifying the domain. then it will store at specified domain user store.
[username :foo.com/dinuka password:dinuka ]
[username :bar.com/malinda password:malinda]

is

is

once you done this you have to go to Roles and give the login permission to everyone role.
is

Now you can log in to the IS with any user in primary or secondary user store either specifying the domain name or without domain name.

[username :foo.com/dinuka password : dinuka] or
[username :dinuka password : dinuka]
Once you try to log in to the system with specifying the domain, IS will look at the specified domain user store to authenticate the user.
other wise it will go through all the define user stores starting from primary user store.

is

is