title: Spring Boot: Configure custom MethodSecurityExpressionOperations?
body: <p>I am trouble shooting a spring boot security configuration that I once had working, but now is not recognizing my custom definitions. My goal was to protect all of our Services with method level security in Spring with custom annotations.</p>
  
  <p>When I start the service my CustomMethodSecurityConfig is instantiated and does call createExpressionHandler(), but when I make the request to the service it does not call createSecurityExpressionRoot(...) on my CustomMethodSecurityExpressionHandler, but on the DefaultWebSecurityExpressionHandler.</p>
  
  <p>I appreciate any insights anyone may be able to provide as to why Spring Security is not recognizing my expressions defined in my CustomMethodSecurityExpressionRoot.</p>
  
  <p>Here is a snippet of my GlobalMethodSecurityConfiguration class</p>
  
  <pre><code>@Configuration
  @EnableGlobalMethodSecurity(prePostEnabled = true)
  public class CustomMethodSecurityConfig extends GlobalMethodSecurityConfiguration {
  
    private final MyService1 myService1;
    private final MyService2 myService2;
    private final MyService3 myService3;
  
    @Autowired
    public CustomMethodSecurityConfig(MyService1 myService1, MyService2 myService2,
                                      MyService3 myService3) {
      this.myService1 = myService1;
      this.myService2 = myService2;
      this.myService3 = myService3;
    }
  
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
      CustomMethodSecurityExpressionHandler expressionHandler =
          new CustomMethodSecurityExpressionHandler(myService1, myService2, myService3);
      expressionHandler.setPermissionEvaluator(permissionEvaluator());
      return expressionHandler;
    }
  }
  </code></pre>
  
  <p>Here is a snippet of my DefaultMethodSecurityExpressionHandler class</p>
  
  <pre><code>public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler {
  
    private final MyService1 myService1;
    private final MyService2 myService2;
    private final MyService3 myService3;
    private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
  
    public CustomMethodSecurityExpressionHandler(MyService1 myService1, MyService2 myService2,
                                                 MyService3 myService3) {
      this.myService1 = myService1;
      this.myService2 = myService2;
      this.myService3 = myService3;
    }
  
    @Override
    protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authentication authentication,
                                                                              MethodInvocation invocation) {
      CustomMethodSecurityExpressionRoot root = new CustomMethodSecurityExpressionRoot(authentication,
                                                                                       myService1,
                                                                                       myService2,
                                                                                       myService3);
  
      root.setPermissionEvaluator(getPermissionEvaluator());
      root.setTrustResolver(this.trustResolver);
      root.setRoleHierarchy(getRoleHierarchy());
  
      return root;
    }
  }
  </code></pre>
  
  <p>Here is the snippet of my SecurityExpressionRoot, this is where I am defining my SpEL expressions which I use in annotations on my Services. I have only included a simplified, isUser as an example. What these methods do isn't important, but the fact that they are visible.</p>
  
  <pre><code>public class CustomMethodSecurityExpressionRoot extends SecurityExpressionRoot
      implements MethodSecurityExpressionOperations {
  
    private Object filterObject;
    private Object returnObject;
  
    private MyService1 myService1;
    private MyService2 myService2;
    private MyService3 myService3;
  
    public CustomMethodSecurityExpressionRoot(
        Authentication authentication,
        MyService1 myService1,
        MyService2 myService2,
        MyService3 myService3) {
      super(authentication);
      this.myService1 = myService1;
      this.myService2 = myService2;
      this.myService3 = myService3;
    }
  
    @Override
    public Object getFilterObject() {
      return this.filterObject;
    }
  
    @Override
    public Object getReturnObject() {
      return this.returnObject;
    }
  
    @Override
    public void setFilterObject(Object obj) {
      this.filterObject = obj;
    }
  
    @Override
    public void setReturnObject(Object obj) {
      this.returnObject = obj;
    }
  
    @Override
    public Object getThis() {
      return this;
    }
  
    //All custom SpEL methods
    public boolean isUser(Long userId) {
      SecurityUser user = (SecurityUser) this.getPrincipal();
      return user.getUserId() == userId;
    }
  
    ...
  
  }
  </code></pre>
  
  <p>And finally here is a snippet of my WebSecurityConfigurerAdapter which is used in tandem, it verifies the external authentication token from our UAA server.</p>
  
  <pre><code>@Configuration
  @EnableWebSecurity
  @EnableGlobalMethodSecurity(
      prePostEnabled = true,
      proxyTargetClass = true)
  public class ServiceSecurityConfig extends WebSecurityConfigurerAdapter {
  
    private final TokenCheckService _tokenCheckService;
  
    @Autowired
    ServiceSecurityConfig(TokenCheckService tokenCheckService) {
      _tokenCheckService = tokenCheckService;
    }
  
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.authenticationProvider(new TokenAuthenticationProvider(_tokenCheckService));
    }
  
    @Override
    public void configure(WebSecurity web) throws Exception {
      web.ignoring().antMatchers(HttpMethod.OPTIONS, "/api/**");
    }
  
    @Override
    protected void configure(HttpSecurity http) throws Exception {
          http
              .anonymous()
                .disable()
              .csrf()
                .disable()
              .exceptionHandling()
                .authenticationEntryPoint(new UnAuthorizedEntryPoint())
                .and()
              .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
              .authorizeRequests()
                .anyRequest().authenticated();
      http.addFilterBefore(new AuthenticationTokenFilter(), BasicAuthenticationFilter.class);
    }
  }
  </code></pre>
  
  <p>Edit:
  I seem to think it is an issue with my WebDecisionVoters being overridden during intialization. If I have a breakpoint in the Affirmative constructor</p>
  
  <pre><code>AffirmativeBased(List&lt;AccessDecisionVoter&lt;? extends Object&gt;&gt; decisionVoters)
  </code></pre>
  
  <p>I can see AffirmativeBased being instantiated with 3 decision voters, one of which is a PreInvocationAuthorizationAdviceVoter, which contains a reference to my expression handler. I believe this is being created by bean instantiation of the methodSecurityInterceptor.</p>
  
  <p>When I continue the breakpoint I again hit the same Affirmative based constructor, but with only one decision voter, a WebExperssionVoter with a reference to an instance of DefaultWebSecurityExpressionHandler. I believe this is being created by bean instantiation of the springSecurityFilterChain.</p>