Google Site Search

Google
 

Wednesday, November 7, 2007

Tip 11: Refresh Security Roles within a Tomcat Session

This long outstanding JIRA issue has been on my mind for a long long time now. The blocking thing for this was always the performance aspect associated with the security roles refresh in the middle of the http session.

The JIRA issue is this:
Need a way to support refreshing security roles within a session

Well, no solution yet for the JBoss 4.2.x series (and for 3.2.x and 4.0.x series also).

But the simplest workaround is to do a full security check (authentication and authorization with each call). This was done anyway by default, except that the Jaas Security Cache in JBoss was pulling the subject out of the cache rather than go through the Jaas authentication process with each call.

Given this, there are 2 steps to perform for the workaround:
1) Disable Jaas Security Cache
- Go to conf/jboss-service.xml and set the "DefaultCacheTimeout" to zero.

<mbean
code="org.jboss.security.plugins.JaasSecurityManagerService"
name="jboss.security:service=JaasSecurityManager">
...
<attribute name="DefaultCacheTimeout">0</attribute>


2) Disable Tomcat caching the principal as part of the session.
NOTE: This is a very important step. If you do not follow it correctly, you will see bad behavior and may lose hair.

Now you will need to figure out, what kind of auth method is used in your web application. How will you know? Look in the web.xml of your web application.

If it is BASIC as in,


<login-config>
<auth-method>BASIC</auth-method>
<realm-name>JBoss JMX Console</realm-name>
</login-config>


then do the following, in your WEB-INF of your web application, create a context.xml with the following information(remember
org.apache.catalina.authenticator.BasicAuthenticator):

<Context>
<Valve
className="org.apache.catalina.authenticator.BasicAuthenticator"
cache="false" />
</Context>


If it is FORM based login, as in

<login-config>
<auth-method>FORM</auth-method>
<realm-name>Tomcat Application</realm-name>
<form-login-config>
<form-login-page>/jsp/login.jsp</form-login-page>
<form-error-page>/jsp/loginerror.jsp</form-error-page>
</form-login-config>
</login-config>

then do the following, in your WEB-INF of your web application, create a context.xml with the following information(remember,
org.apache.catalina.authenticator.FormAuthenticator):


<Context>
<Valve
className="org.apache.catalina.authenticator.FormAuthenticator"
cache="false" />
</Context>


Similarly, if it is Client-cert, just replace FormAuthenticator with SSLAuthenticator.

Inform me if this does not work. I have done some basic testing with BASIC type of auth.

Motivation for the workaround:
For the web layer, the container security checks happen at the time of the user login. Once his auth and authorization checks are done, they are valid for the entire session. Now for custom requirements such as the roles being refreshed at arbitrary times during the session, there is no decent way of solving it other than
the aforementioned work around. The complexity does arise due to the way tomcat caches principal during the session.

1 comment:

nalddon said...

To begin,

this is the single and only corner in the www where I found at list the way to my solution and thank you very much for that.

The thing is, that I didn' t get it to work yet. You see, I deploy my app in tomcat 6 and I don' t use JBoss at all. So, what happens (after adding the valve element in context.xml) is that the UserPrincipal in the request is nullified, resulting to my page having no idea of which user it is! I guess what I still need to do is programmatically make a new j_security_check (?????). Do you happen to know the solution in my occasion?

Thanks anyway cause the last 3 days I thought I was from another planet.