I've been spending some time evaluating the options available for restfully authenticating a user in a Java EE application.
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 no query authentication and what not unless it can be done in a EE compliant way )
1. DIGEST/BASIC authentication
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>DIGEST/BASIC</auth-method>
<realm-name>as-defined-secuity-realm</realm-name>
</login-config>
Advantages
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 Authorization: Basic/Digest QWxhZGRpbjpvcGVuIHNlc2FtZQ==
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.
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 decipherable. 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 entirely 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.
Disadvantages
2. FORM based authentication
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>as-defined-security-realm</realm-name>
<form-login-config>
<form-login-page>/auth/login.html</form-login-page>
<form-error-page>/auth/error.html</form-error-page>
</form-login-config>
</login-config>
Long story short, if user accesses a protected/*
url, the login page is included in the response. So instead of the content the user expects he will get the login page configured in the form-login-page
tag. If the password is OK he will be forwarded (302 Paged Moved Permanently) to the initially requested protected/*
url. If password is NOK, the user will be forwarded (302 Paged Moved Permanently) to the error page.
Advantages
Disadvantages
3. Programmatic authentication
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.
You can implement it by just specifying the security-constraints in your web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>admin</web-resource-name>
<url-pattern>/protected/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
On the server side you simply need to set up a RESTFul service which authenticates a caller. Here is some sample 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());
Advantages
Disadvantages
To conclude, the best viable options :
Really looking forward for you guys to suggest some viable alternative solutions. Because right now I would HATE to go with the PROGRAMMATIC approach
Use of basic authentication is specified as follows: The string "Basic " is added to the Authorization header of the request. The username and password are combined into a string with the format "username:password", which is then base64 encoded and added to the Authorization header of the request.
OAuth (specifically, OAuth 2.0) is considered a gold standard when it comes to REST API authentication, especially in enterprise scenarios involving sophisticated web and mobile applications. OAuth 2.0 can support dynamic collections of users, permission levels, scope parameters and data types.
Java EE security services provide a robust and easily configured security mechanism for authenticating users and authorizing access to application functions and associated data at many different layers. Java EE security services are separate from the security mechanisms of the operating system.
In my experience, it is hard to implement a system using Java EE authentication and authorisation service that would work for both REST services and Server side MVC like JSP or JSF at the same time. All my experience are leaning towards using Form based authentication for the MVC part and some sort of token authentication (OAuth, Kerberos, LTPA) for REST services. Using Form or Basic authentication for REST services was usually challenging to implement, although we did it and it works fine on two projects.
It also depends on the preferred server implementation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With