Posted on Leave a comment

Custom Response Types in Jersey SecurityContext

Jersey Logo

Sometimes you might need to return custom response types in your SecurityContext implementation when using Jersey RESTFul web services. Basically, there are two options available to do so:

  1. Use javax.ws.rs.core.Response and throw a WebApplicationException
  2. or write your own ExceptionMapper

Throw WebApplicationException

import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
import java.security.Principal;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.SecurityContext;

public class MySecurityContext implements SecurityContext {

	private final User user;
	private final Session session;

	public MySecurityContext(User user, Session session) {
		this.user = user;
		this.session = session;
	}

	public String getAuthenticationScheme() {
		return SecurityContext.BASIC_AUTH;
	}

	public Principal getUserPrincipal() {
		return user;
	}

	public boolean isSecure() {
		return false;
	}

	public boolean isUserInRole(String role) {

		JSONObject jsonObj = JSONFactoryUtil.createJSONObject();

		if (null == session || !session.isActive()) {
			jsonObj.put("status", "failed");
			jsonObj.put("message", "Authentication failed");

			javax.ws.rs.core.Response denied = javax.ws.rs.core.Response
					.status(javax.ws.rs.core.Response.Status.FORBIDDEN)
					.type("application/json; charset=utf-8")
					.entity(jsonObj.toString()).build();

			throw new WebApplicationException(denied);
		}

		try {
			return user.getRoles().contains(role);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return false;
	}
}

Custom ExceptionMapper

The other (even nicer option) is to write your own ExceptionMapper:

@Provider
public MyMapper implements ExceptionMapper<WebApplicationException> {
   public Response toResponse(WebApplicationException ex) {
     Response r = ex.getResponse();
     if (r.getStatus() == 403 && r.getEntity() == null) {
      return Response.fromResponse(r).entity(
        new Viewable("/403response", null)).build();
     } else {
       return r;
     }
   }
}