How can I pass my ReactiveSecurityContextHolder role to the mono webclient rest call?

537 views Asked by At

I am having Spring Cloud Gateway with a custom filter. In this filter, I try to call my webclient with a parameter. The roles from the ReactiveSecurityContextHolder. The getAccessToken result a

com.xy.HeaderGatewayFilter$apply$1$1.apply(HeaderGatewayFilter.kt:37).

If I just return "getAccessToken(webClient, "fixString" ).flatMap(chain::filter)" without the actual roles its working and returns an accessToken.

@Component
class HeaderGatewayFilter(@Autowired private val webClient: WebClient) : AbstractGatewayFilterFactory<HeaderGatewayFilter.Config>() {

    open class Config

    override fun apply(config: Config?): GatewayFilter {
        return OrderedGatewayFilter( { exchange, chain ->
           
            return@OrderedGatewayFilter getCurrentUserRole()
                    .map{rolle -> getAccessToken(webClient, rolle )
                    }
                    .map { accessToken ->
                        exchange.request
                                .mutate()
                                .header(HttpHeaders.AUTHORIZATION, "Bearer ${accessToken}")
                        return@map exchange
                    }.flatMap(chain::filter)
           },40)

fun getAccessToken(webClient: WebClient, rolle: String): Mono<String> {
            val map: MultiValueMap<String, String> = LinkedMultiValueMap()
            map.add("scope", "role:${rolle}")
            val inserter = BodyInserters.fromFormData(map)
            return webClient.post().body(inserter).retrieve().bodyToMono(Map::class.java).map {
                   it["access_token"] as String }
        }


    fun  getCurrentUserRole() : Mono<String> {
        return ReactiveSecurityContextHolder.getContext()
                .switchIfEmpty(Mono.error(IllegalStateException("Context is empty")))
                .map(SecurityContext::getAuthentication)
                .map(Authentication::getPrincipal)
                .cast(Jwt::class.java)
                .map {jwt -> 
                    return@map jwt.claims["realm_access"] as JSONObject
                }
                .map { realmAccess ->
                   return@map realmAccess["roles"] as JSONArray}
                .map { rollen -> rollen.first().toString() }
    }
1

There are 1 answers

0
Ringo777 On

Ok, i got it. Everything in my cascade has to return a Mono. I had a mapping, which returned a String, but now i changed it to Mono