springspring-bootamazon-cognitospring-webfluxaccess-token

How to get JWT token in BFF architecture Spring Webflux


I have implemented a Backend for Frontend (BFF) architecture with Spring Webflux using TokenRelay filter. My frontend communicates with the BFF with a cookie as authentication mechanism and the BFF gets the JWT token from Cognito (or stored in the Spring session, not sure. It is magic for me) and sends it in a header to the resource servers. Here the BFF node is working as a confidential oauth2 client, and the browser don't need to store any JWT token or similar.

This is done transparently for me as a developer. It is configured properly and working without any issue. If I make a request to https://bff-url/api/users/{user-id} from the frontend, it works, redirecting automatically to users microservice and attaching the token in the header.

However, lets consider an endpoint which is not in any resource server (microservice). This endpoint is in the BFF.

This endpoint url is https://bff-url/api/auth/me. I have defined as follows:

@RestController
@RequestMapping("/api/auth")
public class CurrentUserController {

public CurrentUserController() {
}

@GetMapping("/me")
@ResponseBody
public Mono<UserResponseDTO> getCurrentUser(Authentication authentication) {
    String userId = ((DefaultOidcUser)authentication.getPrincipal()).getClaim("custom:userId");
    // TODO call to users service users with this userId
    return Mono.empty();
  }
}

I just want to get the id from the session (I get it) and call the users service as usual. I don't know which is the best approach to do:

I'm open to any other approach according to Spring guidelines since I'm not a Spring expert and I'm probably missing something.


Solution

  • How to get JWT token in BFF

    The easiest way is to use the TokenRelay filter to have Spring Cloud Gateway attach it as Bearer Authorization header to a downstream resource server.

    the BFF gets the JWT token from Cognito (or stored in the Spring session, not sure. It is magic for me)

    Both: the BFF is an OAuth2 client configured to use authorization code flow (oauth2Login in Spring Security wording) => this is how it initially gets tokens from the authorization server (further tokens might be obtained using the refresh token flow). It then stores these tokens in sessions. So, for further requests to the BFF, tokens are read in session (unless it is expired or will be within the next minute).

    I'm open to any other approach according to Spring guidelines since I'm not a Spring expert and I'm probably missing something.

    The easy way is to use the BFF solely for routing purposes (adapting session cookie / Bearer authorization on the fly) and host this /me in a downstream resource server. As the TokenRelay attaches an access token for the current user, all that is needed in a downstream resource server is to reflect the access token claims (all of it or probably better, just the necessary ones). This is what I do in this Baeldung article dedicated to the OAuth2 BFF pattern, in this other project, and actually at many other places.

    If you prefer to stick with the /me endpoint on the BFF, two options (but none is as simple and scalable as the one above):