Sharing the same access path between end users and clients - 6.3

Talend ESB Service Developer Guide

EnrichVersion
6.3
EnrichProdName
Talend Data Fabric
Talend Data Services Platform
Talend ESB
Talend MDM Platform
Talend Open Studio for ESB
Talend Real-Time Big Data Platform
task
Design and Development
Installation and Upgrade
EnrichPlatform
Talend ESB

The first problem which needs to be addressed is how to distinguish end users from third-party clients and get both parties authenticated as required. Perhaps the simplest option is to extend a CXF OAuth2 filter (JAX-RS or servlet one), check Authorization header, if it is OAuth2 then delegate to the superclass, alternatively - proceed with authenticating the end users:

public class SecurityFilter 
   extends org.apache.cxf.rs.security.oauth2.filters.OAuthRequestFilter {
   @Context
   private HttpHeaders headers;

   public Response handleRequest(ClassResourceInfo cri, Message message) {
      String header = headers.getRequestHeaders().
         getFirst("Authorization");
      if (header.startsWith("Bearer ")) {
         return super.handleRequest(cri, message);
      } else {
         // authenticate the end user
      }
   }
} 

The next issue is how to enforce that the end users can only access the resources they've been authorized to access. For example, consider the following JAX-RS resource class:

@Path("calendar")
public class CalendarResource {

   @GET
   @Path("{id}")
   public Calendar getPublicCalendar(@PathParam("id") long id) {
      // return the calendar for a user identified by 'id'
   }

   @GET
   @Path("{id}/private")
   public Calendar getPrivateCalendar(@PathParam("id") long id) {
      // return the calendar for a user identified by 'id'
   }

   @PUT
   @Path("{id}")
   public void updateCalendar(@PathParam("id") long id, Calendar c) {
      // update the calendar for a user identified by 'id'
   }
}

Let's assume that the 3rd party client has been allowed to read the public user Calendars at "/calendar/\{id}" only, how to make sure that the client won't try to:

  1. update the calendar available at the same path

  2. read the private Calendars available at "/calendar/\{id}/private"

As noted above, OAuthPermission has an optional URIs property. Thus one way to solve the problem with the private calendar is to add, say, a uri "/calendar/\{id}" or "/calendar/1" (etc) property to OAuthPermission (representing a scope like "readCalendar") and the OAuth filter will make sure no subresources beyond "/calendar/\{id}" can be accessed. Note, adding a "\*" at the end of a given URI property, for example, "/a*" will let the client access "/a", "/a/b", etc.

Solving the problem with preventing the update can be easily solved by adding an httpVerb property to a given OAuthPermission.

One more option is to rely on the role-based access control and have @RolesAllowed allocated such that only users in roles like "client" or "enduser" can invoke the getCalendar() method and let only those in the "enduser" role access getPrivateCalendar() and updateCalendar(). OAuthPermission can help here too as described in the section on using OAuth fiters.