« Maven & SVN Plugins... | Main | Eclipse Galileo -... »

Glassfish & OpenID - JSR-196 with OpenID4Java

Today I implemented a new ServerAuthModule based on JSR-196 using the OpenID4Java library. OpenID4Java is a open source library supporting the Client side authentication process to login a user with an OpenID.

OpenID is an open standard that allows a User to sign into web sites through a single URL (a single digital identity). This URL can be a personal home page, a blog or a web service (e.g from a OpenID Provider like myopenid, Google or yahoo.com) that the user is already using. In any case the user must register only once with his OpenID service provider and therefore he need only one password. Another advantage of using OpenID in your web application is the exemption of hosting and managing user accounts and password informations. You can read more about the details on openid.net.

Please note that I have started a project site to provide a platform for further discussion and development. You will also find souce code from the OpenID-JSR-196 Login Module and a wiki page on the project site:
http://code.google.com/p/openid4java-jsr196/

You are welcome to join this project.


Using JSR-196 and OpenID

There are different solutions available to enable a Web Application to login users with there OpenID account. One of the most auspicious mechanisms to integrate OpenID in JEE Applications is the jsr-196. This authentication service allows web containers to use different login modules - like an external openid provider. JSR-196 is part of Glassfish Server so a Login Mechanism based on the jsr-196 is very easy to use in a JEE or Web application. Ron Monzillo who is the specification lead gives a good overview about the jsr-192 on his blog  "concepts behind JRS-196".

How to Install the OpenID4JavaAuthModule

The OpenID4JavaAuthModule I have written is easy to install. To enable your JEE Web application for OpenID you need a Server plattform supporting JSR-196. The following section will describe the installation steps for a Glassfish Application Server. Glassfish supports JSR-196. But there may be also other web containers supporting JSR-196.

To install the OpenID4Java AuthModule you first need to download the following parts:

Copy the imixs-openid-0.0.2-SNAPSHOT.jar into the Glassfish Lib folder

[GLASSFISHHOME]/lib/

Extract the the openid4java zip archive and copy the following jars into your Glassfish Domain lib/ext/ folder.

  • openid4java-0.9.5.jar
  • commons-codec-1.3.jar
  • commons-httpclient-3.0.1.jar
  • commons-logging-1.03.jar 

The glassfish domain specific /lib folder is located on the following path:

[GLASSFISHHOME]/domains/domain1/lib/ext/

where domain1 is your prefered domain (domain1 is the default domain typical used).

Notice: The tree commons-* libraries are appache utilities which are used by openid4java.

Configuration of the OpenID4JavaAuthModule

Now you can configure the OpenID4JavaAuthModule using the GlassFish Admin Console following the next steps:

  1. Make sure the GlassFish Application Server is running. If it is not already running, you can start it using the following command:
       <GF_HOME>bin/asadmin start-domain domain1

    where <GF_HOME> is the directory where you installed GlassFish

  2. Open the GlassFish Admin Console by pointing your browser to the URL: http://localhost:4848/.
  3. Login to the Admin Console by entering your ID and password.
  4. Expand the Configuration node at the bottom of the left-hand pane.
  5. Navigate to the Security node, expand it, and click MessageSecurity.




  6. Under Message Security Configurations, either open the HttpServlet layer if it already exists, or create it if it doesn't exist by clicking the New button. Clicking the button opens the New Message Security Configuration window.
  7. If you can not see the HttpServlet node you need to create the layer

     Click the "New" button and you can than start to configure the new provider in one step. To do that:

    • Set the following in the New Message Security Configuration window:

      Provider Type: server
      Provider ID: OpenIDProvider
      Class Name: org.imixs.openid.openid4java.OpenID4JavaAuthModule

      Do not check the Default Provider: Enabled check box.

       

    • Click the OK button. This saves the settings and opens the Message Security Configurations window.
    • Click on HttpServlet in the Authentication Layer column.
    • Select the Providers tab. This opens the Provider Configuration window.
    • Select OpenIDProvider in the Provider ID column you just created. This opens the Edit Provider Configuration window.
    • Click the Save button to complete the configuration of the provider.

    If the HttpServlet layer already exists, you open first the provider list and add a new Provider:

    • Open the HttpServlet layer by selecting it in the Message Security Configurations window.
    • Select the Providers tab to open the Provider Configuration window.




    • Click the New button to open the New Provider Configuration window.
    • In the Provider Configuration area of the window, set the following:

      Provider Type: server
      Provider ID: OpenIDProvider
      Class Name: org.imixs.openid.openid4java.OpenID4JavaAuthModule

      Do not check the Default Provider: Enabled check box.

For the first configuration this is a little bit confusing as you need to create the HttpServlet Layer. But in general the hole configuration is very simple. 

Also note that the provider configuration utility also provides a dialog box that you can use to configure additional properties. We will use this properties to configure out OpenIDProvider for our applications.

Configure additional Properties

