HTTP Basic Authentication Mediator in WSO2 ESB with UserManager
Submitted on January 5, 2008 - 21:00. Story : Level : Project :
WSO2 ESB comes with a rich collection of useful mediators to filter, transform, route and manipulate messages. Developers can use these custom mediators to very easily add extra functionality. AuthenticationMediator is a custom mediator that can authorize users to access a Web service based on HTTP Basic authentication.
Introduction
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.
Features of AuthenticationMediator
- Clients provide username/password using HTTP Basic authentication
- Can authenticate users against user stores maintained in either LDAP, Acegi or RDBMS
Applies To
| WSO2 ESB version | 1.5 |
| WSO2 UserManager | version 0.5 |
| Axis2 | 1.3 |
Table of contents
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.
- Background
- Installing and Running AuthenticationMediator
- Implementing the AuthenticationMediator
- Conclusion
Background
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.
Installing and Running AuthenticationMediator
This is how you install AuthenticationMediator to your WSO2 ESB:
- Download authentication-mediator.zip from this page and extract it inside the <esb-home> directory. Make sure it isn't extracted to a sub directory, as the directory "authentication-mediator" must be directly under <esb-home>.
- Add all the jar files inside the <esb-home>/authenticate-mediator/lib directory to <esb-home>/webapp/WEB-INF/lib directory.
- We will modify the Synapse sample 150 configuration to test the Mediator. Therefore, first back up the file named <esb-home>/repository/conf/sample/synapse_sample_150.xml.
Connecting to a RDBMS User Store
- Go to <esb-home>/authentication-mediator/sample-db and give the following command:
- Add the following to the <esb-home>/webapp/WEB-INF/classes/conf/derby.properties file:
- Start the ESB with sample configuration 150.
- Go to the ESB management console and click on the Configuration tab. Edit the configuration to include a <inSequence> with the following XML snippet. This element should be at the same level as <syn:outSequence>. Then click update.
- Go to <esb-home>/samples/axis2Server. Start the sample Axis2 server by running the axis2server script.
- Go to <esb-home>/authentication-mediator/auth-client. Run the client by typing the following.
- If you run the client by giving the following data, it must fail, since the password is incorrect.
ant create-db
| 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
Troubleshooting Connecting to a RDBMS User Store
- If you are using a Derby database driver, check to confirm that you have updated derby.properties file with the username/password as in the previous step (step2).
- If you are using a driver other than Derby, check to confirm that it is added to the classpath
- Check for version compatibilities with the database and the version of the driver you are using.
- Different database drivers require different patterns of connection URLs. Make sure the data given is correct.
Connecting to a LDAP User Store
Before continuing you must have a LDAP server running on your local machine or in a server accessible to you.
- Start the ESB by typing the following command.
- In the ESB management console's Configuration tab, edit the configuration to have a <inSequence>. Following is a sample XML snippet for LDAP. Click on update.
- Go to <esb-home>/samples/axis2Server. Start the sample Axis2 server
- Go to <esb-home>/authentication-mediator/auth-client. Run the client as follows:
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
Connecting to a Acegi user store
Download Acegi 1.0.6 release from here and unzip it. We will call this folder <acegi-home>
- Add <acegi-home>/acegi-security-1.0.6.jar to <esb-home>/webapp/WEB-INF/lib directory
- Start the ESB with sample configuration 150.
- Unzip the <acegi-home>/acegi-security-samples-tutorial-1.0.6.war file. For the purpose of testing, copy the applicationContext-acegi-security.xml and users.properties files from <acegi-home>/acegi-security-samples-tutorial-1.0.6/WEB-INF/ directory into the <esb-home> directory. Edit userDetailsService in applicationContext-acegi-security.xml file to be as follows. (If you already have an Acegi store, you can skip this step but remeber to enter the correct values for the Synapse configuration in the next step).
- Edit the configuration to have a <inSequence> as in the following XML snippet. For the
AuthenticationProviderBeanMappingFile parameter, the relative file path must be given:
- Go to <esb-home>/samples/axis2Server. Start the sample Axis2 server..
- Go to <esb-home>/authentication-mediator/auth-client. Run the client with username/password.
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>
<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
Implementing the AuthenticationMediator
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.
Conclusion
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.
Author
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 |
- Login or register to post comments
- Printer friendly version
- 783 reads










