Search code examples
javasecuritymicronaut

Micronaut security fails to "secure"


I have a simple Micronaut- based "hello world" service that has a simple security built in (for the sake of testing and illustrating the Micronaut security). The controller code in the service that implements the hello service is provided below:

@Controller("/hello")
public class HelloController
{
   public HelloController()
   {
      // Might put some stuff in in the future
   }

    @Get("/")
    @Produces(MediaType.TEXT_PLAIN)
    public String index()
    {
       return("Hello to the World of Micronaut!!!");
    }
}

In order to test the security mechanism, I have followed the Micronaut tutorial instructions and created a security service class:

@Singleton
public class SecurityService
{
    public SecurityService()
    {
       // Might put in some stuff in the future
    }

    Flowable<Boolean> checkAuthorization(HttpRequest<?> theReq)
    {
        Flowable<Boolean> flow = Flowable.fromCallable(()->{
           System.out.println("Security Engaged!");
           return(false);    <== The tutorial says return true
        }).subscribeOn(Schedulers.io());

        return(flow);
    }

}

It should be noted that, in a departure from the tutorial, the flowable.fromCallable() lambda returns false. In the tutorial, it returns true. I had assumed that a security check would fail if a false is returned, and that a failure would cause the hello service to fail to respond.

According to the tutorials, in ordeer to begin using the Security object, it is necessary to have a filter. The filter I created is shown below:

@Filter("/**")
public class HelloFilter implements HttpServerFilter
{
   private final SecurityService secService;

   public HelloFilter(SecurityService aSec)
   {
      System.out.println("Filter Created!");
      secService = aSec;
   }

   @Override
   public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> theReq, ServerFilterChain theChain)
   {
      System.out.println("Filtering!");
      Publisher<MutableHttpResponse<?>> resp = secService.checkAuthorization(theReq)
                                                         .doOnNext(res->{
                                                            System.out.println("Responding!");
                                                         });

      return(resp);
   }
}

The problem occurs when I run the microservice and access the Helo world URL. (http://localhost:8080/hello) I cannot cause the access to the service to fail. The filter catches all requests, and the security object is engaged, but it does not seem to prevent access to the hello service. I do not know what it takes to make the access fail.

Can someone help on this matter? Thank you.


Solution

  • You need to change request in your filter when you no have access to resource or process request as usual. Your HelloFilter looks like this:

    @Override
    public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> theReq, ServerFilterChain theChain) {
        System.out.println("Filtering!");
        Publisher<MutableHttpResponse<?>> resp = secService.checkAuthorization(theReq)
                .switchMap((authResult) -> { // authResult - is you result from SecurityService
                    if (!authResult) {
                        return Publishers.just(HttpResponse.status(HttpStatus.FORBIDDEN)); // reject request
                    } else {
                        return theChain.proceed(theReq); // process request as usual
                    }
                })
                .doOnNext(res -> {
                    System.out.println("Responding!");
                });
    
        return (resp);
    }
    

    And in the last - micronaut has security module with SecurityFilter, you can use @Secured annotations or write access rules in configuration files more examples in the doc