title: RESTful authentication for Java EE
body: <p>I've been spending some time evaluating the options available for restfully authenticating a user in a <strong>Java EE</strong> application. </p>
  
  <p>So, please suggest if the options listed below are valid along with the statements about advantages or disadvantages. It might be I'm missing details which might make an authentication method viable. Or it might be that there's another option which I've missed (again we're talking strictly java EE so <em>no query authentication</em> and what not unless it can be done in a EE compliant way ) </p>
  
  <blockquote>
    <p><strong>1. DIGEST/BASIC authentication</strong> </p>
  </blockquote>
  
  <pre><code> &lt;security-constraint&gt;
       &lt;web-resource-collection&gt;
          &lt;web-resource-name&gt;admin&lt;/web-resource-name&gt;
          &lt;url-pattern&gt;/protected/*&lt;/url-pattern&gt;
       &lt;/web-resource-collection&gt;
       &lt;auth-constraint&gt;
          &lt;role-name&gt;admin&lt;/role-name&gt;
       &lt;/auth-constraint&gt;
  &lt;/security-constraint&gt;
  &lt;login-config&gt;
      &lt;auth-method&gt;DIGEST/BASIC&lt;/auth-method&gt;
      &lt;realm-name&gt;as-defined-secuity-realm&lt;/realm-name&gt;
  &lt;/login-config&gt;
  </code></pre>
  
  <p><strong>Advantages</strong></p>
  
  <ol>
  <li><p>This is a REST friendly way of authenticating. You can send the authorisation credentials via an AJAX call. Once the user is authenticated, the browser will accompany any requests with the proper <code>Authorization: Basic/Digest QWxhZGRpbjpvcGVuIHNlc2FtZQ==</code> header. In case of bad credentials the user will be presented with the ugly browser login screen - if you can live with that then BASIC/DIGEST auth is the way for you. </p></li>
  <li><p>In the case of Digest the string passed to the server is an MD5 encrypted string, which is definetely more secure than Basic( which is a Base64 encoding of the 'user:password' string), but nevertheless <a href="http://en.wikipedia.org/wiki/Digest_access_authentication" rel="nofollow noreferrer">decipherable</a>. So in terms of security BASIC is pretty much as secure as FORM authentication and DIGEST is the most secure of them all. In conclusion if your site is entirely HTTPS (I mean <strong>entirely</strong> because if some resources are fetched via HTTP, your authorization headers for example will be visible to a third party) you are safe to go with BASIC/DIGEST. </p></li>
  <li>Easy to set up.</li>
  </ol>
  
  <p><strong>Disadvantages</strong></p>
  
  <ol>
  <li>Logging out is tricky to implement. See <a href="https://stackoverflow.com/questions/449788/http-authentication-logout-via-php">here</a> and <a href="http://www.berenddeboer.net/rest/authentication.html" rel="nofollow noreferrer">here</a>.Sure you have a nice AJAX request which authenticates the user, but you need to also have an ?AJAX? request which logs off the user - triggering the browser login window to appear again). BTW the nice servlet 3.0 request.logout() method <a href="https://stackoverflow.com/questions/2891750/servlet-3-0-logout-doesnt-work">does not work properly in this case</a>.</li>
  <li>Session timeouts are very hard to implement. Session expiration does occur(it is the job of the servlet container), but the browser will send the authorization headers on the next request, triggering re-authentication.</li>
  <li>No personalized login page. None. </li>
  <li>Hard to keep track of authenticated sessions. </li>
  </ol>
  
  <blockquote>
    <p><strong>2. FORM based authentication</strong></p>
  </blockquote>
  
  <pre><code> &lt;security-constraint&gt;
       &lt;web-resource-collection&gt;
          &lt;web-resource-name&gt;admin&lt;/web-resource-name&gt;
          &lt;url-pattern&gt;/protected/*&lt;/url-pattern&gt;
       &lt;/web-resource-collection&gt;
       &lt;auth-constraint&gt;
          &lt;role-name&gt;admin&lt;/role-name&gt;
       &lt;/auth-constraint&gt;
  &lt;/security-constraint&gt;
  &lt;login-config&gt;
      &lt;auth-method&gt;FORM&lt;/auth-method&gt;
      &lt;realm-name&gt;as-defined-security-realm&lt;/realm-name&gt;
      &lt;form-login-config&gt;
          &lt;form-login-page&gt;/auth/login.html&lt;/form-login-page&gt;
          &lt;form-error-page&gt;/auth/error.html&lt;/form-error-page&gt;
      &lt;/form-login-config&gt;
  &lt;/login-config&gt;
  </code></pre>
  
  <p>Long story short, if user accesses a <code>protected/*</code> url, the login page is <strong>included</strong> in the response. So instead of the content the user expects he will get the login page  configured in the <code>form-login-page</code> tag. If the password is OK he will be forwarded (302 Paged Moved Permanently) to the initially requested <code>protected/*</code> url. If password is NOK, the user will be forwarded (302 Paged Moved Permanently) to the error page. </p>
  
  <p><strong>Advantages</strong></p>
  
  <ol>
  <li>Personalized login page - this one seems to be the most popular :)</li>
  <li>Logoff is easy to implement. One needs only invalidate the HttpSession or call the request.logout() method (Servlet 3.0).</li>
  <li>Session timeouts</li>
  <li>IF and ONLY If you accept having a separate page for login than this is the solution for you.</li>
  </ol>
  
  <p><strong>Disadvantages</strong></p>
  
  <ol>
  <li>REST unfriendly (I'm not going to dig in the phylosophy of rest and the keeping server-side state is not RESTful debate. We're analyzing REST authentication in a JAVA EE way and server side state is always maintained for any authenticated subject). What is really bad about using FORM authentication is the fact that one cannot have consistent behavior across browsers. And it's all due to the 302 redirection which some browsers handle in AJAX response functions while others redirect the entire page (change URL in navigation bar). More details <a href="https://stackoverflow.com/questions/15996779/cannot-handle-302-redirect-in-ajax-and-why">here</a> and <a href="https://stackoverflow.com/questions/11163767/ajax-not-handling-302-redirect">here</a>. You cannot work around that 302 redirect so no FORM  and REST authentication for you mister !! </li>
  </ol>
  
  <blockquote>
    <p><strong>3. Programmatic authentication</strong></p>
  </blockquote>
  
  <p>Set up a URL for authentication. Behind that URL you can have a servlet which instantiates a login module (JAAS way) and calls the HttpServletRequest.login(user,pass) method along with the credentials. It should generate a 401/403 response if login fails. </p>
  
  <p>You can implement it by just specifying the security-constraints in your web.xml:</p>
  
  <pre><code>&lt;security-constraint&gt;
       &lt;web-resource-collection&gt;
          &lt;web-resource-name&gt;admin&lt;/web-resource-name&gt;
          &lt;url-pattern&gt;/protected/*&lt;/url-pattern&gt;
       &lt;/web-resource-collection&gt;
       &lt;auth-constraint&gt;
          &lt;role-name&gt;admin&lt;/role-name&gt;
       &lt;/auth-constraint&gt;
  &lt;/security-constraint&gt;
  </code></pre>
  
  <p>On the server side you simply need to set up a RESTFul service which authenticates a caller. Here is some sample code:</p>
  
  <pre><code>@Path("/auth")
  @ApplicationPath("/rest")
  public class AuthenticationRestFacade {
  
  @POST
  @Path("/login")
  @Consumes(MediaType.APPLICATION_JSON)
  @Produces(MediaType.APPLICATION_JSON)
  public User login(User loginInfo, @Context HttpServletRequest request) throws LoginException, ServletException {
  
      // nasty work-around for Catalina AuthenticatorBase to be able to 
      // change/create the session cookie 
      request.getSession();
      request.login(loginInfo.getName(), loginInfo.getPassword());
  </code></pre>
  
  <p><strong>Advantages</strong></p>
  
  <ol>
  <li>Personlized login page.</li>
  <li>AJAX/REST compatible</li>
  <li>Logout URL ( if a URL is set up to do so )</li>
  <li>Session timeouts ( container managed )</li>
  <li>You can return login data (username,email,roles,groups,etc.) in the response ( reaaaallly nice because you don't have to do another call after a successful login )</li>
  </ol>
  
  <p><strong>Disadvantages</strong> </p>
  
  <ol>
  <li>Needs a some bit of code writing. </li>
  <li>Needs the application to be able to handle 401/403 responses and display login window </li>
  </ol>
  
  <p>To conclude, the best viable options :</p>
  
  <ol>
  <li>If you don't care about session timeouts or logouts --> DIGEST</li>
  <li>If the above does not work for you AND you don't needto have an embedded login page (or a modal panel-like page) and you are fine with one single page for authentication --> FORM</li>
  <li>If the above does not work for you and you want all the flexibility and the compatibility in the world go with the PROGRAMMATIC approach. You have to define login/logout URL and also your client code should be able to cope with 401/403 responses (not easy).</li>
  </ol>
  
  <p>Really looking forward for you guys to suggest some viable alternative solutions. Because right now I would HATE to go with the PROGRAMMATIC approach</p>