How to use Basic HTTP Auth with REST webservice (Java+Jersey)?

user2416728 picture user2416728 · Jul 5, 2013 · Viewed 21.5k times · Source

I am a newbie to REST webservice and have just created my first webservice.
In my service the user can create profile via simple form giving his desired Username and password.

Now how to check user credentials when the user logs-in ??
I mean i have a simple form which validates user has logged in but how to validate user when he is to perform various profile operation of add/update/delete ??

For example:
In FB you sign-in and it stores a cookie which has your credentials and when you perform operations like "Post Status",message a friend...etc... it doesn't ask for your credentials anymore because it has a cookie in which your credentials are there and it just uses that cookie...

But in REST we dont use cookie ,so the next option is HTTP headers. And i want to know how to send and recieve user credentials via HTTP header .i.e
Basic HTTP Auth

Answer

benjiman picture benjiman · Jul 5, 2013

Client Side

To send the credentials to the API you use the HTTP Authorization header, specifying the credentials in a form of Basic username:password. The username:password String has to be encoded using an encoding scheme called Base64. So an example header could look something like this:

Authorization: Basic d2lraTpwZWRpYQ==

As the rest specification states that the client-server communication should be stateless, you have to include the header with the credentials on every request. Normally you will use a session cookie on the client side to identify the user so that he does not have to enter his credentials on every request.

Server Side

To check the credentials inside your Jersey REST Service, you need to catch and intercept all the incoming requests. Jersey provides a concept called ContainerRequestFilters to do this. For example if you use Tomcat you could add filters of this type inside your servlet definition in your web.xml like this:

<init-param>
    <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
    <param-value>your.package.BasicAuthFilter</param-value>
</init-param>

The referenced class BasicAuthFilter needs to implement Jerseys ContainerRequestFilter interface and override the public ContainerRequest filter(ContainerRequest request) method. Inside the method you will basically do the following:

  • fetch the Base64 encoded credentials from the Authorization header of the request
  • decode them (i.e. using javax.xml.bind.DatatypeConverter.parseBase64Binary())
  • use your UserDao (or other datasource provider) to check if the credentials are valid
  • return status code 401 Unauthorized if the validation fails (i.e. throw new WebApplicationException(Status.UNAUTHORIZED))
  • if the credentials are valid, simply return the request in order to delegate it to the Jersey Resource that is responsible for handling it

You can find a very good example in this blog post.