'How to redirect back to original page after login / signup in remix-auth?

With remix auth, we can do the following:

let user = await authenticator.isAuthenticated(request, {
  failureRedirect: "/login",
});

which will allow us to redirect to the /login route if the user is not authenticated. However, I'm wondering how to redirect back to the original page after logging in.

The verify function (that does the login), will not have access to a query parameter like ?redirect_to (this seems to be true in the context of OAuth, which submits a GET to a callback URL).



Solution 1:[1]

Author of Remix Auth here, add the current URL to the failure redirect like this

let user = await authenticator.isAuthenticated(request, {
  failureRedirect: "/login?redirectTo=/my/url",
});

You could also use request.url to know the current URL, mostly useful to keep search params.

Then, in your login route where you call authenticator.authenticate you could do:

async function login(request: Request) {
  // from the URL, get the returnTo search param
  let url = new URL(request.url);
  let returnTo = url.searchParams.get("returnTo") as string | null;

  try {
    // call authenticate as usual, in successRedirect use returnTo or a fallback
    return await authenticator.authenticate("auth0", request, {
      successRedirect: returnTo ?? "/home",
      failureRedirect: "/",
    });
  } catch (error) {
    // here we catch anything authenticator.authenticate throw, this will
    // include redirects
    // if the error is a Response and is a redirect
    if (error instanceof Response && error.redirected) {
      // we need to append a Set-Cookie header with a cookie storing the
      // returnTo value
      error.headers.append(
        "Set-Cookie",
        await returnToCookie.serialize(returnTo)
      );
    }
    throw error;
  }
}

Call this login function in your loader/action and in the callback URL where the OAuth2 provider will redirect the user back to your app add this:

export let loader: LoaderFunction = async ({ request }) => {
  // get the returnTo from the cookie
  let returnTo =
    (await returnToCookie.parse(request.headers.get("Cookie"))) ?? "/home";

  // call authenticate to complete the login and set returnTo as the successRedirect
  return await auth.authenticate("auth0", request, {
    successRedirect: returnTo,
    failureRedirect: "/signup",
  });
};

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Sergio Xalambrí