3

Please bear with me while I explain my problem and the solutions/guides I have found.

Description: In my company, we have one product that have multiple modules. Each module is its separate backend and frontend. We have JavaEE/JakartaEE with JAX-RS as our backend stack and React as for our frontend. Until now we are using Basic Authentication using the JavaEE Security via Sessions, but because the product is evolving and we need mobile clients and allow third parties to access the data, we have decided to integrate OAuth2/OpenID Connect into our application.

Since there are multiple implementations out there that provide OAuth2 functionality, we are currently looking into a few available options. (Keycloak and ORY Hydra for example). The decision which we will choose depends on how much work we want to do change the existing structure of the application how we handle the users in the database. But regardless of which implementation we opt for, we have similar questions going forward.

Questions

  1. How do the react applications handle login process and token storage?

    Every documentation says: If the user is not logged in s/he is redirected to the login page. Where after login and consent he is redirected back to the app (After completing the oauth2 workflow obviously) with the Access/ID Token for the resource server and/or Refresh Token for refreshing the Access/ID Token.

    Now here is what is not clear to me:

    • Since this is our own React app, we do not want to show the consent screen, like in apps from Microsoft/Google etc you do not see any. I guess this is possible by setting a value in the request itself, or skipping the consent screen based on the client id but I just want to make sure.

    • Next is where do I store the Access and Refresh Token? Access Token should be sent as the Bearer token with each request. So it can be stored in local storage because they are short lived, but the refresh token should be stored securely. Like in a secure http cookie?. If that is the case, then the server has to set it. If this is correct is this how the flow will look like?

      Our React App (Not logged In) --> Login Page (Another React Page) --> User Enters Credentials --> Java Backend --> Authenticates the user --> Initiate the OAuth2 process --> Get the Access and Refresh Tokens --> Set them as secure Cookies --> Return the authenticated response to frontend with the cookies --> Login Page redirects to the previous page --> User continues with the app

      This does not feel correct. How would PKCE help in this case?

  2. Assuming what I wrote above is correct, I would need different login flows when the users logs in from our own app or from a third party app. That can however be determined by checking client ids or disabling password flow for third party clients.

  3. The same would be applicable then for the refresh token flow too. Because for my own app I have to set the cookies, for third parties this has to be directly from the OAuth Server

Resources I have read/researched:

https://gist.github.com/mziwisky/10079157

How does OAuth work?

Edit: Adding more links I have read

What is the purpose of implicit grant

Best practices for session management

RESTful Authentication

And of course various writings and examples from Keycloak and ORY Hydra also.

I am currently trying both Keycloak and ORY Hydra figuring out which fits our needs better.

Thank you all in advance!

varijkapil13
  • 390
  • 4
  • 16

2 Answers2

2
  1. You don't have to show the consent screen. Here's an example of a React app authenticating using the Authorization Code Grant: https://fusionauth.io/blog/2020/03/10/securely-implement-oauth-in-react (full disclosure, this is on my employer's site but will work with any OAuth2 compliant identity server).

The short answer is that it's best for you to avoid the implicit grant, and have the access and refresh tokens stored in some middleware, not the browser. The example in the link uses a 100 line express server and stores those tokens in the session.

I wrote a bit about PKCE. Excerpt:

The Proof Key for Code Exchange (PKCE) RFC was published in 2015 and extends the Authorization Code grant to protect from an attack if part of the authorization flow happens over a non TLS connection. For example, between components of a native application. This attack could also happen if TLS has a vulnerability or if router firmware has been compromised and is spoofing DNS or downgrading from TLS to HTTP. PKCE requires an additional one-time code to be sent to the OAuth server. This is used to validate the request has not been intercepted or modified.

  1. Here's a breakdown of the various OAuth options you have (again, this is on my employer's site but will work with any OAuth2 compliant identity server): https://fusionauth.io/learn/expert-advice/authentication/login-authentication-workflows You can allow different flows for different clients. For example, you could use the Authorization Code Grant for third parties and the Resource Owner Password Credentials grant (which essentially is username and password) for your own applications.

I'm not sure I answered all of your questions, but I hope that some of this is helpful.

mooreds
  • 4,932
  • 2
  • 32
  • 40
  • If I understand this correctly, the middleware used in the example is actually our backend then. It would work the same as I described in my question. The frontend sends the user to the login page, receives a code, sends it to the backend, the backend sends this code to the oauth server, and receives the tokens, sets them in a session and redirects the user where s/he wants to go. – varijkapil13 Apr 24 '20 at 19:21
  • 1
    Almost: The frontend sends the user to the login page, the backend receives a code from the OAuth server, the backend sends this code to the oauth server, and receives the access tokens, sets them in a session and redirects the user where s/he wants to go. Then any calls to an authenticated API that need the access token can be proxied through the middleware. The tokens are kept out of the react code entirely. – mooreds Apr 25 '20 at 16:43
1

The OAuth 2.0 Security Best Current Practice should be consulted. Even though it is still a "Internet Draft" it is mature and has been implemented by several vender implementations.

In general the OAuth 2.0 Authorization Code with PKCE Flow is the recommendation regardless of the use of Bearer tokens or JWT.

You should also consider reading about WebAuthn (Where there is not password)

Community
  • 1
  • 1
jwilleke
  • 10,467
  • 1
  • 30
  • 51
  • Definitely a great idea to read the best practices doc. Several of those recommendations are going to make it into OAuth 2.1. – mooreds Apr 25 '20 at 16:44