Sunday, February 10, 2013

Integrating Spring Security with Dropwizard


Dropwizard is a great framework for streamlining Java web apps (I'd argue any app) for deployment in a production environment.  It's an answer to the complexity of Java Web and Application Containers, which tend to be overkill for 90% of your use-cases.
As a framework, Dropwizard is still a little young (I won't say immature because it's a rock-solid environment).    Dropwizard comes with two authenticators, Basic and OAuth, and it's SSL-based Client Authentication is relatively undocumented.  We needed certificated-based client authentication, but didn't want to have to also force users to do BasicAuth in addition to using a certificateust so we could inject a "principal" object (i.e. @Auth) in our JAX-RS controllers.
More importantly, we wanted the rich features of Spring Security, which not only includes support for other authentication mechanisms like SPNEGO+Kerberos, but also route-based and expression-based security.
With that said, we did the hard work in figuring out how to integrate Spring Security with Dropwizard and this is the resulting work:  https://github.com/Berico-Technologies/Fallwizard.  To use our set of extensions, follow the instructions below:

Configure Spring Security in your applicationContext.xml

Here is an example for certificate-based authentication.
<security:http>
  <security:intercept-url pattern="/*" access="ROLE_USER" />
  <security:intercept-url pattern="/admin/*" access="ROLE_ADMIN" />
  <security:x509 subject-principal-regex="CN=(.*?)," />
</security:http>

<security:authentication-manager>
  <security:authentication-provider>
    <security:user-service>
      <security:user name="Super Awesome Client" authorities="ROLE_USER" />
      <security:user name="The Boss" authorities="ROLE_USER, ROLE_ADMIN" />
    </security:user-service>
  </security:authentication-provider>
</security:authentication-manager>


Initialize your Spring Application Context.

Initialize your Spring Application Context in your Dropwizard Service class. We explicitly require the location of theapplicationContext in our Dropwizard Configuration class.
ApplicationContext applicationContext = 
  new FileSystemXmlApplicationContext(
    configuration.getSpringApplicationContext());

Register Spring Security with the Dropwizard Environment.

@Override
public void run(BlahBlahConfiguration configuration, Environment environment) throws Exception {

  ApplicationContext applicationContext = 
    new FileSystemXmlApplicationContext(
      configuration.getSpringApplicationContext());

  new SpringSecurityAuthProvider(applicationContext).registerProvider(environment);
}

Use @Auth UserDetails userDetails in your JAX-RS controllers.

We're going to inject the Spring Security UserDetails context into your controllers (why invent a new User object?).
@GET
@Timed
@Path("/chitty-chat/{topic}")
public ChittyChat getChittyChatOnTopic(@Auth UserDetails userDetails, @PathParam("topic") String topic){
   // ... get Chitty-Chat ...
}

Get to working on your app!

You're done. Spring Security is filtering requests prior to you're resources being called.  It it also possible to use the Spring Security annotations if your resources are instantiated and managed by Spring or by using the "component-scan" capability (see http://www.mkyong.com/spring/spring-auto-scanning-components/).

8 comments:

  1. great post! I'm confused, though, as to how one could use this as a basis for a webapp - how would I integrate a login page? i.e. use dropwizards views to return a HTML prompting for credentials - then intercept this and set state on the backend

    ReplyDelete
    Replies
    1. Thanks for your comments. I actually use Basic Auth, x509/SSL Auth and Kerberos with Dropwizard (through Spring Security) and haven't needed to implement Form-based authentication. You can, however, specify the login form using the Spring context file and simply perform a post to that serlvet with the correct form POST parameters: http://www.mkyong.com/spring-security/spring-security-form-login-example/. If you have any trouble, let me know and I will mock up a demo (I might do it anyway).

      Delete
    2. an example would be amazing :)
      I think I'm confident in the authentication mechanism (i.e. returning a login page whenever authentication is 'missing')
      what I'm wondering about is how to propagate authorization tags to other views

      long story short, I'm using part of my dropwizard setup as a regular MVC (returning views which will contain javascript [think single-page-app] that will call my other REST endpoints)

      by the way, the github link is 404ing

      Delete
    3. Sorry about the link. I renamed the repository and forgot to update. You can find it here: https://github.com/Berico-Technologies/Fallwizard. I write a little example over the weekend.

      As for your questions, I'm not sure what you mean by propagating "authorization tags". I don't actually use Spring MVC. I use JAX-RS (Jersey) coupled with Angular.js. You should be able to insert the UserDetails object into your model and ask questions like (user.getAuthorities().contains("role")). It's probably a little more difficult than that with many template languages, but I'm not terribly familiar with Spring MVC.

      Delete
  2. Highly recommended, the provided guidelines given are of the most importance to my searches, hopefully this would also proved to be great guide for me, looking forward the best use of the sufficient information given above. Please see http://best-college-essay.com/ for best essays.

    ReplyDelete
  3. I happen to be commenting to let you understand of the terrific encounter my wife's child undergone browsing your web site. Visit seder plates for best Seder Plates.

    ReplyDelete
  4. I wanted to construct a word to be able to appreciate you for all the amazing tactics you are showing at this site. My extensive internet look up has now been recognized with sensible ideas to talk about with my co-workers. Check professional phone answering for best Phone Answering.

    ReplyDelete
  5. Good informative post, thanks for sharing.

    ReplyDelete

Note: Only a member of this blog may post a comment.