users@jersey.java.net

Re: [Jersey] Security - Basic, Session, or Encrypted Key

From: Craig McClanahan <Craig.McClanahan_at_Sun.COM>
Date: Fri, 21 Aug 2009 09:35:56 -0700

Grover Blue wrote:
> I'm trying to add a security layer on top of my services. Below are
> the choices I think I have:
>
> Note: All would be required to run via HTTPS
I would suggest looking at Jersey filters to implement this. In
addition to performing authentication on every call for you (so that you
don't need to modify your resource methods), you an also choose to do
role-based authorization as well. There is a fully worked but
relatively simple example of this in the
"samples/atompub-contacts-server" example app.
>
> *Basic Authentication: *
> If I understand this correctly, the user of the WS sends a POST with a
> "Authorization Basic" header item. Browses cache the header line,
> sending it with each subsequent request. For users doing automation
> through code, they would have to include that with each request. So
> this method is effectively stateless.
Yes, you need to include the header in every request.
>
>
> *Session Key:*
> Even though the web server is stateless, it does run in a session,
> correct?
No, that is not correct. REST applications should not use sessions
because that violates the statelessness principle, and it also makes the
application much harder to scale.
> So, another approach would be to have the resource generate a
> session key and save it to a session variable. I just haven't been
> able to figure out how to access the session scope from a JAX-RS
> service. If I could, the key could be return it in the response to
> the user, which would be appended to the resource URL in subsquent
> requests, like such:
>
> /resources/myservice/someGetMethod/someParam1/someParam2?sessionKey=ASDGJASFGKNASDGKNAKFADSF
>
> The key would be pulled from the URL and validated against what is in
> session:
>
> @GET
> @Path("/someGetMethod/{param1}/{param2}")
> @Produces("application/xml")
> public String getXmlByExternalIp(@PathParam("param1") String param1,
> @PathParam("param2") long param2,
> @QueryParam(value="sessionKey")
> String sessionKey) {
>
> // validate seesionKey, and return an appropriate response
>
> }
>
>
>
As suggested above, you should stay away from sessions and use a filter
to perform the authentication for you.

> *Encrypted Key:*
> I recently discussed WS security with a friend, and he told me about
> the approach Splunk takes. Apparently, the user POSTs their
> username/passowrd to /auth/login, which returns a specially encrypted
> key. The key is generate using a private server side key, which takes
> into account the username, password, start/end time (why time? - it's
> not like the key is updated). With each subsequent request the key is
> included in the POST, and it's decrypted on the server using the
> decryption key. The username/password is then re-evaluated. I can't
> verify any of this, though.
>
> What are your thoughts on these approaches?
>

Some folks don't like HTTP Basic because it sends the credentials across
the wire in a lightly encoded (base 64) format that can be easily
deciphered -- unless you are using HTTPS, which you stated that you
are. Then, it's a reasonably secure approach. You would definitely
want to look at other techniques (including HTTP Digest, or the
token-based approach used in services like Amazon EC2 and S3) when you
are using HTTP.

Keep in mind, of course, that there is no such thing as an "/auth/login"
request in a stateless REST service :-). You'll be performing the
authentication check on every single request as they come in.

Craig