Extract Principal from the request in WebFlux

979 views Asked by At

So I am using webflux and I have a filter where I am logging all the requests. When logging an authenticated request I try exctract the principal from the request object which is a Mono I tried to get the value by using .block method but I got an error "IllegalStateException" i tried to use .map and doOnNext but these are not being called. How do i get the Princial value out

1

There are 1 answers

0
switang On

Had the same issue and was able to piece together a solution mainly from this answer: https://stackoverflow.com/a/59011016/1169966

//Inside your filter's public Mono<Void> filter method...

var requestDetails = "Some request details: ";

return exchange.getPrincipal()
        .defaultIfEmpty(NO_PRINCIPAL) //Custom No Principal instance
        .flatMap(principal -> {
            requestDetails.append(String.format("Principal: [%s]", getPrincipalInfoFromToken(principal))); //Using custom helper method
            return chain.filter(exchange);
        })
        .then(Mono.fromRunnable(() -> LOGGER.atDebug().log("{}", requestDetails))); //Could just execute in the flatMap since we are defaulting

});

The closure you pass to flatMap will have an actual Principal object in that context.

Also note on that answer the comment about how you shouldn't subscribe as you are not the initiator/client.

I thought I had the solution with this but obviously it was always resulting in a null principal:

//No worky
ReactiveSecurityContextHolder.getContext()
        .log()
        .map(SecurityContext::getAuthentication)
        .map(Principal::getName)
        .defaultIfEmpty("Principal Not Available")
        .doOnSuccess(name ->
                LOGGER.info(String.format("UUID:[%s] | Principal:[%s]", uuid, name)))
        //Doesn't work
        .subscribe(name ->
                LOGGER.info(String.format("UUID:[%s] | Principal:[%s]", uuid, name)));