Servlet authentication woes

I’ve always been surprised by how the servlet spec writers managed to make my life unnecessarily harder in a number of occasions, and today, despite an ongoing flu, I have been bitten (again) by what appears to be a stupid yet blocking problem in implementing what seemed to be an easy task.

We are writing an application exposing a REST interface and a web based administration. We need to protect access to both of them, of course with different sets of users. Now, if there is something that I hate with a passion, is writing custom authentication code in a web application. Why on earth should I bother with cookies, sessions, redirects and all the fuss when security is clearly a protocol concern and it’s much better managed by the application server? Programmatic security kills SSO, is a PITA to maintain, needs to be reimplemented basically on every deployment and, overall, tends to suck badly (is there anything worse that an HTTP 200/302 when a resource is protected?).

Declarative security is my favourite way to go for a number of reasons:

  • every application server comes with a full set of different AAA backends, be it flat files, databases or LDAP servers. Any decent “enterprise” environment has some kind of integration with corporate security layers, and such integration comes at the application server level;
  • security policies can be set by system administrators using server-wide settings and with no need to learn a different tool (yes, I’ve been a sysadmin in a past life, could you tell?);
  • a tested application server security code can be trusted (and audited) much better than custom written code;
  • custom application code needs sessions, adding unnecessary overhead to the application server;
  • I’m a lazy butt. Why should I bother writing code that goes around reinventing wheels?

This said, today I started to wrestle with my web.xml and, surprise surprise, I came to understand that either I’m a complete idiot (and I’d be happy to find out), or the servlet specs are horribly wrong. If you remember, a few lines above I wrote that I had to support two different set of users, which can be easily done using roles. I have another requirement though: users want to see a fancy FORM based authentication (which, to my surprise, uses the damn cookie&session paradigm), whereas applications accessing the REST interface could certainly deal much better with BASIC or DIGEST auth.

Well, despite the fact that the login-config tag does accept an optional realm attribute, which seems to suggest that at a certain point someone pointed out how there might be an exotic case for a web application to host more than one protected area, the actual servlet specification seem to state that only ONE login-config element per web.xml is actually allowed. This means, basically, that whatever is configuredas the authentication method, it will be global to the whole application space, with no chance to override it apart from entering the programmatic security hell.

Bottom line, I’m stuck with this stupid issue, cursing the servlet specifications and trying to come up with a solution with will most probably need to use programmatic security. Unless the lazyweb comes to the rescue, of course.

Comments

comments

6 thoughts on “Servlet authentication woes”

  1. One possibility would be to place a custom servlet filter that wraps requests to the REST URLs and implements BASIC auth by hand (shouldn’t be hard).

    Another is to put an Apache httpd with mod_proxy in front and protect the REST URLs with Apache, leaving form-based auth to the servlet container.

  2. We went for the ‘duplicate webapp’ solution, its just a change to the build scripts. In fact if you have an XML/SOAP client, its better to have a separate webapp, or you’ll get unwanted HTML responses for errors.

    My gripe with this stuff is more that it is still *impossible* to portably have container-managed SSO across servers going by the servlet spec. (ie things like CAS, Athens – the spec allows for SSO on a single container). This leaves the container not knowing the security context of servlet requests and a lot of work needs done to help integrate properly with other parts of the J2EE stack (where acegi comes in).

    If apps could just declare ‘CONTAINER-MANAGED’ authentication and leave the details until deployment time, life would be much better (wouldn’t solve your problem though).

  3. I had the same problem and ended using BASIC auth for webservices (Hessian) and custom code for Form Authentication (admin app).
    I’ve also tried the SecurityFilter solution, trying to mix it with a Tomcat Realm at the Container level but didn’t work, unfortunately SecurityFilter (even the latest 2.0) needs to create its own instance of a Tomcat Realm object and it seems to work only for JDBCRealm, not even DataSourceRealm, that needs a reference to the container to access the JNDI context.
    But after this experience now I would use two different webapp, maybe sharing some code in CATALINA_HOME/shared, at least it makes sense that sessions for webservices users and web users are separated… maybe the servlet spec was right?
    Looks like stuff for some next JUG meeting 😉

  4. I had exactly the same problem, but managed to solve it with securityfilter (http://securityfilter.sourceforge.net/) I configured my web xml to run two instances of the filter with different configuration and then map the filters to differend url-patterns.
    Could that be a solution?

    Lars

Comments are closed.