title: Implement Basic Authentication with Jersey on Client and Server
body: <p>I have implemented a REST server with JAX-RS that provides some endpoints which consume x-www-form-urlencoded data and respond with XML.</p>
  
  <p>I have two clients: an HTML page in a browser and a Java client that uses the Jersey 2 client API to send a request.</p>
  
  <p>So far, everythings works fine. Now, things start to get tricky as I try to implement basic authentication on server and client. My first approach was to use servlet authentication which works fine. I have added users and roles in tomcat-users.xml and enabled basic authentication in my server's web.xml.</p>
  
  <p>The problem is that I have to implement application level authentication in a javax.servlet.Filter for this exercise. So, basically the filter shall intercept any request to the server and check the Base64 decoded 'Authorization' header content against a HashMap that contains valid user credentials and respond with a 401 status code if no match is found.</p>
  
  <p>Surprisingly, that works. <em>But only as long as I keep the servlet authentication running</em>. As soon as I deactivate the servlet level authentication my application level authentication doesn't work anymore. I have checked that my filter is not ignored by adding entries to the Hashmap that are not contained in the tomcat-users.xml and vice versa. Only requests with credentials that pass both the servlet authentication as well as my own make it to the server.</p>
  
  <p>Debugging revealed that all requests miss the Authorization header as soon as I turn off servlet authentication. My guess is that servlet authentication somehow compensates for a mistake I made and "repairs" my requests but I can't see how.</p>
  
  <p>Here's the relevant client code:</p>
  
  <pre><code>HttpAuthenticationFeature httpAuthenticationFeature =
          HttpAuthenticationFeature
          .basic("ceo", "123456");
  
  ClientConfig clientConfig = new ClientConfig();
  clientConfig.register(httpAuthenticationFeature);
  javax.ws.rs.client.Client client = ClientBuilder.newClient(clientConfig);
  
  webTarget = client.target("http://" + hostname + ":" + port)
          .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_USERNAME, "ceo")
          .property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_PASSWORD, "123456")
          .path("RESTService");
  
  Form form = new Form();
  form.param("field1", value1);
  form.param("field2", value2);
  
  String response = webTarget.path("rest").path("service").path("endpoint")
          .request(MediaType.APPLICATION_XML)
          .post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE), String.class);
  </code></pre>
  
  <p>And here's the server code:</p>
  
  <pre><code>@Priority(Priorities.AUTHENTICATION)
  public class AuthenticationFilter implements javax.servlet.Filter {
  
      @Override
      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
              throws IOException, ServletException {
  
          HttpServletRequest req = (HttpServletRequest)request;
          String authCredentials = req.getHeader(HttpHeaders.AUTHORIZATION);
  
          // authenticate() returns true if credentials are valid
          if (authenticate(authCredentials))      
              chain.doFilter(request, response);
  
          // should return proper 401 response, but apparently does not
          // as browser shows no prompt for credentials
          else if (response instanceof HttpServletResponse) {
              HttpServletResponse httpServletResponse = (HttpServletResponse) response;
              httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
          }
      }
  
      // ...
  }
  </code></pre>
  
  <p>Thanks in advance!</p>