mscharhag, Programming and Stuff;

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

Posts tagged with Spring Security

  • Thursday, 15 October, 2020

    Spring Security: Delegating authorization checks to bean methods

    In this post we will learn how authorization checks can be delegated to bean methods with Spring Security. We will also learn why this can be very useful in many situations and how it improves testability of our application. Before we start, we will quickly look over common Spring Security authorization methods.

    Spring Security and authorization

    Spring Security provides multiple ways to deal with authorization. Some of them are based on user roles, others are based on more flexible expressions or custom beans. I don't want to go into details here, many articles are already available on this topic. Just to give you a quick overview, here are a few commented examples of common ways to define access rules with Spring Security:

    Restricting URL access via a WebSecurityConfigurerAdapter:

    public class SecurityConfig extends WebSecurityConfigurerAdapter {
        
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()
            
                // restrict url access based on roles
                .antMatchers("/internal/**").hasRole("ADMIN")
                .antMatchers("/projects/**").hasRole("USER")
                
                // restrict url access based on expression
                .antMatchers("/users/{username}/profile")
                    .access("principal.username == #username");            
        }
    }

    Using annotations to restrict access to methods:

    @Service
    public class SomeService {
    
        // Using Springs @Secured annotation for role checks
        @Secured("ROLE_ADMIN")
        public void doAdminStuff() { }
    
        // Using JSR 250 RolesAllowed annotation for role checks
        @RolesAllowed("ROLE_ADMIN")
        public void doOtherAdminStuff() { }
    
        // Using Springs @PreAuthorize annotation with an expression 
        @PreAuthorize("hasRole('ADMIN') and hasIpAddress('192.168.1.0/24')")
        public void doMoreAdminStuff() { }
        
        // Using an expression to delegate to a PermissionEvaluator bean
        @PreAuthorize("hasPermission(#stuff, 'write')")
        public void doStuff(Stuff stuff) { }
    }

    What to use when?

    If roles are the only thing you need, it is easy. You just need to decide if you prefer defining the required roles based on URLs or based on methods in your Java code. If you prefer the later, just pick one annotation and use it consistently.

    In case you need some ACL-like security (e.g. User x has permission y on object z) using @PreAuthorize with hasPermission(..) and a custom PermissionEvaluator is often a good choice. Also, have a look at the Spring Security ACL support.

    However, there is a huge field between both approaches where roles are not enough but ACLs might be too fine grained or just the wrong tool. Here are a few example authorization rules that do not fit well into both solutions:

    Access to a resource should only be given ..

    • .. to the owner of the resource (e.g. a user can only change his own profile)
    • .. to users with role x from department y
    • .. during standard business times
    • .. to administrators who signed in using two-factor authentication
    • .. to users who connect from specific IP addresses

    All those examples can probably be solved by building a security expression and passing it to @PreAuthorize. However, in practice it is often not that simple.

    Let us look at the last example (the ip address check). The previously shown code snippet contains a @PreAuthorize example that does exactly this:

    @PreAuthorize("hasRole('ADMIN') and hasIpAddress('192.168.1.0/24')")
    

    This looks nice as an example and shows what you can do with security expressions. However, now consider:

    • You possibly need to define more than one IP range. So, you have to combine multiple hasIpAddress(..) checks.
    • You probably do not want to hard-code IP addresses in your code. Instead they should be resolved from configuration properties.
    • It is likely that you need the same access check in different parts of your code. You probably do not want it to duplicate it over and over.

    In other cases you might need to do a database look-up or call another external system to decide if a user is allowed to access a resource.

    Simple expressions are fine. However, if they get larger and are scattered all over a code base they can become painful to maintain.

    Side note: Spring Security implements method security by proxying the target bean. Security checks are then added via the proxy. If you don't know about proxies, you should probably read my post about the Proxy pattern.

    Delegating access decisions to beans

    Within security expressions we can reference beans using the @beanname syntax. This feature can help us to implement the previously described authentication rules.

    Let's look at an example:

    @Service
    public class ProjectService {
    
        @PreAuthorize("@projectAccess.canUpdateProjectName(#id)")
        public void updateProjectName(int id, String newName) {
            ...
        }
        
        @PreAuthorize("@projectAccess.canDeleteProject(#id)")
        public void deleteProject(int id) {
            ...
        }
    }

    Here we define a ProjectService class with two methods, both annotated with @PreAuthorize. Within the security expression we delegate the access check to methods of a bean named projectAccess. Relevant method parameters (here id) are passed to projectAccess methods.

    projectAccess looks like this:

    @Component("projectAccess")
    public class ProjectAccessHandler {
    
        private final ProjectRepository projectRepository;
        private final AuthenticatedUserService authenticatedUserService;
    
        public ProjectAccessHandler(ProjectRepository repo, AuthenticatedUserService aus) {
            this.projectRepository = repo;
            this.authenticatedUserService = aus;
        }
    
        public boolean canUpdateProjectName(int id) {
            return isProjectOwner(id);
        }
    
        public boolean canDeleteProject(int id) {
            return isProjectOwner(id);
        }
    
        private boolean isProjectOwner(int id) {
            User user = authenticatedUserService.getAuthenticatedUser();
            Project project = projectRepository.findById(id);
            return (project.getOwner().equals(user.getUsername()));
        }
    }

    It is a simple bean with two public methods that are called via security expressions. In both cases only the owner of the project is allowed to perform the operation. To determine the project owner we first have to look-up the related project by using a ProjectRepository bean.

    The injected AuthenticatedUserService is a simple facade around Spring Security's SecurityContextHolder:

    @Service
    public class AuthenticatedUserService {
        public User getAuthenticatedUser() {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            return (User) authentication.getPrincipal();
        }
    }

    This cleans up our code a little bit because it removes Spring Security internals (and the type cast) from our access control logic. It also becomes helpful when writing unit tests. This way we do not have to deal with static method calls during tests.

    Note we use the standard Spring Security User class for simplicity in this example. Often it is a good idea to create your own customized class as principal. However, this is something for another blog post.

    Testing access rules

    Another important benefit of this approach is that we can test access rules in simple unit tests. No Spring application context is required to evaluate @PreAuthorize expressions. This speeds up tests a lot.

    A simple test for canUpdateProjectName(..) might look like this:

    public class ProjectAccessHandlerTest {
    
        private ProjectRepository repository = mock(ProjectRepository.class);
        private AuthenticatedUserService service = mock(AuthenticatedUserService.class);
        private ProjectAccessHandler accessHandler = new ProjectAccessHandler(repository, service);
        private User john = new User("John", "password", Collections.emptyList());
    
        @Test
        public void canUpdateProjectName_isOwner() {
            Project project = new Project(1, "John", "John's project");
            when(repository.findById(1)).thenReturn(project);
            when(service.getAuthenticatedUser()).thenReturn(john);
            assertTrue(accessHandler.canUpdateProjectName(1));
        }
    
        @Test
        public void canUpdateProjectName_isNotOwner() {
            Project project = new Project(1, "Anna", "Anna's project");
            when(repository.findById(1)).thenReturn(project);
            when(service.getAuthenticatedUser()).thenReturn(john);
            assertFalse(accessHandler.canUpdateProjectName(1));
        }
    }

    Summary

    Many authorization requirements cannot be solved by using roles alone and ACLs often do not fit. In those situation it can be a viable solution to create separate beans for handling access checks. With @PreAuthorize we can delegate the authorization check to those beans. This also simplifies writing tests as we do not have to create a Spring application context to test authorization constraints.

    You can find the shown example code on GitHub.

  • Sunday, 5 March, 2017

    Be aware that bcrypt has a maximum password length

    bcrypt is a popular password hashing function these days. Other than standard hash functions (like SHA-515), bcrypt is designed to be slow and therefore very resistant to brute force attacks.

    However, when using bcrypt you should be aware that it limits your maximum password length to 50-72 bytes. The exact length depends on the bcrypt implementation you are using (see this stackexchange answer).

    Passwords that exceed the maximum length will be truncated.

    The following piece of code shows the password truncation using Spring Securities BCryptPasswordEncoder:

    BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    
    // 72 characters
    String password1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
    
    // 73 characters
    String password2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab";
    
    String encodedPassword1 = passwordEncoder.encode(password1);
    boolean matches = passwordEncoder.matches(password2, encodedPassword1);
    
    System.out.println("encodedPassword1: " + encodedPassword1);
    System.out.println("matches: " + matches);
    

    When running this example, the output might look like this:

    encodedPassword1: $2a$10$A5OpVKgjEZzmy6UNsqzkjuG2xGET1wp3b/9ET5dz/tHQ3eRvyXSSO
    matches: true
    

    According to BCryptPasswordEncoder both passwords match (= are identical) even if they have a different length.

  • 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.

  • 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.