Submitted on January 5, 2008 - 21:00.
AuthenticationMediator employs WSO2 UserManager to authenticate users. UserManager realms have the ability to connect new or existing user stores maintained in different technologies such as LDAP, Acegi or relational databases.
| WSO2 ESB version | 1.5 |
| WSO2 UserManager | version 0.5 |
| Axis2 | 1.3 |
This tutorial shows how to install and run AuthenticationMediator, then it goes on to explain implementation details of the Mediator. If you are only interested in implementation details then you can jump to it straight away.
Before we begin, we assume you know how to work with the WSO2 ESB, although you are not expected to know anything about the UserManager. This article will refer to the directory where WSO2 ESB is installed as <esb-home> - mimicking the WSO2 ESB documentation.
This is how you install AuthenticationMediator to your WSO2 ESB:
This tutorial deals with a client that sends username/password using pre-emptive HTTP basic authentication. The client is available inside <esb-home>/authenticate-mediator/auth-client.
WSO2 ESB creates the AuthenticationMediator when it encounters the <userStore> XML element inside the Synapse Configuration. Therefore, we will edit the <esb-home>/repository/conf/sample/synapse_sample_150.xml, as shown in Step #4 below. The configuration XML snippet also states the type of user's store and how to connect to it. For example, if the user store is LDAP, the XML will state how to connect to it and authenticated users. When creating the AuthenticationMediator the relevant realm will also be created.
ant create-db
The ant script will create an Apache Derby database inside <esb-home>/authentication-mediator/sample_db/AuthenticationMediatorUsers/USER_STORE. Copy the USER_STORE directory into <esb-home>/webapp/WEB-INF/classes/conf directory. It will contain the following users:
| User Name | Password |
|---|---|
| john | doe |
| alice | alice |
| bob | bob |
| chris | chris |
derby.user.tintin=snowyDerby is configured inside ESB to use "Built-In authentication scheme". Therefore, all derby connection username/passwords must be in the file. The connection name for our sample user database is "tintin" and password "snowy". This step is not needed if you are using some other JDBC driver other than Derby.
sh wso2-esb.sh -sample 150
<syn:inSequence>
<syn:userStore>
<syn:realmClass>org.wso2.usermanager.custom.jdbc.JDBCRealm</syn:realmClass>
<syn:realmParameters>
<syn:parameter name="UserTable">sample_user</syn:parameter>
<syn:parameter name="UserNameColumn">username</syn:parameter>
<syn:parameter name="UserCredentialColumn">password</syn:parameter>
<syn:parameter name="ConnectionURL">jdbc:derby:USER_STORE</syn:parameter>
<syn:parameter name="DriverName">org.apache.derby.jdbc.EmbeddedDriver</syn:parameter>
<syn:parameter name="ConnectionUserName">tintin</syn:parameter>
<syn:parameter name="ConnectionPassword">snowy</syn:parameter>
</syn:realmParameters>
</syn:userStore>
</syn:inSequence>
ant stockquote -Daddurl=http://localhost:8080/soap/StockQuoteProxy -Dusername=alice -Dpassword=alice
ant stockquote -Daddurl=http://localhost:8080/soap/StockQuoteProxy -Dusername=alice -Dpassword=hora
In this manner, you could also connect to any existing database using a standard JDBC driver. All you have to do is change the configuration parameters.
Before continuing you must have a LDAP server running on your local machine or in a server accessible to you.
sh wso2-esb.sh -sample 150
<syn:inSequence>
<syn:userStore>
<syn:realmClass>org.wso2.usermanager.custom.ldap.LDAPRealm</syn:realmClass>
<syn:realmParameters>
<syn:parameter name="ConnectionUrl">ldap://localhost:389</syn:parameter>
<syn:parameter name="ConnectionName">cn=root,dc=wso2,dc=com</syn:parameter>
<syn:parameter name="ConnectionPass">secret</syn:parameter>
<syn:parameter name="UserPattern">uid={0},ou=People,dc=wso2,dc=com</syn:parameter>
</syn:realmParameters>
</syn:userStore>
</syn:inSequence>
ant stockquote -Daddurl=http://localhost:8080/soap/StockQuoteProxy -Dusername=alice -Dpassword=alice
Download Acegi 1.0.6 release from here and unzip it. We will call this folder <acegi-home>
sh wso2-esb.sh -sample 150<
<bean id="userDetailsService" class="org.acegisecurity.userdetails.memory.InMemoryDaoImpl">
<property name="userProperties">
<bean class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="users.properties"/>
</bean>
</property>
</bean>
AuthenticationProviderBeanMappingFile parameter, the relative file path must be given:
<syn:inSequence>
<syn:userStore>
<syn:realmClass>org.wso2.usermanager.custom.acegi.AcegiRealm</syn:realmClass>
<syn:realmParameters>
<syn:parameter name="AuthenticationProviderBeanMappingFile">applicationContext-acegi-security.xml</syn:parameter>
<syn:parameter name="AuthProviderId">daoAuthenticationProvider</syn:parameter>
</syn:realmParameters>
</syn:userStore>
</syn:inSequence>
ant stockquote -Daddurl=http://localhost:8080/soap/StockQuoteProxy -Dusername=scott -Dpassword=wombat
In this section we discuss implementation details of AuthenticationMediator briefly. We use the interface trio described here - Mediator, Factory and Serializer.
When mediator() method of AuthenticationMediator is called, it reads username/password from HTTP headers and the authenticate() method of the realm is called to provide authentication. If the user is not authenticated, an exception is thrown and the service will not be accessible.
Axis2MessageContext axis2smc = (Axis2MessageContext) synCtx;
org.apache.axis2.context.MessageContext axis2MessageCtx =
axis2smc.getAxis2MessageContext();
Map tmp = (Map)axis2MessageCtx.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
String authString = (String)tmp.get("Authorization");
String username = null;
String password = null;
if (authString != null) {
authString = authString.trim();
}
if (authString.startsWith("Basic ")) {
authString = new String(Base64.decode(authString.substring(6)));
int i = authString.indexOf(':');
if (i == -1) {
username = authString;
} else {
username = authString.substring(0, i);
}
if (i != -1) {
password = authString.substring(i + 1);
if (password != null && password.equals("")) {
password = null;
}
}
}
if(!realm.getAuthenticator().authenticate(username, password)){
handleException("Invalid Username/Password!", synCtx);
}
When the createMediator() method of the AuthenticationMediatorFactory is called, the Realm is created and set to the AuthenticationMediator.
Class clazz = Class.forName(realmClassName);
Realm realm = (Realm) clazz.newInstance();
Object configBean = realm.getRealmConfiguration();
.................
/*
Populate configBean by reading name-value pairs given
by parameter elements inside the <userStore>
of the Synapse Configuration.
Using Java Reflection.
*/
........
...
realm.init(configBean);
AuthenticationMediator mediator = new AuthenticationMediator();
mediator.setRealm(realm);
return mediator;
The XML snippet given in the Synapse definition is used for creating and configuring the Realm inside the Mediator Factory. Since Java Reflection is used for populating the configuration of the Realm, any custom Realm can be loaded into the AuthenticationMediator.
For example,
<syn:userStore>
<syn:realmClass>org.wso2.usermanager.custom.jdbc.JDBCRealm</syn:realmClass>
<syn:realmParameters>
<syn:parameter name="UserTable">users</syn:parameter>
</syn:realmParameters>
</syn:userStore>
The method called for the above parameter is setUserTable() in the configBean of the Realm.
WSO2 ESB is a powerful and extensible enterprise service bus. UserManager is a flexible and extensible library that can be configured to connect user stores belonging to different technologies. In the same way, developers can add functionality to the WSO2 ESB by writing Mediators. New Realms can be written enabling UserManager to connect to many different types of user stores. AuthenticationMediator uses Java Reflection technology to populate realms by reading the XML snippet. Therefore, AuthenticationMediator is not restricted to the Realms mentioned above.
Dimuthu Leelarathne is a Senior Software Engineer at WSO2. She is a committer of the Apache Software Foundation.
dimuthul at wso2 dot com
| Attachment | Size |
|---|---|
| authentication-mediator.zip | 129.01 KB |