Authorizing the Current User with Spring Security and EL

After authentication, we usually want to authorize the actions of users in our system. Spring Security allows for this to be done with a simple annotation.

Initial Conditions

This presumes that Spring Security is already working and already being used to authenticate users. At this point we also presume that we have an implementation of UserDetails. Our goal is to authorize the currently logged in user using only the @PreAuthorize annotation on a web controller method.

Authorize!

Because @PreAuthorize uses Spring EL, we can use a simple string in the annotation to set authorization rules. Spring Security defines certain methods and objects available via EL. We can leverage these to do the authorization.

Spring Security provides an object called “principal” which – if you are using JPA authentication and have your own implementation of UserDetails – is really the UserDetails object defined in your code. Because the EL string is evaluated using reflection, all of the methods defined on your user details domain object are available in the EL string. For instance, maybe you have a domain object called CustomUserDetails with a method for determining authorization to read another domain object, such as .canReadDomainObject(Long id). We can reference this method directly in the Spring EL.

Observe:

@Controller
public class FooController {
    @PreAuthorize("isAuthenticated and principal.canReadDomainObject(#id")
    @RequestMapping(value="/foo/bar/{id}", method=RequestMethod.GET)
    public @RequestBody DomainObject String fooAction(@PathVariable Long id ) {
        return repository.findById(id);
    }
}

Note that we can reference the method parameter in the EL, but this requires an extra step. The full details are in the documentation for Spring Security EL, but the gist of it is that parameter information is not available via reflection by default, so we need to make that information available somehow. I found it easiest to just compile with the “-parameters” flag since I’m using Java 8. If you’re using an older version of Java, you can use the @P annotation to mark the parameter. The both work, feel free to use the technique that suits your taste.

Happy authorizing!

Advertisements

Leave a comment

Filed under Software Engineering

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s