grpc-spring-boot-starter icon indicating copy to clipboard operation
grpc-spring-boot-starter copied to clipboard

PreAuthorize expression not finding bean reference

Open pcalouche opened this issue 2 years ago • 7 comments

I'm receiving this error Caused by: org.springframework.expression.spel.SpelEvaluationException: EL1057E: No bean resolver registered in the context to resolve access to bean 'securityService' when trying to access an existing bean inside a @PreAuthorize annotation. I've used this pattern before on REST controllers. Using hasRole works as expected, so I think I have my security setup correctly. I'm curious if this is a known issue or limitation. I'm using Spring Boot 2.7.3 and Java 17.

UPDATE: Here is a sample project that demonstrates this https://github.com/pcalouche/grpc-starter

Thanks for hard work on this library.

// Example bean used in PreAuthorize expression
public class SecurityService {
  public boolean allow(AuthenticatedPrincipal principal) {
    // more complex stuff could be here
    return true;
  }

  public boolean block(AuthenticatedPrincipal principal) {
    // more complex stuff could be here
    return false;
  }
}
// Security configuration
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig {
  @Bean // registered bean
  public SecurityService securityService() {
    return new SecurityService();
  }

  @Bean
  public InMemoryUserDetailsManager userDetailsService() {
    PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
    UserDetails user =
        User.withUsername("user")
            .password(passwordEncoder.encode("password"))
            .roles("ADMIN")
            .build();
    return new InMemoryUserDetailsManager(user);
  }

  @Bean
  public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeRequests().anyRequest().authenticated().and().httpBasic();

    return http.build();
  }

  @Bean
  public AuthenticationManager authenticationManager(
      AuthenticationConfiguration authenticationConfiguration) throws Exception {
    return authenticationConfiguration.getAuthenticationManager();
  }
}
@GRpcService
@Slf4j
public class GreetingService extends GreetingServiceGrpc.GreetingServiceImplBase {
  @PreAuthorize("@securityService.allow(#principal)") // does not work
  //  @PreAuthorize("hasRole('ADMIN')") // works as expected
  public void sayHello(GreetingRequest request, StreamObserver<GreetingResponse> responseObserver) {
    GreetingResponse reply =
        GreetingResponse.newBuilder().setMessage("Acknowledging " + request.getMessage()).build();
    responseObserver.onNext(reply);
    responseObserver.onCompleted();
  }
}
@RestController
@RequestMapping("test")
public class TestController {

  @PreAuthorize("@securityService.block(#principal)") // works as expected
  // @PreAuthorize("hasRole('ADMIN')") // works as expected
  @GetMapping
  public String hello() {
    return "Hello";
  }
}
syntax = "proto3";

package net.energyhub.example.grpc.protos;

option java_multiple_files = true;
option java_package = "net.energyhub.example.grpc.protos";

service GreetingService {
  rpc sayHello(GreetingRequest) returns (GreetingResponse){}
}

message GreetingRequest {
  string message = 1;
}

message GreetingResponse {
  string message = 1;
}

pcalouche avatar Sep 22 '22 18:09 pcalouche

I don't see you inherit GrpcSecurityConfigurerAdapter and configuring GrpcSecurity

jvmlet avatar Sep 22 '22 19:09 jvmlet

I had this at one point, but it didn't make a difference from what I could tell. Basic auth with something like @PreAuthorize("hasRole('ADMIN')") works fine with out this two, which I find confusing.

I would not doubt I'm missing something else here. I can work on getting the entire project posted in a public repo. It's in a private work repo at the moment.

@Configuration
public class CustomGrpcSecurityConfigurerAdapter extends GrpcSecurityConfigurerAdapter {

  @Override
  public void configure(GrpcSecurity builder) throws Exception {
    builder.authorizeRequests().anyMethod();
  }
}

pcalouche avatar Sep 22 '22 21:09 pcalouche

I'll try to reproduce it in this repo

jvmlet avatar Sep 23 '22 07:09 jvmlet

Btw. I updated the original post with a sample repo that demonstrates this. This is the repo https://github.com/pcalouche/grpc-starter.

pcalouche avatar Oct 06 '22 19:10 pcalouche

404

jvmlet avatar Oct 06 '22 19:10 jvmlet

My apologies. It should be public now.

pcalouche avatar Oct 06 '22 20:10 pcalouche

Thanks, @pcalouche , I'll be able to have a look after 14/10 (vacation )

jvmlet avatar Oct 06 '22 20:10 jvmlet

Please try with 4.9.1-SNAPSHOT I've also added test that uses current Authentication object to make access decision.

jvmlet avatar Oct 16 '22 10:10 jvmlet

@jvmlet The changes in 4.9.1-SNAPSHOT worked for me. Thank you so much for addressing this issue.

pcalouche avatar Oct 17 '22 01:10 pcalouche

4.9.1 was released

jvmlet avatar Dec 05 '22 07:12 jvmlet