IcedDante
IcedDante

Reputation: 6842

Is a Secure Oauth2 Web App Flow with FE and BE the right approach?

We have a Web Application that mints an internal JWT used for authentication along with a secure cookie. As the organization has been moving to Okta there is an ask to integrate that login flow into our app.

Our current workflow:

It poses a lot of challenges. After some analysis, I think I see how I want to approach it:

Does this flow make sense? Is it safe? Most literature and examples I see tend to involve SPA or integrate everything in the BE.

Because of the opaqueness of the Spring oauth2 integration I am favoring avoiding that for now and manually constructing my POST call to the /token endpoint.

Upvotes: 0

Views: 723

Answers (2)

ch4mp
ch4mp

Reputation: 12835

According to latest recommendations, OAuth2 clients (applications to which tokens are delivered and which store those tokens) should be "confidential" (secured with some sort of secret). This requires it to run on a server you trust (neither Javascript based apps in a browser nor mobile apps can keep a secret).

This means that, to follow OAuth2 best practices, your React app should not be an OAuth2 client nor have access to tokens. Its requests to the backend should be authorized with session cookies (which requires protection against CSRF attacks).

A noticeable exception being Next.js apps using the NextAuth lib which handles authorization code and tokens storage server side (node) with a confidential client, and use session cookies for communication between the browser and server parts of the app.

The solution I detail in this Baeldung article, is to configure a spring-cloud-gateway instance as an OAuth2 BFF (runs authorization code and refresh token flows, stores tokens, and bridges between cookie-based authorization (requests from the frontend) and Bearer-based authorization (requests forwarded to downstream resource servers). This is the exact same pattern as what NextAuth does for Next.js, but probably more scalable and easier to instrument with observability (also works with any frontend framework, not just Next.js).

When user authentication is required:

  • the Javascript based app exits by setting the window location to an URI on the gateway to initiate authorization_code flow
  • the gateway redirects to the authorization server (Okta in your case)
  • after the user authenticated, the authorization server redirects back to the gateway with authorization-code
  • the gateway exchanges the authorization-code for tokens and store it in session
  • the gateway redirects back to the React app

With this pattern, requests are protected with:

  • sessions (and CSRF, but not tokens) between the front-end (React, Angular, Vue, etc.) and the gateway
  • tokens (not sessions nor CSRF) between the gateway and downstream REST APIs (which should be configured as stateless resource servers).

If you inspect about any serious OAuth2 app with your browser debugging tools (Gmail, Facebook, LinkedIn, etc.), you'll find session cookies but no Authorization header with a Bearer token. You won't even find an OAuth2 token anywhere in your browser. The reason is that they apply this pattern...

Upvotes: 2

Matt Raible
Matt Raible

Reputation: 8634

I wouldn't recommend minting your own JWT. I would recommend packaging your frontend and backend together and doing all your authentication on the backend. Especially if your apps live on the same host. If they can't live on the same host, do the authentication in your frontend and pass an access token to the backend.

These two tutorials show how to package the apps together while maintaining the development workflow of working on them separately.

This tutorial shows how to do all the authentication on the frontend:

Please let me know if this helps!

Upvotes: 0

Related Questions