Some Thoughts on Securing Web Resources

Lately I’ve been trying to figure some figure out some new ways to define declarative security constraints to web resources. Here’s the a use case that popped into my head a while back: suppose you have a service to access a persons information on a social networking site such as:

http://mysocialnetwork.foo/people/12345

This service offers two levels of membership: free and paid subscriptions. The free model only allows the caller to access a limited subset of information about user 12345, but a paid subscriber would have access to the complete record. So same URI, but a different resource depending on the authorization credentials of the caller.

Declarative security in the servlet API only allows you apply constraints to a single URI. So with the servelt API, you’d have to create to separate URIs in order to separate the functionality for free and paid users. By creating multiple URIs for different service tiers, the user would have to change the the URIs in their calling code if they upgraded from a free to paid subscriber.

To get around this, I’m thinking that a web resource could leverage the security annotations from JSR-250 so that you could write a PersonResource like so:

@UriTemplate("/people")
class PeopleResource {

   @UriTemplate("{id}")
   @RolesAllowed({"paidSubscriber"})
   @SecureTransport
   PersonResource getPaidPersonResource (@UriParam("id) String id) {
     return PaidPersonResource(id);
   }

   @UriTemplate("{id}")
   @RolesAllowed({"basic"})
   PersonResource getCheapSkatePersonResource( UriParam("id) String id) {
     return CheapSkatePersonResource (id);
   }
}

In this instance, the framework would invoke the method that the user is authorized for. If the user was a paid subscriber, they’d invoke the resource method that returns a PaidPersonResource. Additionally, because the PaidPersonResource may contain sensitive information, it must be accessed over SSL. The @SecureTransport annotation will redirect the caller to the same URI, but using a secure port.

Of course, if declarative security isn’t you cup of tea, then you can alway manage it yourself:

@UriTemplate("/people")
class PeopleResource {

   @HttpContext SecurityContext securityContext;

   @UriTemplate("{id}")
   PersonResource getPerson(@UriParam("id) String id) {
     if (securityContext.isUserInRole("paidSubscriber")) {
       if(securityContext.isTransportSecure()) {
          return PaidPersonResource(id);
       }else {
          //-- Handle your else condition
       }

     } else {
       return FreePersonResource(id);
     }
   }
}

Since JSR-311 is not exclusive to a servlet container, the SecurityContext would be a generalized injectable interface that provides access to security related information. This would make access to security details consistent across implementations regardless of whether or not you’re using a servlet container or not.

Please keep in mind that this is just an idea that I’m throwing around and it’s nothing official yet.

Advertisement