Tuesday, April 19, 2011

Java EE 6 Security (without another framework)

While working on a new project I needed to add good old authentication and authorization for a RESTful web service. There are many popular frameworks out there for doing this but with the mindset that less is more I wanted to see if I could do it without adding yet another framework. I've been very happy with Java EE 6 and how they really have come a long way on simplicity so I put it to the test in the requirement. Below is all I had to do to protect my resources.

1. Configure Glassfish to provide a security realm. I used a jdbcRealm that pointed to my database. The 2 tips I have for this is if your db schema doesn't have the structure the container wants simply create a view. The second is make sure your JAAS Context name is "jdbcRealm" this is a "special" identifier and it doesn't work if you pick your own.

2. Configure the web.xml to specify what resources you want protected. It ended up looking like this:

<security-constraint>
        <display-name>user authentication</display-name>
        <web-resource-collection>
            <web-resource-name>Requiring authorization resources</web-resource-name>
            <description></description>
            <url-pattern>/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
            <http-method>HEAD</http-method>
            <http-method>PUT</http-method>
            <http-method>OPTIONS</http-method>
            <http-method>TRACE</http-method>
            <http-method>DELETE</http-method>
        </web-resource-collection>
        <auth-constraint>
            <description>Have to be a USER</description>
            <role-name>Consumer</role-name>
        </auth-constraint>
    </security-constraint>
  <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>login</realm-name>
    </login-config>
    <security-role>
        <description/>
        <role-name>Consumer</role-name>
    </security-role>


3. Inject SessionContext where I needed to get Principal information for user-level authorization. It ended up being a simple method in my base resource class I call when I need to know which username was authenticated:

    @Resource
    private SessionContext sessionContext;

    protected String getCallerUsername() {
        Principal principle = sessionContext.getCallerPrincipal();
        return principle.getName();
    }


I was very happy to be able to implement this common use case with Java EE 6 and not have to pull in yet another framework!