I have experience with server-rendered applications where, after logging in with a username and password or through an OAuth provider (like Facebook), the server sets a session cookie while redirecting to the intended page. Now, I am attempting to create a more modern application using React on the front end and a JSON API backend. It seems that utilizing a JSON web token for authentication is the standard practice, but I’m facing challenges figuring out how to send the JWT to the client so it can be saved in session or local storage.
Here’s an example to clarify my situation:
User clicks to log in via Facebook at /auth/facebook.
The user is redirected to the Facebook login dialog.
Facebook returns the user to /auth/facebook/callback with an authorization code.
The server exchanges this for an access token and retrieves user information.
The server then finds or creates the user in the database and issues a JWT containing essential user details (like user ID).
???
I want the user to seamlessly navigate to the main page of the React application (e.g., /app) with the JWT included. However, I’m unsure how to achieve this without compromising the JWT. One option I considered was appending it to the query string of the redirect (like /app?token=...), but that would reveal it in the address bar until I remove it using something like replaceState(), which seems odd. I’m looking for the best practice regarding how to transfer this token to the client post-OAuth redirect when using Passport. The backend setup uses Node with Koa and Passport.
From my experience, sending the token as part of the response body in a JSON format upon successful authentication is an effective method. Once the client receives the token in the JSON response, it can store the token in sessionStorage or localStorage. This offers a straightforward approach, although it requires ensuring your API uses HTTPS to keep the token secure in transit. This method keeps the token out of the URL and allows for easy access by your client-side code whenever you need to attach the JWT to subsequent requests.
another way is leveraging websockets, if your app has real-time features. After authentication, server can push JWT directly to the client. It’s effective for non-HTTP processes, ensuring token isn’t exposed in URLs. Keep in mind this approach needs extra setup but can enhance security and real-time comms.
Have you thought about using httpOnly cookies instead? They make storing JWTs more secure as they’re not accessible via JavaScript. Upon authenticating, the server can set the token in a cookie, and you can just access it on the client-side as needed. What do others think of this approach?
You can also use secure cookies with SameSite policies if you want to ensure the best security. It restricts the JWT to be sent with cross-site requests, mitigating CSRF risks. Also, use a state param in the OAuth flow for additional security measures against CSRF.
Have any of you tried splitting the token in a custom header during redirects, similar to how headers are usually used in AJAX calls? This may keep it secure while avoiding exposure in the URL. Can it be a more efficient method than those suggested so far? Curious to know your thoughts!