Thursday 2 October 2014

How to Secure RESTful Webservice via Annotation in Jersey

In my previous how to secure restful webservice I have showed how to secure a RESTful Webservice by configuring in web.xml.

Now we see how to implement security via annotation.

We can provide authorization for JAX-RS resource using the below annotation.
  • @PermitAll - specifies that all security roles are permitted to access your JAX-RS resources
  • @DenyAll - specifies that no security roles are permitted to access your JAX-RS resources
  • @RolesAllowed - specifies the security roles that are permitted to access your JAX-RS resources
Below are the steps to implement security via annoataion. 

1. Create a Custome ResourcConfig by creating a new class and extend it. In the constructor register RolesAllowedDynamicFeature as shown below.

import javax.ws.rs.ApplicationPath;

import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature;

@ApplicationPath("/")
public class ApplicationResourceConfig extends ResourceConfig{
  public ApplicationResourceConfig() {
         super(MyResource.class);
         register(RolesAllowedDynamicFeature.class);
     }
}

2. Now add Roles that can access the specific resources in JAX-RS resources. In below MyResource class I have added three method with sub path and Roles corresponding to them.


import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

/**
 * Root resource (exposed at "myresource" path)
 */
@Path("myresource")
public class MyResource {

 /**
  * This method is allowed for all Roles
  * 
  * @return
  */
 @GET
 @Produces(MediaType.TEXT_PLAIN)
 @Path("/unsecured")
 @PermitAll
 public String getsecured() {
  return " Message For all Roles!";
 }

 /**
  * This method is allowed to only users with Role <b>secured</b>
  * 
  * @return
  */
 @GET
 @Produces(MediaType.TEXT_PLAIN)
 @Path("/secured")
 @RolesAllowed("secured")
 public String getSecured() {
  return "Message for user with Role secured!";
 }

 /**
  * This method is allowed to only users with Role <b>admin</b>
  * 
  * @return
  */
 @GET
 @Produces(MediaType.TEXT_PLAIN)
 @Path("/securedadmin")
 @RolesAllowed("admin")
 public String getSecuredadmin() {
  return "Message for user with Role admin!";
 }
}

3. Configure web.xml

Add Custom ResourceConfig create above in init-param


    <init-param>
            <param-name>javax.ws.rs.Application</param-name>
            <param-value>com.ranvanshi.jersey.basicsecurityannotation.ApplicationResourceConfig</param-value>
    </init-param>

Add security-constraint for the Resources. We have provided security entry for enire resources. User has to in Role admin to access the resources.


 <security-constraint>
  <web-resource-collection>
   <web-resource-name>Secured</web-resource-name>
   <url-pattern>/webapi/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
   <role-name>admin</role-name>
  </auth-constraint>
 </security-constraint>
 <security-role>
  <role-name>admin</role-name>
 </security-role>
 <login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>Login</realm-name>
 </login-config>

Complete web.xml


<?xml version="1.0" encoding="UTF-8"?>
<!-- This web.xml file is not required when using Servlet 3.0 container, 
 see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html -->
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
 <servlet>
  <servlet-name>Jersey Web Application</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.ranvanshi.jersey.basicsecurityannotation</param-value>
  </init-param>
  <init-param>
   <param-name>javax.ws.rs.Application</param-name>
   <param-value>com.ranvanshi.jersey.basicsecurityannotation.ApplicationResourceConfig</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
  <servlet-name>Jersey Web Application</servlet-name>
  <url-pattern>/webapi/*</url-pattern>
 </servlet-mapping>
 <security-constraint>
  <web-resource-collection>
   <web-resource-name>Secured</web-resource-name>
   <url-pattern>/webapi/*</url-pattern>
  </web-resource-collection>
  <auth-constraint>
   <role-name>admin</role-name>
  </auth-constraint>
 </security-constraint>
 <security-role>
  <role-name>admin</role-name>
 </security-role>
 <login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>Login</realm-name>
 </login-config>
</web-app>


This post explains about implementing security via annotation in  Jersey.

Thanks !

Wednesday 1 October 2014

How to Secure RESTful Webservice in Jersey and Tomcat

This example explain how to make JAX-RS resource secured using HTTP Basic Auth.

I will enable HTTP Basic Authentication for the RESTful Webservice created in my previous blog Creating Jersey Restful Webservice.

Secure Resource With web.xml

You need to define the <security-constraint> elements in the web.xml and assign roles which are able to access these resources.


  <security-constraint>
    <web-resource-collection>
      <web-resource-name>BasicSecurityExample</web-resource-name>
      <url-pattern>/webapi/myresource</url-pattern>
      <http-method>GET</http-method>
    </web-resource-collection>
    <auth-constraint>
      <description>Authorized role is admin</description>
      <role-name>MyRole</role-name>
    </auth-constraint>
  </security-constraint>
  <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>Login</realm-name>
   </login-config>

To Secure multiple resources we have to add <security-constraint> for each resource we need to securr or we can secure multiple resource using wildcard in <url-pattern> like below.


  <security-constraint>
    <web-resource-collection>
      <web-resource-name>BasicSecurityExample</web-resource-name>
      <url-pattern>/webapi/*</url-pattern>
      <http-method>GET</http-method>
    </web-resource-collection>
    <auth-constraint>
      <description>Authorized role is admin</description>
      <role-name>MyRole</role-name>
    </auth-constraint>
  </security-constraint>

Create User in Tomcat Server.


In Tomcat we can add user in tomcat-users.xml file which is located in <TOMCAT_HOME>/conf folder. Add the below entry in tomcat-user.xml file to add a User test with Password test with role as MyRole.


<user password="test" roles="MyRole" username="test"/>


Now our GET method in the resource /webapi/myresource is secure. Run the application.

Open any browser and go to the below link http://localhost:8080/FirstDemo/
You will See the index page for the application.
Click on the Jersey resource to access the Jesery REST service.
When we click on the link we will be asked for Username and Password to login. GIve username and password as test to access the resource.


This post explains about enabling security in web.xml  without touching the java code.In my next blog i will share how to enable security via annoatation in java code.