Problems with JAAS authentication and Struts/EJB
kristiane Sep 5, 2004 3:21 PMHi,
I have been trying to implement authentication using JAAS in my Struts based application running on JBoss.
The application consists of some servlets implemented using Struts, and some session EJB implementing the business logic. Both the
servlets and EJBs are secured and need a authenticated user to access them.
The authentication works I that the user is authenticated and the Principal set on logon. But then when I try to make an EJB call
on the next Struts action, I get Principal=null exception:
20:15:30,188 ERROR [SecurityInterceptor] Authentication exception, principal=null
20:15:30,198 ERROR [LogInterceptor] EJBException, causedBy:
java.lang.SecurityException: Authentication exception, principal=null
It seems that the Principal and authentication information is lost somewhere between the login action, where the authentication
occurs, and the next action, where a EJB call is done...
I have been using the http://www.javaworld.com/javaforums/showflat.php?Cat=2&Board=JavaSecurity&Number=2500&page=0&view=collapsed&sb=5&o=&fpart=1> Complete configuration of JAAS on JBOSS and STRUTS
The login code looks like this:
public ActionForward execute(...) { // Some code removed for simplicity SecurityAssociationHandler handler = new SecurityAssociationHandler(); SimplePrincipal user = new SimplePrincipal(j_username); handler.setSecurityInfo(user, new String(j_password)); LoginContext loginContext = new LoginContext("notatbase", (CallbackHandler)handler); loginContext.login(); Subject subject = loginContext.getSubject(); session.setAttribute("subject", subject);
Now I check that the Subject is indeed set, and that I can access the EJB layer with the following code
logger.debug("Subject: "+SecurityAssociation.getSubject().toString()); UserAdminHome userhome = (UserAdminHome)EjbLookupUtility.lookupHome(UserAdminHome.JNDI_NAME); UserAdminRemote userbean = userhome.create(); userbean.getCurrentUserDTO();
This code works. The Subject is set, and the EJB call is successful. The following is printed out:
20:15:29,847 DEBUG [LoginAction] Subject: Subject:
Principal: ke@objectnet.no
Principal: Roles(members:Member)
20:15:29,877 DEBUG [UserAdminEJB] Using caller ke@objectnet.no as current user
But on the next (Struts) action when the following code is executed the EJB call fails with the above exception.
public ActionForward execute(...) { // Some code removed for simplicity if (SecurityAssociation.getSubject() != null) logger.debug("Subject: "+SecurityAssociation.getSubject().toString()); else logger.debug("Subject is null"); UserAdminHome userhome = (UserAdminHome)EjbLookupUtility.lookupHome(UserAdminHome.JNDI_NAME); UserAdminRemote userbean = userhome.create(); userbean.getCurrentUserDTO();
Here the Subject is null, and the userhome.create() call will throw the following execption:
20:15:30,188 DEBUG [SystemInfoAction] Subject is null
20:15:30,188 ERROR [SecurityInterceptor] Authentication exception, principal=null
20:15:30,198 ERROR [LogInterceptor] EJBException, causedBy:
java.lang.SecurityException: Authentication exception, principal=null
What am I doing wrong here? Is there a bug in JBoss?
I have used many days on this problem and have all but given up. If sombody have any ideas, clues or downright solutions,
please let me know...
Regards,
- Chris
More details:
I am using JBoss 3.2.4 with Tomcat 5.0. I have also used JBoss 3.2.5 with the same result. To give a more complete picture of my
implementation I have attached the files necesary to implement the security features in JBoss.
The application is packed as a EAR with a WAR for the servlets and a JAR for the EJBs. The deployment descriptors looks like the
following:
In jboss.xml and jboss-web.xml I have added the following line to secure the servlets and EJBs:
<security-domain>java:/jaas/notatbase</security-domain>
In the login-config.xml I have added the following security domain:
<application-policy name="notatbase"> <authentication> <login-module code="org.jboss.security.ClientLoginModule" flag="required" /> <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required"> <module-option name="managedConnectionFactoryName">jboss.jca:service=LocalTxCM,name=NotatbaseDS</module-option> <module-option name="dsJndiName">java:/NotatbaseDS</module-option> <module-option name="principalsQuery">Select passwd as Password from users where email=?</module-option> <module-option name="rolesQuery">select 'Member' as Role, 'Roles' as RoleGroup from users where email=?</module-option> </login-module> </authentication> </application-policy>
The ejb-jar.xml is a very long file, generated by XDoclet. This is only the most interesting part:
<security-role> <description>[CDATA[description not supported yet by ejbdoclet]]</description> <role-name>Member</role-name> </security-role> <method-permission > <description>[CDATA[description not supported yet by ejbdoclet]]</description> <role-name>Member</role-name> <method > <description>[CDATA[]]</description> <ejb-name>UserAdmin</ejb-name> <method-intf>Home</method-intf> <method-name>create</method-name> <method-params> </method-params> </method> </method-permission> <method-permission > <description>[CDATA[description not supported yet by ejbdoclet]]</description> <role-name>Member</role-name> <method > <description>[CDATA[Gets the UserDTO for the current user.]]</description> <ejb-name>UserAdmin</ejb-name> <method-intf>Remote</method-intf> <method-name>getCurrentUserDTO</method-name> <method-params> </method-params> </method> </method-permission>
The web.xml:
<!-- notatbase, fails in auth-constraint, does not recognize role, and is therefore calling <form-login-page> anyway --> <security-constraint> <web-resource-collection> <web-resource-name>notatbase</web-resource-name> <description>Security constraint for all resources</description> <url-pattern>*.do</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <!-- the role which can access these resources <auth-constraint> <role-name>Member</role-name> </auth-constraint> --> <user-data-constraint> <description>no description</description> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint> </security-constraint> <login-config> <auth-method>FORM</auth-method> <form-login-config> <form-login-page>/login.do</form-login-page> <form-error-page>/logout.do</form-error-page> </form-login-config> </login-config> <security-role> <description>A user allowed to invoke Member methods</description> <role-name>Member</role-name> </security-role>