Authentication Without the Form

The nice thing about form-based authentication is that it allows a simple way for an application to let the container handle common security tasks. The bad thing about it is that, well, you need an HTML form. For a "Rich Internet Application" (RIA) that doesn't normally use JSPs or HTML pages, this means tacking on some extra files that don't have a natural fit in your application: the JSPs and/or HTML pages themselves, along with a deployment descriptor to specify the security settings. With the new features of the Servlet 3.0 spec, form-based login is no longer needed. Instead, your application can collect username and password credentials however you'd like and simply pass them to the container during an HTTP request. (Logout is equally simple.)

With form-based authentication, you would normally select some set of URLs and protect them with a security constraint. To access these URLs, a user would have to be authenticated and properly authorized. In some RIAs, this pattern no longer makes sense. For example, there may be few (or one) URL for the entire application. Instead, you can apply declarative security at the EJB level to protect any sensitive information (remember that EJBs can be used within a war file in Java EE 6!)

In this blog, I'll show an example of user authentication that doesn't involve an HTML form (or any JSP or HTML pages). There is a simple session bean acting as our back end service, and one of the two "hello world" style methods can only be called by a caller in the 'ADMIN' role:

    @RolesAllowed("ADMIN")
    public String getAdminMessage() {
        return String.format("Hello again '%s', it's great to see you!",
            context.getCallerPrincipal().getName());
    }

While the entire application is available in this zip file, you can see the full session bean, copiously commented, here. The rest of the sample application is simple as well: there is a main, servlet-based application class using Vaadin that includes these two panels (the authentication panel has been broken out into a separate class). See the code in the authentication panel for the full details, but the code to log the user in is this simple:

    String name = // retrieved from web UI
    String pass = // retrieved from web UI
    
    // exception handling omitted here
    // app.getRequest() returns the current HttpServletRequest
    app.getRequest().login(name, pass);

Logging the user out, of course, uses the logout() method instead. Here is the full user interface:

The ee6auth example application

In the "Actions" panel, there are two buttons that call a method in the EJB when clicked. The top button can be used whether there is an authenticated user or not. The other will result in an exception if there is not an authenticated user who is authorized to make the call (a user in the 'ADMIN' role). The exception is popped up in the browser to let you know what happened. Please see the three class files for comments describing the details of each part of the application. Note: while we're keeping this example simple, remember to use SSL any time you're dealing with user credentials such as passwords. The only other file in the application is a deployment descriptor that maps users in the authentication realm to the proper application role.

Before using the application, you need to add some users in the proper group in the default realm in the application server. The group we're using is 'ADMIN_GROUP,' but you can use any group you'd like as long as the mapping is correct in sun-web.xml. To help get you set up, here is a screen cast that shows how to create users in the default realm in GlassFish. We're keeping this very simple by using the file realm in the server, but you could use any realm you'd like. To use a realm other than the default one, add a web.xml file to specify it:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <login-config>
        <realm-name>your-realm-here</realm-name>
    </login-config>
</web-app>

Important note: because of this issue, you need a post-3.0 build of GlassFish v3. You can download a promoted build of v3.0.1 here -- to install, just unzip it. One more time, here's a link to the example application.

To build the application, you can use any IDE that supports Maven or use the command 'mvn clean package' to build it directly. Then deploy with the admin console or use this command (the --force option is only necessary on the 2nd or later deployment):

asadmin deploy --force --contextroot /ee6a <somepath>/ee6auth/target/ee6auth.war

Then you can access the application in a browser with http://localhost:8080/ee6a/. Let me know if you have any problems with the example. For any general questions, you'll get an answer more quickly at users@glassfish.dev.java.net.

I'd like to give a big thanks to Petter Holmström from the Vaadin team for his help, especially the article Creating Secure Vaadin Applications Using JEE6 that explains the steps needed to use regular form-based authentication (and a lot more) with a Rich Internet App such as Vaadin.

Comments:

Post a Comment:
Comments are closed for this entry.
About

Whatever part of GlassFish or the Java EE world that catches my attention. (Also, go Red Sox.)

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today