I did that part programmatically:
public AppConfigurationEntry[] getAppConfigurationEntry( String
applicationName )
{
if( m_appConfig == null ) {
if( applicationName == null ) {
throw new NullPointerException( "Could not retrieve security
configuration. "
+ "Application name was not
specified." );
}
if( m_dbkey == null ) {
throw new NullPointerException( "The application, \"" +
applicationName + "\", "
+ "does not have a security
configuration entry "
+ "defined in " +
this.getClass().getName() + "." );
}
String[] parms = { applicationName };
String sql = MessageFormat.format( SECURITY_CONFIGURATION_SQL,
parms );
Connection dbConn = null;
Statement stmt = null;
ResultSet rs = null;
ArrayList modules = new ArrayList();
try {
dbConn = ConnectionFactory.getConnection( m_dbkey );
stmt = dbConn.createStatement();
rs = stmt.executeQuery( sql );
while( rs.next() ) {
String loginClass = rs.getString( "LoginModuleClass" );
String cFlag = rs.getString( "ControlFlag" );
DEBUG_MODE = rs.getBoolean( "DebugFlag" );
HashMap options = new HashMap();
options.put( "debug", String.valueOf( DEBUG_MODE ) );
AppConfigurationEntry.LoginModuleControlFlag controlFlag =
resolveControlFlag( cFlag );
AppConfigurationEntry appEntry = new AppConfigurationEntry(
loginClass,
controlFlag,
options );
modules.add( appEntry );
m_appConfig = (AppConfigurationEntry[])modules.toArray(
new
AppConfigurationEntry[modules.size()] );
}
} catch( SQLException e ) {
Logger.log( Logger.ERROR, getClass() +
".getAppConfigurationEntry", e );
return null;
} catch( KException e ) {
Logger.log( Logger.ERROR, getClass() +
".getAppConfigurationEntry", e );
return null;
} finally {
SQLUtil.close( dbConn, stmt, rs );
rs = null;
stmt = null;
dbConn = null;
}
}
return m_appConfig;
}
The hook into the login module is created when the context listener for the
web-app is initialized. The initialization parameters come from the database,
which is what I was referring to, as opposed to a policy file.
What I find strange is that the authentication piece works perfectly. Tomcat
calls my login module, does it's work and build a Subject that is consistent
with what I expect. The question is, why am I able to call
request.isUserInRole("landscape") when Tomcat's internal call to the roles in
my Subject uses something else?
The Tomcat code that is failing for my auth check is
(http://kickjava.com/src/org/apache/catalina/realm/RealmBase.java.htm):
} else if(!denyfromall) {
787
788 for (int j = 0; j < roles.length; j++) {
789 if (hasRole(principal, roles[j]))
790 status = true;
791 if( log.isDebugEnabled() )
792 log.debug( "No role found: " + roles[j]);
793 }
794 }
public boolean hasRole(Principal JavaDoc principal, String JavaDoc role) {
851
852 // Should be overriten in JAASRealm - to avoid pretty inefficient
conversions
853 if ((principal == null) || (role == null) ||
854 !(principal instanceof GenericPrincipal))
855 return (false);
856
857 GenericPrincipal gp = (GenericPrincipal) principal;
858 if (!(gp.getRealm() == this)) {
859 if(log.isDebugEnabled())
860 log.debug("Different realm " + this + " " +
gp.getRealm());// return (false);
861 }
862 boolean result = gp.hasRole(role);
863 if (log.isDebugEnabled()) {
864 String JavaDoc name = principal.getName();
865 if (result)
866 log.debug(sm.getString("realmBase.hasRoleSuccess", name,
role));
867 else
868 log.debug(sm.getString("realmBase.hasRoleFailure", name,
role));
869 }
870 return (result);
871
872 }
So, what works in the one case, i.e., request.isUserInRole("landscape"), fails
when using Tomcat's role checking, i.e., hasRole(principal, roles[j]). So,
Tomcat isn't treating my Principal as a role, which its own messages says that
it is:
org.apache.catalina.realm.JAASRealm - Checking Principal "landscape"
[com.kaleidescape.logdb.webapp.security.auth.UserGroupPrincipal]
2008-05-05 14:02:53,665 10885193 [http-9808-Processor24] DEBUG
org.apache.catalina.realm.JAASRealm - Adding role Principal "landscape" to
this user Principal's roles
If my JAAS realm wasn't properly configured, I can't see how I'd get all the
way to the JAASRealm hasRole() method. Also, my own implementation was a check
against Tomcat. I called all the same code that Tomcat calls, the only
difference is, I can access my Subject when I call my own code, whereas Tomcat
sticks the Subject that it creates into an InternalSession, which isn't
accessible outside of the Catalina code base.
Since my UserGroupPrincipal implements Principal, it is castable to
GenericPrincipal. I am not in a different realm, since the debug message about
that isn't fired. So it comes down to how the Catalina code base is
interpreting gp.hasRole(role). Haven't tracked down that code yet but I will.
At least, that's how it appears to me, but I am open to any fixes. :)
Robin.
-----Original Message-----
From: Caldarale, Charles R [mailto:[EMAIL PROTECTED]
Sent: Monday, May 05, 2008 2:12 PM
To: Tomcat Users List
Subject: RE: JAAS authenticated user fails authorization check
> From: Robin Coe [mailto:[EMAIL PROTECTED]
> Subject: RE: JAAS authenticated user fails authorization check
It appears that the problem is you haven't fully configured the JAAS
environment. See below for details.
> I tested the implementation of isUserInRole() by wild-carding
> the role, to force Tomcat to authenticate but not authorize:
It doesn't work that way. A <role-name> of * means that authorization
is allowed for any of the listed <security-role>s, not that
authorization is ignored.
> As a side note, I wrote my own implementation of the login
> process, using a servlet to hook into my login module, thus
> avoiding the declarative security.
Why did you choose to reinvent the wheel here? Use the declarative
security - it's much easier.
> <Context>
> <Realm className="org.apache.catalina.realm.JAASRealm"
> appName="landscape"
The appName is not some arbitrary value; it needs to point to the entry
in the file pointed to by the java.security.auth.login.config system
property (see below).
> The JAAS module is not based on a security policy file, I
> wrote it to work from a database.
Not relevant to the discussion. You still have to tell Tomcat's
JAASRealm what your LoginModule class name is via the file pointed to by
the java.security.auth.login.config system property. For example,
here's ours:
-Djava.security.auth.login.config=conf/security/tomcatLogin.config
The conf/security/tomcatLogin.config file contains:
TomcatLogin {
com.unisys.os2200.security.TomcatLoginModule required;
};
Have you done that?
- Chuck
THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY
MATERIAL and is thus for use only by the intended recipient. If you
received this in error, please contact the sender and delete the e-mail
and its attachments from all computers.
---------------------------------------------------------------------
To start a new topic, e-mail: [email protected]
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To start a new topic, e-mail: [email protected]
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]