Photo by Carlos Muza on Unsplash
Saving and using custom data before and after redirecting users to external services with Remix
If you've read my other two articles on how to create toast notifications and confetti rain in Remix you would've noticed a common pattern I used among them, and that pattern is flash storage.
In today's article, I will show you a little trick on how you can store a custom flash session before you send a user to a third-party service without passing the info along and then parsing it on user return.
For this article, I will use Auth0 Universal login using remix-auth as an example and a redirectTo param that would redirect the user back to where he was after he logs in, but you can store whatever you need into the session and consume it later on.
So the approach is the same as in this article:
https://alemtuzlak.hashnode.dev/handling-toasts-in-remix
If you haven't read it I recommend you skim over the flash storage part so you understand what we're doing!
First of all, let's assume you have a route "login.tsx", and if the user is inactive for a while you log him out and send him to that route. On that route we naturally want to send the user to Auth0 for him to log in. Let's also asume he was on a custom route, let's say "/dasbhoard", so what we want to do is send the user to Auth0, and when he is back and logged in we want him to be back on the dashboard as if nothing happened.
Implementing the redirectTo behavior is out of scope of this article but let's assume you get it from the url as a search parameter. Well, let's first implement what we need in the flash-session.server.ts file:
// Schema to validate the flash session storage
const flashSessionValuesSchema = z.object({
// validation schema from above
toast: toastMessageSchema.optional()
// we add a redirectTo (this is the part where it can be whatever you need)
redirectTo: z.string().optional()
});
Alright, so now all we have to do is the following in our "login.tsx":
export const loader ({ request }: LoaderArgs) => {
// We generate the URL object to easily extract search params
const url = new URL(request.url);
// We get the redirectTo
const redirectTo = url.searchParams.get("redirectTo");
// We do not consume the headers from the flash so it is kept in flash storage until used
const { flash } = await getFlashSession(request);
// The url contains no redirect path or the redirectTo has already been stored, we directly redirect to the auth0 login page
if (!redirectTo || flash?.redirectTo) {
return authenticator.authenticate("auth0", newRequest, {
failureRedirect: "/login"
});
}
// We redirect back to here to store the redirect path in the flash session
return redirectWithFlash(PATH.LOGIN, { redirectTo }, request);
}
So what are we doing here? Well, it's very simple, if the user lands on login with a redirectTo in the search params we redirect to login again and store the info in the flash session, and then on the next loader call we will have it in the flash session and we will redirect the user to the Auth0 universal login, pretty simple!
And the final piece of the puzzle is to actually use the flash session, Let's say the user is back on a different route in /auth/callback, well all we do there is:
export const loader = ({ request }) => {
const { flash } = await getFlashSession(request);
// handle the authenticator part and store the tokens etc.
const redirectTo = flash?.redirectTo;
return redirect(redirectTo ?? "/default-path");
}
And that's it! We redirect the user to where he was and the flash session is removed by our root.tsx loader and we're done!
Thank you!
If you've reached the end you're a champ! I hope you liked my article.
If you wish to support me follow me on Twitter here:
or if you want to follow my work you can do so on GitHub:
And you can also sign up for the newsletter to get notified whenever I publish something new!