When we develop REST APIs for our application to enable integration with other applications, often we would want to secure the interface. This is done for a variety of reasons. We would like to prevent sniffing of data on the network by unauthorized people. We may want to categorize each user using user role and allow certain set of operations to be performed only by users of one role.
There are three important concepts which we need to understand with respect to JAX-RS core security concepts and protocols:
This refers to validating the identity of a client who is trying to access our services. This is done by checking whether the client has provided valid credentials or not. There are a few standard authentication protocols available for the Web. We will learn about some of them in later sections of the tutorial.
After the client is authenticated, it may want to interact with the RESTful web service. Authorization is done to ensure that the client is doing what it is supposed to do with the job role assigned. For example, in any multi-user application, the user creation REST APIs may be available for those users who are having administrative privileges. Care will be taken to give a 401 unauthorized access error if another user with no administrative privileges tries to create a new user in the system.
While the client is interacting with the RESTful service, chances are there for man-in-the-middle attacks to happen from some other people using by intercepting network packets if the connection is not secure. SSL/TLS are usually used to protect sensitive data that is transmitted over the wire. HTTPS may be used instead of HTTP protocol to make sure that encryption and security is incorporated in the application.
Decide The Appropriate Authentication Mechanism
While thinking of securing our RESTful web service, the first step we should be doing would be to decide which authentication protocol we should use. Java’s servlet containers usually support three types of authentication – basic, digest and client certificate authentications.
As the name suggests, this authentication mechanism provides the lowest amount of security for the application. In this type of authentication process, username and password incorporated in a request header called Authorization header. The credentials are encoded in Base64 encoded format and sent for each request to the server. Upon receiving the request, server inspects the request header and verifies the username and password.
A problem with this approach will be that a hacker can easily intercept the request and decode the credentials to use them for his own requests to server. To avoid this, we usually use basic authentication over HTTPS. Since HTTPS is secured and encrypted, an attacker cannot easily intercept the connection and decode the Authorization header. Here is a tutorial to secure a REST Service with Basic Authentication.
Even if the Base64 encrypted username and password credentials are sent over secure network in basic authentication, some network administrators are paranoid about the level of security associated with the approach. Digest Authentication was introduced so that the clients do not have to send cleartext passwords over HTTP.
The entire process happens in these steps:
- The client at first sends an insecure request to server.
- As the request does not contain credentials, server sends back a 401 error code and a WWW-Authentication header. The WWW-Authentication header gives an idea about the authentication protocol the client should be using. There are two important attributes that are sent as part of this header – the nonce and opaque attributes – which are server generated keys which can be used by the client to build subsequent requests.
- Using the information passed as a part of WWW-Authenticate header, the client builds a new request with Authorization header populated with digest specific attributes as response array. This contains username, realm, MD5 key generated from username, nonce, realm, URI and password.
- Upon receiving the request at server end, it builds its own version of the response hash using the secret values of username and password. If the hashes match, the credentials sent by client are valid.
The problem with this approach is that unless you use HTTPS, the approach is still vulnerable to a man-in-the-middle attack. The attacker can intercept the packet and send a fake response asking the client to use Basic authentication.
Client Certificate Authentication
Out of the three authentication procedures discussed so far, Client Certificate Authentication is perhaps the most secure way to perform authentication over the web.
Often, when we visit banking websites, we will often be redirected to https or advised by banking officials to access the website only over HTTPS to avoid stealing of confidential information by hackers. While we have an HTTPS connection, we may see something like this on the address bar:
The green lock symbol and green text says that the browser has downloaded the digitally signed certificate and verification has been done with a central verification authority, for instance, VeriSign. This makes sure that the browser is interacting with the real website we intend to talk with and not an imposter.
In Java, the same idea can be incorporated using what you call CertStore or KeyStore. The trusted certificates of various servers are usually stored in:
In production environment, if the client program interacts with a server program, at first, the client downloads the certificate from the server and adds it to the trust store. To provide two-way authentication, in addition to client receiving and installing a signed digital certificate from the server, the server can also receive and install a certificate that represents and identifies the client. Once a verified link is established, there is no further need for user authentication.
Authentication is all about making sure that access to the service is granted only to identified users. Authorization goes one step further to ensure that we grant access only to those services that should be given to the specified category of users.
In JAX-RS, we do this by modifying web.xml deployment descriptor or by adding annotations to the resources classes. In the deployment descriptor, <login-config> can be used to define authentication method for the entire application. An <auth-constraint> with one or more <role-name> can be used to define which category of users are allowed to access that particular constraint. Alternatively, this can be done at resource or method level using @RolesAllowed annotation.
Further Security Measures
The deployment descriptor can also be modified to incorporate encryption. This can be done using <user-data-constraint> tag. If the value stored in the tag is confidential, any user who access the server over HTTP will be redirected to HTTPS.
JAX-RS provides the class javax.ws.rs.core.SecurityContext which can be used to gather information about a secure connection programmatically within the application. This class has many useful methods which can be used further to enhance the features of the application.