After adding the new OpenIDProvider like described before you can start using the provider in your web application. But there a also a few additional properties which can be configured for each provider instance. You can add these properties by using the box "additional properties at the end of you configuration page:

 

The different properties and there usage are described below:

assign.groups

This property is the most important one. It defines which group will be assigned to a user how has logged on with his OpenID. Typical this is a default group used in your web application. 

debug.stages

This property allows you define different debug stages. So you can follow the different phases during the logon process on the server log. Remove this property to turn the debug modus off to switch off debugging.

loginpage

Per default the login module will prompt the user with a simple login page where he can enter his OpenID. You can replace this default page with a individual page supported by your web application (similar to a form based authentication). I will discus this later.

(The other params - verfiymode and debug - shown in the screenshot are deprecated and can be left)

 

Configuration of your Web Application

Now I will explain how you can configure your web application to use openid as a login mechanism. If you have installed the OpenID Login module like described before this step is quiet easy. 

web.xml & sun-web.xml

The first thing what you should do is remove existing tag login-config like basic or form-based authentification configuration from the web.xml if available. Using JSR-196 you now only need the security-constraint configuration.

This is an example of the security-constraint seciton in my web.xml

....
<security-constraint>
<display-name>Access Manager Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>AUTHENTICATED_RESOURCE
</web-resource-name>
<url-pattern>/pages/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS
</role-name>
</auth-constraint>
</security-constraint>

<security-role>
<role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS
</role-name>
</security-role>
.....

Next you need to link your openid provider configured on glassfish admin client with you web application in the sun-web.xml. 

Therefor you need to add the attriubte "httpservlet-security-provider" with the name of your openid provider. The the following example of my sun-web.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">
<sun-web-app error-url="" httpservlet-security-provider="OpenIDProvider">

<context-root>/openidtestclient</context-root>

<security-role-mapping>
<role-name>org.imixs.ACCESSLEVEL.AUTHORACCESS</role-name>
<group-name>Author</group-name>
</security-role-mapping>

<class-loader delegate="true" />
<jsp-config>
<property name="keepgenerated" value="true">
<description>Keep a copy of the generated servlet class java
code.</description>
</property>
</jsp-config>
</sun-web-app>

That's it!

Now You will see a default login page if you try to login to your web application


Role Mapping

Notice that we mapped also our default group "Author" to a application specific role name. The group "Author" was configured in the OpenIDProvider property "assign.groups". So each user how have successful authenticated against his OpenID Provider will default to this group and the role  "org.imixs.ACCESSLEVEL.AUTHORACCESS". You can change this settings to the requirements of your application.

Login Form

If you did not specific a login form with the additional property "loginpage" the OpenID Login Module will answer an unautenticated request with an simple login form as shown above.

You can implement you own login form if you like and use this form as the default form for your openidProvider module. 

There for add the property "loginpage"  to your provider configuration and support a valid Page inside your application or a simple HTTP page located on a web server.

This is a simple example for a individual login form based on JSF :

	<form method="get"
action="#{facesContext.externalContext.requestContextPath}/openid_login">
<f:facet name="header">
<h:outputLabel value="#{global.login_title} " />
</f:facet>
<h:panelGrid columns="2">
<h:outputLabel value="#{global.username}:" />
<h:inputText id="openid_identifier" />

<h:inputHidden id="return_to"
value="#{loginMB.serverURI}#{facesContext.externalContext.requestContextPath}/pages/notes.jsf" />

</h:panelGrid>
<input type="submit" value="#{global.login}" />


<!-- BEGIN ID SELECTOR -->
<script type="text/javascript" id="__openidselector"
src="https://www.idselector.com/selector/e0ed3a269b77fa785de90aeaa20fa0f985746767"
charset="utf-8"></script>
<!-- END ID SELECTOR -->
<script type="text/javascript">
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
var pageTracker = _gat._getTracker("UA-3469303-6");
pageTracker._trackPageview();
</script>
</form>
 

Your form need to care about three things:

  1. The form action method need to point to the method path "/openid_login". This path indicates the OpenIDLogin Module to start an OpenID Login process.
  2. The users Input field to enter his OpenID URL should be named "openid_identifier". Make sure that the "name" and "ID" attribute are set to "openid_identifier"
  3. The form must support a hidden field "return_to" with points to a page where the user is redirected after login process succeed.

 

The ID Selector Script is just a funny script provided by http://www.idselector.com to support the user with a nice widget to simplify using openid.

Conclusion

You can see that using JSR-196 and OpenID4Java is a very comfortable way to support a new and easy to use login mechanism for web applications. For Internet applications openid opens you web site to millions of users. It is easy to use and you don't have to handle all the stuff with managing userids and passwords.

If you have any suggestions or comments let me know.

You can download the source file of my Implementation also from here.

I also want to thank the OpenID4Java Team for there work.

Please note that I have started a project site on googlecode to publish the sources and provide a platform to discuss and exchange experience. You are welcome to join this project.

 http://code.google.com/p/openid4java-jsr196/