I've been building some RESTful application recently and as part of that wanted to look at authentication techniques. Traditional web application will typically use form-based authentication - where the user enters their credentials on a web page and then they are authenticated for whole session. RESTful apps can use this approach, however it is different for every application and relies on server-side state, which is not ideal for scalability, and has the potential for session hi-jacking.
The alternative for RESTful apps is to provide authentication credentials with every call. Many applications have application specific means of providing credentials, which I've implemented in the past, however this time I've been particularly interested in looking at more general solutions.
HTTP supports two standard means of providing authentication information, via the 'Authorization' header: Basic and Digest. The Authorization header is extensible and the Atom community have produced an extension based on the WS-Security specification: WSSE. This has gained quite a lot of acceptance including in the REST community, and so I wanted to see how difficult it would be to implement it in my own application. The answer was that it was pretty straight-forward to get simple mechanism working.
For background on WSSE, read Mark Pilgrim's article on it.
To implement WSSE authentication using Spring Security, I took a similar approach to Spring Security's existing Digest authentication mechanism. I created a WSSE Authentication Filter and a WSSE Authentication Entry Point. The Filter is responsible for parsing the Authorization header and checking the password digest that has been provided by the client against the one it expects given the user's actual password. The Entry Point is responsible for handling failures and returning 401 Unauthorized response with the appropriate WWW-Authenticate header specifying that WSSE is required.
Like the built-in DigestAuthenticationFilter, my WSSEAuthenticationFilter requires access to the user's password in plain-text. This is the main disadvantage of this technique.
Then the final step was to update my configuration to use my own filter and entry point instead of the digest filter and entry point.
At present I haven't implemented a mechanism to check for replay attacks by caching the nonce or checking the created timestamp. That is something that I'll look at shortly.
My next challenge however is to get WSSE authentication working for a GWT client.