mscharhag, Programming and Stuff;

A blog about programming and software development topics, mostly focused on Java technologies including Java EE, Spring and Grails.

  • Tuesday, 15 October, 2013

    Getting Started with method security in Grails using Spring Security

    This blog post will be about implementing method level security with security expressions in Grails using the Spring Security plugins. I assume you have some basic understanding of the Grails Spring Security Core plugin.

    Roles aren't enough.
    When using the Spring Security Core plugin you typically start to configure which roles are required for accessing certain URLs. This configuration can be done by using a configuration map (see below), annotating controller actions with the @Secured annotation or by storing a
    RequestMap within a database (see: Requestmap Instances Stored in the Database).

    Example role configuration:

    grails.plugins.springsecurity.interceptUrlMap = [
      // /admin/** URLs can only be accessed by users with role ROLE_ADMIN
      '/admin/**' : ['ROLE_ADMIN'], 
      ...
    ]

    Roles work fine to define simple rules like only admins are allowed to access admin functionality.
    Unfortunately this often is not enough.

    Consider an application in which users can create some kind of content (like comments, news, etc.). A user should be able to edit the content he created later. However, a user should not be able to edit content created by other users. Here, a role could be used to check if a user has general access to the edit content functionality. Unfortunatelly roles aren't a great help for checking if a certain user is allowed to edit a specific piece of content. This is where security expressions and method security jumps in.

    The @Secured annoation
    If you used Spring Security (without Grails) before you might remember the @Secured annotation from Spring Security. The Grails Spring Security Core plugin also contains a Grails replacement for this annotation. The grails version (@grails.plugins.springsecurity.Secured) also works on fields while the original (@org.springframework.security.access.annotation.Secured) can only be used on methods. This allows the Grails annotation to be used with fields that contain a closure value:

    @Secured(['ROLE_ADMIN']) // only works with @grails.plugins.springsecurity.Secured
    def adminAction = {
      ...
    }

    Additionally the Grails @Secured annotation also supports SpEL expression while the standard Spring Security @Secured annotation only supports role checking (see the documentation for more details).

    What about services?
    Security constraints are something you typically want to have in your service layer. Unfortunately the Grails Spring Security Core plugin makes the @Secured annotation only available in controllers. To use service level security annotations we have to add the Grails Spring Security ACL plugin. The ACL plugin additionally provides the more sophisticated @PreAuthorize and @PostAuthorize annotations. These annotations can be used to validate access to a method before and after it has been executed (we will see this later). The main purpose of the Grails Spring Security ACL plugin is to provide support for Access Control Lists (ACL) which allow very fine grained control of access rights. Maybe I will write a blog post about the usage of ACLs in the future, but it is definitely out of scope for this post. Here we only use the ACL plugin to get security expression support in annotations. No further plugin configuration is required for this.

    That's fine. What about code?
    OK let's assume we want to build an application where users can manage notes. The domain classes look like this:

    class Note {
      String title
      String text
      static belongsTo = [author: User]
    }
    class User {
      String username
      String password
      static hasMany = [notes: Note]
    
      static constraints = {
        username blank: false, unique: true
        ...
      }
    
      // .. rest of generated user class from Spring Security Core plugin 
    }

    A user can have many notes while a Note has exactly one author. Now we want to create a service which provides some common methods for working with Note objects:

    class NoteService {
      public long getTotalNoteCount() { .. }
      public void createNote(Note note) { .. }
      public void updateNote(Note note) { .. }
      public Note getNote(long id) { .. } 
      public void removeNote(long id) { .. }
    }

    To these service methods we want to apply the following access rules:

    • Everyone should be able to get the total count of notes stored by the system with getTotalNoteCount()
    • Logged in users can create new notes using createNote()
    • Notes can only be read, updated or removed by the author

    We start with adding @PreAuthorize to getTotalNoteCount():

    @PreAuthorize('permitAll()')
    public long getTotalNoteCount() {
      ...
    }

    @PreAuthorize and @PostAuthorize take a SpEL expression as parameter, which is evaluated to decide if a user is granted access. Everyone should be able to call getTotalNoteCount() so we simply call the predefined permitAll() function.

    The security expression for createNote() looks similar:

     

    @PreAuthorize('isFullyAuthenticated()')
    public Note createNote(Note note) {
      ...
    }

    Since only logged in users should be able to create notes we call the isFullyAuthenticated() function within the expression.

    So far it would be possible to achieve the same effect using roles. We will see the real bonus of security expressions in the next example. The access rule for updateNote() is slightly more complicated:

    @PreAuthorize('isAuthenticated() and principal?.username == #note.author.username')
    public Note updateNote(Note note) {
      ...
    }

    When updating a Note we have to be sure that the logged in user is the author of the Note object he wants to edit. Spring Security populates the SpEL context with a predefined variable named principal which can be used to access the currently logged in user (the list of all predefined variables can be found here). With the # prefix it is possible to access method arguments. So #note in the SpEL expression references the note method parameter. In this example we check if the names of the logged in user (principal) and the author of the passed Note object (#note.author) match. If both are the same the user is allowed to update the Note object.

    The getNote() method is a bit different because there is no Note object parameter which can be used to access the author of the note. However, the return value is a Note object which can be checked using @PostAuthorize:

    @PostAuthorize('isAuthenticated() and principal.username == returnObject.author.username') 
    public Note getNote(long id) {
      ...
    }

    As mentioned above the @PostAuthorize annotation can be used to evaluate a security expression after a method has been called. Within the @PostAuthorize expression it is possible to access the object returned by the method call using the predefined variable returnObject. Here an AccessDeniedException will be thrown if the logged in user is not the author of the returned Note object.

    removeNote() is a bit more complicated. There is no Note object parameter so there is no easy way to validate the note author within @PreAuthorize. @PostAuthorize doesn't help here either. Even if removeNote()would return the removed Note object @PostAuthorize would check if the user is allowed to remove a Note object after it has been removed. Not that useful...

    In the following I will show two different ways of adding the security constraint to removeNote().

    1. Using bean references

    Within SpEL expressions it is possible to reference beans and delegate the evaluation of security rules to them. This can look like the following piece of code:

    @PreAuthorize("@securityService.canRemoveNote(#id)")
    public Note removeNote(long id) {
      ...
    }

    The @ sign is used to reference beans in SpEL expressions. Here, the method canRemoveNote() of a bean named securityService is called. The note ID is passed as parameter to canRemoveNote(). The securityService bean is a standard Grails service that is used to implement the security constraints:

    class SecurityService {
     
      def springSecurityService
     
      public boolean canRemoveNote(long id) {
        Note note = Note.get(id)
        return note.author == springSecurityService.getCurrentUser()
      }
    }

    Unfortunately this won't work out of the box and some small adjustments to the Spring Security configuration need to be done. Some time ago I wrote a short article about exactly this, so I won't explain it here again. Please have a look at this blog post for more details: Calling bean methods in Spring Security expressions.

    2. Using a PermissionEvaluator

    An alternative solution for implementing the access rules of removeNote() is to use Spring Security's build in hasPermission() methods to delegate the security checks to a PermissionEvaluator. Within the security expression context two different hasPermission() methods are available:

    hasPermission(Object targetObject, Object permission)
    hasPermission(Serializable targetId, String targetType, Object permission)

    The first one can be used if an instance of the object that has to be checked is available (like in  updateNote(Note note)). The second version can be used of no instance is available and the object needs to be identified by an ID and type. The later one is the one that can help us with the removeNote() method:

    @PreAuthorize("hasPermission(#id, 'com.mscharhag.Note', 'remove')")
    public Note removeNote(long id) {
      ..
    }

    Note that the primitive type long of id gets converted to Long which implements the required Serializable interface. Now we have to create our own PermissionEvaluator implementation to define our security constraints. PermissionEvaluator requires the implementation of two methods which directly correlate to the two hasPermission() methods that can be used within security expressions:

    boolean hasPermission(Authentication authentication, Object targetDomainObject, Object permission) 
    boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) 

    The only difference is that Spring Security passes the current authentication state as additional parameter to the PermissionEvaluator. A possible implementation of PermissionEvaluator can look like this:

    class GrailsPermissionEvaluator implements PermissionEvaluator {
      
      def grailsApplication
      def springSecurityService 
      
      @Override
      public boolean hasPermission(Authentication authentication, Object note, Object permission) {
        def user = springSecurityService.getCurrentUser();
        return permission == 'remove' && note.author == user
      } 
      
      @Override
      public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType, Object permission) {
        // get domain class with name targetType
        Class domainClass = grailsApplication.getDomainClass(targetType).clazz
        
        // get domain object with id targetId
        Note note = domainClass.get(targetId)
        
        return hasPermission(authentication, note, permission)
      }
    }

    As we can see the second method resolves targetType and targetId to a Note object, which is then passed to the first method. The first method checks if the currently logged in user is allowed to remove the Note object.

    To make this work we need to override the default permissionEvaluator bean that is configured by the Spring Security ACL plugin. This is done in grails-app/conf/spring/resources.groovy :

    permissionEvaluator(GrailsPermissionEvaluator) {
      grailsApplication     = ref('grailsApplication')
      springSecurityService = ref('springSecurityService')
    }

    By default the Grails Spring Security ACL plugin configures an AclPermissionEvaluator instance as permissionEvaluator, which can be used for evaluating ACL rules. However, in this example we are not using ACLs, so we can override it with our own implementation.

    In summary bean references and the PermissionEvaluator approach provide both a good way to implement your own security constraints. This is especially useful if your access rules are more complex than the ones in this example.

    The final NoteService looks like this:

    class NoteService { 
      
      @PreAuthorize('permitAll()')
      public long getTotalNoteCount() { .. }
      
      @PreAuthorize('isFullyAuthenticated()')
      public Note createNote(Note note) { .. }
      
      @PostAuthorize('isAuthenticated() and principal.username == returnObject.author.username') 
      public Note getNote(long id) { .. }
      
      @PreAuthorize('isAuthenticated() and principal.username == #note.author.username')
      public Note updateNote(Note note) { .. }
      
      @PreAuthorize("@securityService.canRemoveNote(#id)")
      public Note removeNoteUsingBeanResolver(long id) { .. }
       
      @PreAuthorize("hasPermission(#id, 'com.mscharhag.Note', 'remove')")
      public Note removeNoteUsingPermissionEvaluator(long id) { .. } 
    }

    The full source code can be found at GitHub.

  • Friday, 4 October, 2013

    Single quote escaping in Java resource bundles

    In this post I will describe a small pitfall when using Java's ResourceBundle and MessageFormat classes, especially in combination with Spring's ResourceBundleMessageSource.

    ResourceBundle is a widely used class for localizing resources like message strings while MessageFormat can be used to replace placeholders within string messages. The typical usage of ResourceBundle and MessageFormat look like this:

    messages_en.properties:

    myMessage=Hello {0}

    Java code:

    ResourceBundle bundle = ResourceBundle.getBundle("messages");
    String pattern = bundle.getString("myMessage");         // Hello {0}
    String message = MessageFormat.format(pattern, "John"); // Hello John

    Code similar to this is used for example in the fmt JSP Tag library or in Spring's ResourceBundleMessageSource for retrieving localized messages.

    Whenever you are using MessageFormat you should be aware that the single quote character (') fulfils a special purpose inside message patterns. The single quote is used to represent a section within the message pattern that will not be formatted. A single quote itself must be escaped by using two single quotes ('').

    Let's look at some examples:

    messages_en.properties:

    test.message1=test {0} {1} {2}
    test.message2=test {0} '{1}' {2}
    test.message3=test {0} ''{1}'' {2}
    test.message4=test {0} '''{1}''' {2}
    test.message5=test {0} '{1} {2}
    test.message6=test {0} ''{1} {2}

    Java code:

    for (int i = 1; i <= 6; i++) {
      String pattern = bundle.getString("test.message" + i);
      String message = MessageFormat.format(pattern, 'A', 'B', 'C');
      System.out.println(message);
    }

    Output:

    test A B C
    test A {1} C
    test A 'B' C
    test A '{1}' C
    test A {1} {2}
    test A 'B C 

    As we can see placeholders between two simple single quotes are not replaced and all single quotes that are not escaped by another single quote don't show up in the output.

    It is important that everyone working on localization is aware of this. Note that the usage of single quotes varies a lot between languages. You can write pages of German text that do not contain a sole single quote character. In contrast, French text is typically full of single quotes. So it is a good idea to double-check messages of single quote heavy languages like French for proper escaping.

    Single quote escaping with Spring's ResourceBundleMessageSource

    Single quote escaping can become a bit more tricky if you are building a Spring application that makes use of Spring's ResourceBundleMessageSource class. If you have properly set up a ResourceBundleMessageSource bean it can be used to retrieve string messages like this:

    messages_en.properties:

    myMessage=Hello {0}

    Java code:

    Object[] args = new Object[] { "John" };
    Locale locale = new Locale("en");
    String message = messageSource.getMessage("myMessage", args, locale); // Hello John

    Internally ResourceBundleMessageSource uses Resourcebundle and MessageFormat for receiving string messages. However, ResourceBundleMessageSource does a small optimization by default. It will only parse a message through MessageFormat if one or more arguments have been passed in for the message. If no message arguments are passed to getMessage() the message text will be returned as-is. This means that the rules for escaping single quotes only need to be applied if the message takes any arguments.

    Let's look at another example:

    messages_en.properties:

    test.message1=John's message
    test.message2={0}'s message
    test.message3=John's {0}

    Java code:

    private void printMessage(String code, Object... args) {
      Locale locale = new Locale("en");
      String message = messageSource.getMessage(code, args, locale);
      System.out.println(message);
    }
    printMessage("test.message1");
    printMessage("test.message2", "John");
    printMessage("test.message3", "message");

    Output:

    John's message
    Johns message
    Johns {0}

    The first message does not take any arguments, so no MessageFormat is applied and the single quote does not need to be escaped. The second and third messages, however, are formatted by a MesssageFormat which processes the single quote characters. In these messages the single quotes should better be escaped with another single quote character otherwise they won't show up in the output.

    From a developer point of view the rules for escaping single quotes might make sense. However, you will have a hard time explaining these rules to localizers who have only a very basic technical knowledge. It just won't work!

    Luckily ResourceBundleMessageSource has a very useful flag called alwaysUseMessageFormat that can be enabled if all messages should be parsed by MessageFormat. If this flag is set to true (default value is false) all single quotes need to be escaped.

    If you are working with multiple localizers you should enable this option to simplify the rule of escaping single quotes. Otherwise, you (or the localizer) will go down in localization tickets if you have to support French ;-)

  • Tuesday, 1 October, 2013

    Grails: Calling bean methods in Spring Security expressions

    Some days ago while working on a Grails application I was in a situation where I wanted to call a bean method from a Spring security SPEL expression. I was using the @PreAuthorize annotation from the Spring Security ACL plugin and wanted to do something like this:

    @PreAuthorize("myService.canAccessUserProfile(#profileId)")
    public Profile getUserProfile(long profileId) {
      ...
    }

    @PreAuthorize takes a SPEL expression as parameter that is evaluated to see if the currently logged in user is allowed to access the getUserProfile() method. Within this SPEL expression I wanted to call the canAccessUserProfile() method of myService for performing the security check. In the following I will explain which steps are necessary to make this working.

    Luckily it is possible to reference beans from SPEL expressions by prefixing their name with an @ symbol:

    @PreAuthorize("@myService.canAccessUserProfile(#profileId)")

    However, this change alone won't work out of the box and we have to do some small adjustments on the Spring Security configuration.

    The SPEL expression parser (see: SpelExpressionParser) that is used to parse the security expression delegates the lookup of beans to a BeanResolver. In order to make the security expression from above work we have to create a BeanResolver implementation and add it to the Spring Security configuration.

    Creating a BeanResolver for Grails is very simple:

    class GrailsBeanResolver implements BeanResolver {
    
      GrailsApplication grailsApplication
    
      @Override
      public Object resolve(EvaluationContext evaluationContext, String beanName) throws AccessException {
        return grailsApplication.mainContext.getBean(beanName)
      }
    }

    We only have to implement the resolve() method to satisfy the BeanResolver interface. In our example we delegate this job to the bean factory of our Grails application. So, we can access all available beans within security expressions.

    Now we have to add our bean resolver to the SPEL evaluation context (see: EvaluationContext). This can be done by overriding the createEvaluationContext() of Spring Securities DefaultMethodSecurityExpressionHandler:

    class GrailsExpressionHandler extends DefaultMethodSecurityExpressionHandler {
    
      BeanResolver beanResolver
    
      @Override
      public EvaluationContext createEvaluationContext(Authentication auth, MethodInvocation method) {
        StandardEvaluationContext context = (StandardEvaluationContext) super.createEvaluationContext(auth, method)
        context.setBeanResolver(beanResolver)
        return context;
      }
    }

    As the name suggests createEvaluationContext() is responsible for creating the evaluation context for security expressions. The only thing we do is adding a beanResovler after the EvaluationContext has been created.

    After that, we have to configure our two new beans in grails-app/conf/spring/resources.groovy using the Spring Bean DSL:

    beans = {
      expressionHandler(GrailsExpressionHandler) {
        beanResolver              = ref('beanResolver')
        parameterNameDiscoverer   = ref('parameterNameDiscoverer')
        permissionEvaluator       = ref('permissionEvaluator')
        roleHierarchy             = ref('roleHierarchy')
        trustResolver             = ref('authenticationTrustResolver')  
      }
    
      beanResolver(GrailsBeanResolver) {
        grailsApplication = ref('grailsApplication')
      }
    }

    Normally the expressionHandler bean would be an instance of DefaultMethodSecurityExpressionHandler as mentioned above. Since we want Spring
    Security to use our GrailsExpressionHandler we have to override the expressionHandler bean. The only new dependency we added is the beanResolver property. The other four dependencies of expressionHandler are required by DefaultMethodSecurityExpressionHandler (the base class of GrailsExpressionHandler). These dependencies are already provided by the Spring Security plugins.

    Now it should be possible to reference beans using the @ prefix and call their methods in security expressions.

  • Tuesday, 24 September, 2013

    Trouble with MySQL’s lower() function

    If you are using MySQL 5.6.x with Hibernate and your query results don’t show up in the expected order it is possible that you run into this MySQL bug.

    Today we ran into this issue with GORM (which uses Hibernate). A simple findAll() returned the results in invalid order:

    List users = User.findAll([max: 10, offset: 0, sort: "name", order: "asc"]

    Other than expected the resulting list of users was not ordered by the users name.

    When looking at the query generated by hibernate we saw the following order by clause:

    ... order by lower(this_.name) asc limit ?

    After testing this query in different variations against different MySQL versions, we noticed that the lower() function does not work as intended in MySQL 5.6.11. Shortly after that, we found the bug ticket mentioned above.

  • Sunday, 15 September, 2013

    Grails: Data binding with Lists

    Some days ago I had a bit of trouble with the data binding utilities of Grails. I wanted to bind multiple values from a GSP form to a List inside a command object. My code looked something like this:

    <g:form>
     <g:textField name="bars[0].baz" />
     <g:textField name="bars[1].baz" /> 
     ...
    </g:form>
    class FooCommand {
      List<BarCommand> bars
    }
    
    class BarCommand {
      String baz
    }
    
    class FooController {
      def test(FooCommand cmd) {
        // ...
      }
    }

    In the controller I expected to get a FooCommand which contains two elements of BarCommand in the bars collection. Unfortunately this code resulted in an

    java.lang.IndexOutOfBoundsException, Message: Index: 0, Size: 0

    Reason for this is that the Grails data binding does not (like Spring) automatically create new list elements. Grails tries access the elements zero and one of the bars list during data binding. Since the list is empty an IndexOutOfBoundsException is thrown.

    The ugly workaround is to initialize bars with a couple of BarCommand instances:

    List bars = [new BarCommand(), new BarCommand()]

    However, this does only work if you know how much elements of the list will have. Luckily Groovy's List methods provide a better solution:

    List bars = [].withLazyDefault { return new BarCommand() }

    This creates an empty list that grows whenever it is called with a non-existent index value. So if Grails tries to access bars[0] and bars[1] during data binding these values will be initialized with a new BarCommand.

    Another point to note is that withLazyDefault fills gaps with null. This means the following form would result in a list with four elements where the third element is null

    <g:form>
     <g:textField name="bars[0].baz" />
     <g:textField name="bars[1].baz" />
     <!-- index 2 is missing -->
     <g:textField name="bars[3].baz" /> 
     ...
    </g:form>

    These null elements can easily be filtered in a controller using Groovy's grep() function:

    List listWithoutNullValues = cmd.bars.grep()

    grep() returns a new sublist of the elements that evaluate to true. Since null evaluates to false in Groovy all null elements are removed.