Search code examples
oauth-2.0keycloakopenid-connectspring-cloud-gateway

How to use Spring Cloud Gateway for both APIs and UI


I am using Spring Cloud Gateway in front of APIs and UI. I want the UI paths to trigger the oidc flow where they are presented with the login screen from keycloak and so on. But when the APIs are called, I want the resource server flow. Can I configure Spring Cloud Gateway to treat both routes different. If yes, how?

I followed the following tutorial to setup API security jwt flow and I am using Keycloak as the Idp: https://blog.devops.dev/spring-cloud-gateway-oauth2-security-with-keycloak-jwt-tokens-and-securing-it-with-https-ssl-2166d8009531

Wherever I've looked it's one or the other in most of the tutorials available on the internet.


Solution

  • Neither OIDC nor resource server are flows. You are probably referring respectively to authorization_code flow for end-users login and requests authorization with Bearer token (which can be done whatever the flow used by the client to get tokens).

    As per latest recommandations, you shouldn't configure your SPA frontend as an OAuth2 client. You should use sessions (and CSRF protection), not tokens, to authorize requests from SPAs to your backend, but very few tutorials follow current best practices when it comes to OAuth2 and SPAs (or mobile apps).

    As you already figured out, spring-cloud-gateway can be configured as an OAuth2 client with oauth2Login. It can also be configured with TokenRelay filter on the routes to your resource servers to replace the session cookie with the access token in session before forwarding the request.

    I wrote a tutorial on Baeldung with spring-cloud-gateway configured as BFF for SPAs (Angular, React and Vue).

    What is not in this tutorial anymore is the case where you need to route both SPAs (authorized with sessions) and OAuth2 clients (authorized with tokens) through the gateway. The 2nd case is legit when you have a service running on a server you trust and itself configured as a confidential client (for instance a batch with client_credentials or a Thymeleaf UI).

    In such a case, you may define differents routes on your gateway redirecting to the same resource-servers:

    • one (let's say /bff/v1/**) with oauth2client and the TokenRelay filter for SPAs authorized with sessions. Such requests should be processed in an OAuth2 client filter-chain.
    • another one (let's say /resource-server/v1/**) transparent to security (neither oauth2client nor TokenRelay filter) for OAuth2 clients authorized with tokens. You may define another "stateless" filter-chain for such requests, to save the resources consumed to maintain sessions.

    See this other answer if you need instructions to configure more than one security filter-chain in a single Spring application (one with sessions and oauth2Login for /bff/** routes and another without sessions nor login for /resource-server/** routes)