RESTful Services HTTP basic Authentication

Last modified on February 11th, 2015 by Joe.

In this RESTful services tutorial, we will see about how to do HTTP basic authentication. There are many ways to implement authentication in RESTful web services. HTTP basic authentication is the first step in learning security.

In this tutorial, I have not used any Jersey specific interceptors and we will see about them in future tutorials. I will be using a standard servlet filter to intercept the request, do the authentication and continue with response.

Follow the earlier written tutorial, RESTful Web Services with Java JAX-RS using Jersey to setup a basic hello world RESTful service.

Step1: Intercept the request

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>RESTful Service Authentication</display-name>
  <welcome-file-list>
    <welcome-file>index.htm</welcome-file>
  </welcome-file-list>
  <servlet>
    <servlet-name>RESTful Jersey Hello World Service</servlet-name>
    <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
    <init-param>
      <param-name>jersey.config.server.provider.packages</param-name>
      <param-value>com.javapapers.webservices.rest.jersey</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>RESTful Jersey Hello World Service</servlet-name>
    <url-pattern>/rest/*</url-pattern>
  </servlet-mapping>
  <filter>
    <filter-name>AuthenticationFilter</filter-name>
    <filter-class>com.javapapers.webservices.rest.jersey.RestAuthenticationFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>AuthenticationFilter</filter-name>
    <url-pattern>/rest/*</url-pattern>
  </filter-mapping>
</web-app>

We have added a servlet filter class RestAuthenticationFilter for all urls of the form /rest/*.

Step 2: RestAuthenticationFilter class

package com.javapapers.webservices.rest.jersey;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RestAuthenticationFilter implements javax.servlet.Filter {
	public static final String AUTHENTICATION_HEADER = "Authorization";

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain filter) throws IOException, ServletException {
		if (request instanceof HttpServletRequest) {
			HttpServletRequest httpServletRequest = (HttpServletRequest) request;
			String authCredentials = httpServletRequest
					.getHeader(AUTHENTICATION_HEADER);

			// better injected
			AuthenticationService authenticationService = new AuthenticationService();

			boolean authenticationStatus = authenticationService
					.authenticate(authCredentials);

			if (authenticationStatus) {
				filter.doFilter(request, response);
			} else {
				if (response instanceof HttpServletResponse) {
					HttpServletResponse httpServletResponse = (HttpServletResponse) response;
					httpServletResponse
							.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
				}
			}
		}
	}

	@Override
	public void destroy() {
	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {
	}
}

Before the RESTful resource is invoked, we get control in the above class. We get the HTTP Header value for Authorization. That’s the Basic authentication credential and we will pass it on to AuthenticationService for validation.

Step 3: AuthenticationService

package com.javapapers.webservices.rest.jersey;

import java.io.IOException;
import java.util.Base64;
import java.util.StringTokenizer;

public class AuthenticationService {
	public boolean authenticate(String authCredentials) {

		if (null == authCredentials)
			return false;
		// header value format will be "Basic encodedstring" for Basic
		// authentication. Example "Basic YWRtaW46YWRtaW4="
		final String encodedUserPassword = authCredentials.replaceFirst("Basic"
				+ " ", "");
		String usernameAndPassword = null;
		try {
			byte[] decodedBytes = Base64.getDecoder().decode(
					encodedUserPassword);
			usernameAndPassword = new String(decodedBytes, "UTF-8");
		} catch (IOException e) {
			e.printStackTrace();
		}
		final StringTokenizer tokenizer = new StringTokenizer(
				usernameAndPassword, ":");
		final String username = tokenizer.nextToken();
		final String password = tokenizer.nextToken();

		// we have fixed the userid and password as admin
		// call some UserService/LDAP here
		boolean authenticationStatus = "admin".equals(username)
				&& "admin".equals(password);
		return authenticationStatus;
	}
}

Here in we have standard Java code. We extract the username and password from the auth string. Then verify it against the existing credentials and return boolean accordingly.

Step 4: RESTful resource

package com.javapapers.webservices.rest.jersey;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/helloworld")
public class HelloWorld {

	@GET
	@Produces(MediaType.TEXT_PLAIN)
	public String sayPlainTextHello() {
		return "Hello World RESTful Jersey!";
	}

	@GET
	@Produces(MediaType.TEXT_XML)
	public String sayXMLHello() {
		return "<?xml version=\"1.0\"?>" + "<hello> Hello World RESTful Jersey"
				+ "</hello>";
	}

	@GET
	@Produces(MediaType.TEXT_HTML)
	public String sayHtmlHello() {
		return "<html> " + "<title>" + "Hello World RESTful Jersey"
				+ "</title>" + "<body><h1>" + "Hello World RESTful Jersey"
				+ "</body></h1>" + "</html> ";
	}

}

Above is a Jersey implementation of Java JAX-RS RESTful service. This should be invoked on successful authentication. If the authentication is failed we will get 401 status error given in the Servlet authentication filter.

Testing RESTful Service with a REST client

I used “Advanced Rest Client”, a Chrome extension to test the RESTful services. Its nice and does the job well. Add it in your Chrome browser and send the request as below. Sending the basic auth credentials in this REST client is not so trivial. They should think about adding an explicit button. How we should do it is, go to the “Headers” tab and type “Authorization” in the key field and then go to the value field. On focus of value, we get a small pop-up button “Construct” and on clicking that we get the form to enter username and password.

RESTful-Services-Authentication-Information

On pop-up, enter the authentication credentials.

RESTful-Services-http-basic-Authentication

After adding credentials, ensure that the method selected is GET for this example tutorial and then send the request. On success, the REST resource should respond with hello world message.

RESTful-Services-Authentication

Download the RESTful Services Example Authentication Project

Download

Project zip does not include the dependent jar files. I have included all the JAR file from the Jax-RS Jersey download bundle in the lib folder. Please download all those jar files and add to the project lib. Following are those JAR files.

aopalliance-repackaged-2.4.0-b06.jar
asm-debug-all-5.0.2.jar
hk2-api-2.4.0-b06.jar
hk2-locator-2.4.0-b06.jar
hk2-utils-2.4.0-b06.jar
javassist-3.18.1-GA.jar
javax.annotation-api-1.2.jar
javax.inject-2.4.0-b06.jar
javax.servlet-api-3.0.1.jar
javax.ws.rs-api-2.0.1.jar
jaxb-api-2.2.7.jar
jersey-client.jar
jersey-common.jar
jersey-container-servlet-core.jar
jersey-container-servlet.jar
jersey-guava-2.15.jar
jersey-server.jar
org.osgi.core-4.2.0.jar
osgi-resource-locator-1.0.1.jar
persistence-api-1.0.jar
validation-api-1.1.0.Final.jar

Comments on "RESTful Services HTTP basic Authentication"

  1. Harry says:

    Hi Joe, i really like your RESTful Services series tutorial, in this tutorial, i am using the zipped project and import it in Eclipse(Luna),however,when i tried to send request in Advanced Rest Client,i got the following error in the console

    Servlet.service() for servlet [RESTful Jersey Hello World Service] in context with path [/RESTful_Service_Authentication] threw exception [Filter execution threw an exception] with root cause
    java.lang.ClassNotFoundException: java.util.Base64
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1305)
    at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1157)
    Basically, it is saying that java.lang.ClassNotFoundException: java.util.Base64, but there is not compiling error in Eclipse, i have no idea why this is happening. Can you help me please ? i am runing JDK 8 and have tested both on Tomcat 7 and Tomcat 8,producing the same error.

    Thanks

  2. Deepak says:

    Nice…

  3. Satya Prasad says:

    Can you tell me why Jersey’s ServletContainer is more preferred to spring’s DispatcherServlet?

  4. Joe says:

    @Harry,

    “Edit Server Runtime Environment” and ensure that the JRE is pointing to JDK8.

  5. Krishna kumari says:

    Very helpful. Good explanation.

  6. […] In this RESTful services tutorial series, we will see about how to intercept a request in JAX-RS restful web service. JAX-RS specification is the Java API for RESTful web services and Jersey is its reference implementation. In the previous tutorial we saw about doing authentication in REST with plain servlet filters. […]

  7. Peter says:

    Joe,

    Thanks for these tutorials. This was the simplest version of adding basic authentication to a REST service that I could find.

    Great job!

  8. Chuck says:

    Hi Joe,

    I am deploying this in a Weblogic 10 container (forced to use Jersey 1.2 due to JDK 5). At any rate, when I send the basic auth header, it appears that Weblogic wants a valid weblogic user (and will not allow me to intercept the request in my filter) and fails. Any idea how i can bypass this?

    Thanks!

  9. Gerhard says:

    Hi Joe,

    Thanks so much for this tutorial – it actually works !!!

  10. Yatender says:

    Very helpful and working fine :)

    Thanks a lot :)

  11. Sanket says:

    Hi, thank you for this post.
    I have one doubt
    After calling AuthenticationService, when it returns “true”
    You have called doFilter method.

    if (authenticationStatus) {
    filter.doFilter(request, response);}

    What does this filter.doFilter() method does excatly??

  12. Anhad says:

    This is perfect!!
    Clear and to the point.
    Thanks a lot.
    Cheers,
    Anhad

  13. BG says:

    Thanks a lot, very great article with complete information.

  14. Nitesh says:

    Thank you for the tutorial. I am able to run it actually.

  15. Marcio Barroso says:

    Thanks a lot man ! Life saver. Great job !

Comments are closed for "RESTful Services HTTP basic Authentication".