Wednesday, January 23, 2008

Intro to JBoss Seam Security, Part 1 - Authentication

Recently, I mentioned how I had just started working with the JBoss Seam application framework. The more I have worked with it, the more impressed I have become at how it makes things that are typically difficult using standard Java EE much simpler and more streamlined. One of the areas in which Seam really shines is security. While Java EE defines JAAS for use in securing applications, it is left up to the developer to ingrain this security down to each facet of the application. With Seam, it is easy to define security constraints at all levels of an application, simply through using annotations. In addition, the complexity of authenticating users with JAAS is reduced through Seam's authenticator mechanism. This article will give an introduction to Seam authentication, and show how to write your own custom authenticator.

Seam's authenticator construct hides the complexity of managing a JAAS configuration, and allows you to implement authentication how you see fit. Perhaps your organization relies on a simple username/password combination for authenticating user accounts in LDAP. Maybe you use a SecureID token, and the accounts are stored in a SQL database. By writing your own authenticator class, or making use of publicly available ones, you can control the way authentication is done in your organization.

To get started with your own authenticator, you must first declare it in the components.xml file. This file manages much of the configuration for Seam. To add your authenticator, you simply define the class and method that will be used for authentication. For example:

<components xmlns="http://jboss.com/products/seam/components"
xmlns:core="http://jboss.com/products/seam/core"
xmlns:security="http://jboss.com/products/seam/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=
"http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.0.xsd
http://jboss.com/products/seam/security http://jboss.com/products/seam/security-2.0.xsd">

<security:identity method="#{authenticator.authenticate}">

</components>


You'll notice the #{} syntax used here. This is JBoss' expression language pointing to a class with the instance name of authenticator, where the authenticate method will be used to login a user. Now that we have declared an authenticator to Seam, we're ready to implement it. Our example will be quite simple. If the user enters a username of admin, with a password of password, they will be authenticated successfully. In addition, we will assign them to the role of admin, so that they can perform some sort of administrative function within our application. The implementation of our authenticator would look like this:

@Name("authenticator")
public class Authenticator {

private static final String valid_user = "admin";
private static final String valid_password = "password";

public boolean authenticate() {
String username = Identity.instance().getUsername();
String password = Identity.instance().getPassword();

if((username.equals(valid_user)) && (password.equals(valid_password))) {
return true;
}

return false;
}

}
Our example is rather trivial. However, it gives a slight glimpse into how Seam authentication works. The first thing that you should notice is the @Name annotation. This annotation prompts Seam to create a bean with the name specified in the annotation. In this case, the name is authenticator, which is how we arrive at the value specified in our components.xml file. Our authenticate method will return true if authentication was successful, and false otherwise.

So how does the authenticate method get the username and password? This is done via the Identity class. The standard Identity class that comes with Seam is quite extensive, but basically provides support for a username/password combination. It is possible to subclass Identity, however, to support whatever authentication mechanisms you may need. You could implement code to support getting a SecureID token value from a user, or a SPNEGO ticket. All that is needed to make use of the Identity subclass is to add the following annotations to your implementation:

@Name("org.jboss.seam.security.identity")
@Scope(SESSION)
@Install(precedence = APPLICATION)
@BypassInterceptors
@Startup
public class MyCustomIdentity extends Identity
{ ... }

Your custom Identity subclass is now ready for use.

Now that we have our authentication classes in place, we are ready to create our login form. This is trivial to create using Seam, particularly because of Seam's use of the JBoss expression language in forms. Our login form fragment would look like the following:


<div>
<h:outputlabel for="name" value="Username">
<h:inputtext id="name" value="#{identity.username}">
</div>

<div>
<h:outputlabel for="password" value="Password">
<h:inputsecret id="password" value="#{identity.password}">
</div>

<div>
<h:commandbutton value="Login" action="#{identity.login}">
</div>


That's all there is to it. You are now ready to authenticate users via your own custom login form and authenticator. While this is an introduction to the simplified form of authentication in Seam, it should give you a good foundation to learn and explore on your own.

Next time, we will look at how authentication is used throughout an application, not just at the entry point.

3 comments:

Hugo said...

Very nice nugget of information!

mojavelinux said...

Good tutorial. However, I want to point out that there is nothing JBoss-specific about the #{authenticator.authenticate} syntax. That is standard EL, in this case a method binding expression. JBoss does have extensions to the EL, but this is not one of them.

WeiLing said...

Hi,

I have read this and thought this is very good.

I am the community content coordinator for DZone and it would be an honor if you would share this article with our readers by allowing us to repost this article on our website at www.dzone.com.

Please let me know, I look forward to hearing back from you and reading more on your blog in the future.

Thanks,

Wei Ling Chen

Community Content Coordinator, DZone, Inc.

Phone: 919-678-0300 ext. 105

Email: weiling@dzone.com

AOL/MSN/Jabber: weiling@dzone.com