Search code examples
javaredismicronaut

Unable to get Principal/Authentication when using session + redis persistence


I've been trying to follow Micronaut Security Session and Micronaut Redis Session to get session and security working with Redis persistence with no luck.

If I disable Redis persistence, I can get the Principal object and user is authenticated properly but if I enable Redis persistence, I can see the user is authenticated on Redis data, however I can never get the Principal object and always returns null

However when I enable Redis persistence, I can confirm that I can still get the correct Session object which is created and read from Redis properly (by visiting /anon endpoint I can see both authentication and session id value). I'm not sure what I'm doing wrong

Here's my application.yml file

---
micronaut:
  application:
    name: hello-world
  security:
    enabled: true
    endpoints:
      login:
        enabled: true
      logout:
        enabled: true
    session:
      enabled: true
      login-success-target-url: /
      login-failure-target-url: /login/authFailed
  session:
    http:
      cookie-name: supahsexy
      cookie: true
      redis:
        enabled: true
        namespace: 'myapp:sessions'
        write-mode: BACKGROUND
        enable-keyspace-event: false
        value-serializer: io.micronaut.jackson.serialize.JacksonObjectSerializer
---
redis:
  uri: redis://localhost

And for AuthenticationProviderUserPassword.java

@Singleton
public class AuthenticationProviderUserPassword implements AuthenticationProvider {
    @Override
    public Publisher<AuthenticationResponse> authenticate(AuthenticationRequest authenticationRequest) {
        if (authenticationRequest.getIdentity().equals("admin") && authenticationRequest.getSecret().equals("admin")) {
            var ud = new UserDetails((String) authenticationRequest.getIdentity(), List.of());
            return Flowable.just(ud);
        }
        return Flowable.just(new AuthenticationFailed());
    }
}

Finally this is the endpoints

@Controller("/")
public class HelloController {
    @Get("/")
    @Produces(MediaType.TEXT_PLAIN)
    @Secured(SecurityRule.IS_ANONYMOUS)
    public String index(Session session, @Nullable Principal principal) {
        System.out.println(principal);
        String username = principal != null? principal.getName() : "<anonymous>";
        session.put("session id", session.getId());
        return "Hello world " + username;
    }

    @Get("/blah")
    @Produces(MediaType.TEXT_PLAIN)
    @Secured(SecurityRule.IS_AUTHENTICATED)
    public String blah(Session session, @Nullable Principal principal) {
        System.out.println(session.asMap().toString());
        if (principal != null) {
            System.out.println(principal.getName());
        }
        return "Blah";
    }

    @Get("/anon")
    @Produces(MediaType.TEXT_PLAIN)
    @Secured(SecurityRule.IS_ANONYMOUS)
    public String anon(Session session) {

        return "Session = " + session.get("micronaut.AUTHENTICATION").orElse("no auth") + ", " + session.get("session id").orElse("no session id");
    }
}

Solution

  • This was a bug that was recently fixed https://github.com/micronaut-projects/micronaut-security/issues/47