Search code examples
securityoauth-2.0

Oauth2.0 Authentication Flow problems


I am struggeling with a design problem regarding the Oauth2 Authentication Flow. A little bit of background: We are developing a Client with React and a backend with java (spring boot). There will be ONLY an oauth2 based login with an oauth2 server like keycloak h osted in our AWS.

Now to the problem:

As we are using REST and therefore a stateless approach, th client seems to be in the position to make any Oauth2 requests to the keycloak. This leads to a security issue, at least in my head. As the client gets the code from the keycloak, and later the token of the keycloak (which can be used as sso in our whole company) the token will be very easy to grap . I would like to see the Oauth2 requests in the backend, as the backend will provide another JWT token just for the basic communication between client and server..

So the question is, are there any more secure ways to deal with oauth2? The backend is not able to trigger anything in the frontend (stateless and async).


Solution

  • The answer is "Yes, there is more secure ways to deal with oauth2" <:oD

    To be more constructive, a quite popular pattern lately is called Backend For Frontend and does just what you are looking for. I even wrote a tutorial for it on Baeldung with sample implementations for Angular, React (Next.js) and Vue.

    Here is how it works:

    • setup a middleware on your server (the BFF)
    • configure the BFF as an OAuth2 client
    • the BFF keeps sessions for front-ends: requests between browser and BFF are authorized with secured (exchanged over https only), http-only (not readable by Javascript code) and ideally same-site session cookies. It should also be protected against CSRF attacks (CSRF token accessible to Javascript code with a value to return as X-XSRF-TOKEN header to POST / PUT / DELETE requests).
    • the BFF handles login, logout and tokens storage (usually in session)
    • the BFF replaces on the fly the session cookie with a Bearer access token before forwarding a request from a front-end to a resource server.

    This solves two security issues:

    • the OAuth2 client running on a server you trust, can use a secret and be "confidential": neither mobile apps nor Javascript based applications in a browser can keep a secret and must be configured as "public" clients, which means that anyone tricking a user to get an authorization-code can easily turn it into tokens (access, ID and refresh)
    • tokens are kept on the server (by the BFF) and never exposed to Javascript code or even to the browser (as a contrast, the session cookie used to authorize requests will be exposed to the browser but hidden from Javascript).

    As you are using React and Spring, I see two natural choices:

    • use Next.js OAuth where the OAuth2 client is the node part of the app (on the server)
    • use spring-cloud-gateway with spring-boot-starter-oauth2-client and TokenRelay= filter

    I have a personal inclination for the second option, which I believe to be more scalable and more polyvalent (sessions can be shared across instances using spring-session, it works with React apps without a node part on the server and also with Angular or Vue apps, etc.).

    No need for Javascript lib to drive authorization_code flow, store or renew tokens (this is done by the BFF), and nothing to do to authorize requests as the session cookie is automatically attached to the request by the browser.