Hi everyone,
I'd like to post a few quick thoughts about authentication strategies
for JSPWiki 3.0. When I say "authentication," I mean the process by
which a user logs into JSPWiki. I don't mean "authorization" -- what a
user can do once they log in.
Since 2.4, we've used a captive JAAS (the Java Authentication and
Authorization Service) to log in users. That means we tell the JVM
where to find our login configuration, and then we execute the "login
stack" as its configured. "Authentication" via JAAS happens twice:
once when the user's HTTP request is received (so that we can grab any
container-managed credentials) and (optionally) a second time if we
authenticate against JSPWiki's user database, using Login.jsp. It's a
"captive" JAAS system in the sense that we wire it up and execute it
independently from the container.
I suppose the details of exactly what we do don't matter nearly as
much as the technologies. In both cases, we're relying on JAAS to look
up a LoginConfiguration and execute it.
Of course, the current strategy causes problems because it means
sometimes we need to wire up certain containers in special ways (e.g.,
JBoss). And it's sometimes a deployment hassle. From the deployer
standpoint, it's probably not very obvious what the jspwiki.jaas
config file we use does.
On the plus side, using standard JAAS LoginModules for authentication
is a good thing because it's a fairly well-defined interface, and if
developers want to plug in their own LoginModules, it's just a matter
of configuring the JAAS login config file and putting the custom
module on the classpath. So that's good. Also, we get to say that
we're doing things in a "Java standard" way.
But I confess I've been re-thinking the authentication strategy
lately, largely because of some of the deployment hassles people have
experienced. To solve them properly, there's really only two ways to go:
1) Build a "clean-room" implementation of LoginContext that would re-
implement the JAAS login stack, but do it in a way that could be
instantiated per-webapp, rather than JVM-wide. That would allow us to
re-use all of our LoginModules and the JAAS config file, and is the
least invasive alternative. Precedent for this approach exists. This
is totally analogous to how we've handled the security policy
configuration issues with jspwiki.policy: the "local security policy"
scheme is, in essence, a clean-room (and portable) re-write of the
Java security Policy class. It doesn't require any special JVM config
to work, and it's the policy files it reads are line-for-line
compatible with the standard J2SE policy files.
It's a neat approach, but not the only one. Which brings me to the
second approach:
2) Get rid of significant chunks of the JAAS login scheme we use, and
do something a little simpler. I'm thinking, in particular, of putting
in a very lightweight servlet filter that wraps the incoming
HttpServletRequest. It would delegate to WikiSession for
getUserPrincipal() and getRemoteUser(), and delegate to WikiSession
and AuthorizationManager for isUserInRole(). This is similar to how,
for example, ACEGI does things. For configuring custom authentication,
we'd simply put in a single line that points to ONE LoginModule to
execute. As it happens, that's what we do today in the "jswiki-custom"
configuration -- the config says, "execute [just] the
UserDatabaseLoginModule." Today, we specify the
UserDatabaseLoginModule class name in jspwiki.jaas -- all we'd be
doing is moving it to jspwiki.properties.
I'm strongly leaning towards number 2. Benefits would include:
- No more fooling around with the java.security.auth.login.config
system property (meaning: no more container dependencies)
- We'd throw away jspwiki.jaas
- isUserInRole() would become a lot more useful to JSPs because
callers could inquire about JSPWiki roles, and even about wiki group
membership
- "Probably" better compatibility with schemes like ACEGI
- We could slightly reduce the security privileges JSPWiki requires to
run under a security manager (hypothetically)
Here's what wouldn't change:
- We'd keep the JAAS UserDatabaseLoginModule class for custom
authentication (and allow it to be swapped out in favor of any
LoginModule, by changing a line in jspwiki.properties)
- We'd keep the cookie authentication technique (as much as it pains
me to do so) and the cookie-sniffing technique for "asserted" names
- WikiSession, with its embedded Subject and Principals, would still
exist and be associated with the HttpSession
- Public API for WikiSession, SessionMonitor, etc. wouldn't change
- Java security policies (and the related APIs in
AuthorizationManager) would stay exactly the same
I don't see too many downsides to this, frankly. Really, this is more
about the "plumbing" than stuff that would be visible to users,
deployers or developers not named Andrew.
Thoughts? There's nothing that says we need to wait until 3.0. If
everyone likes this idea, we could do it in 2.8.
Andrew