Skip to content

Commit dad37ef

Browse files
committed
Revert "fix(webapp): show magic link confirmation instead of reloading login (#4215)"
This reverts commit afc8f9e.
1 parent 9f76c92 commit dad37ef

3 files changed

Lines changed: 36 additions & 20 deletions

File tree

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { createCookie } from "@remix-run/node";
2+
import { env } from "~/env.server";
3+
4+
// Carries the submitted email to the confirmation screen in a short-lived,
5+
// httpOnly cookie rather than the URL, so the address never lands in access
6+
// logs, browser history, or error-tracker breadcrumbs. Lives in a .server
7+
// module: it calls createCookie at import time using server-only env, which
8+
// throws if it ever evaluates in the client bundle.
9+
export const magicLinkEmailCookie = createCookie("magiclink-email", {
10+
maxAge: 60 * 10,
11+
httpOnly: true,
12+
sameSite: "lax",
13+
secure: env.NODE_ENV === "production",
14+
path: "/",
15+
});

apps/webapp/app/routes/login.magic/route.tsx

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import { ssoRedirectForEmail } from "~/services/ssoAutoDiscovery.server";
3434
import { logger, tryCatch } from "@trigger.dev/core/v3";
3535
import { env } from "~/env.server";
3636
import { extractClientIp } from "~/utils/extractClientIp.server";
37+
import { magicLinkEmailCookie } from "./magicLinkEmailCookie.server";
3738

3839
export const meta: MetaFunction = ({ matches }) => {
3940
const parentMeta = matches
@@ -73,14 +74,12 @@ export async function loader({ request }: LoaderFunctionArgs) {
7374
// confirmation renders the flashed error as magicLinkError below.
7475
const url = new URL(request.url);
7576
const sanitized = sanitizeRedirectPath(url.searchParams.get("redirectTo"));
76-
// The email-link strategy stores the submitted address in the session
77-
// (`auth:email`) alongside the magic-link key, so read it from there to name
78-
// the confirmation — no address in the URL, and no separate cookie to leak
79-
// into the client bundle. Validate before echoing it back.
80-
const emailValue = session.get("auth:email");
77+
// The submitted address is carried in a short-lived cookie (not the URL) so
78+
// the confirmation can name it. Validate before echoing it back.
79+
const emailCookie = await magicLinkEmailCookie.parse(request.headers.get("Cookie"));
8180
const email =
82-
typeof emailValue === "string" && z.string().email().safeParse(emailValue).success
83-
? emailValue
81+
typeof emailCookie === "string" && z.string().email().safeParse(emailCookie).success
82+
? emailCookie
8483
: null;
8584
if (!session.has("triggerdotdev:magiclink")) {
8685
// Throw (not return) so the redirect doesn't widen the loader's return
@@ -216,13 +215,20 @@ export async function action({ request }: ActionFunctionArgs) {
216215
return redirect(ssoRedirect);
217216
}
218217

219-
// The email-link strategy stores the address in the session (`auth:email`)
220-
// and throws its own redirect Response (with the committed session cookie),
221-
// so return it directly — the confirmation reads the email from the session.
222-
return await authenticator.authenticate("email-link", request, {
223-
successRedirect: "/login/magic",
224-
failureRedirect: "/login",
225-
});
218+
// authenticator.authenticate throws its redirect Response; attach the
219+
// sent-to email as a short-lived cookie so the confirmation can name it
220+
// without putting the address in the URL.
221+
try {
222+
return await authenticator.authenticate("email-link", request, {
223+
successRedirect: "/login/magic",
224+
failureRedirect: "/login",
225+
});
226+
} catch (thrown) {
227+
if (thrown instanceof Response) {
228+
thrown.headers.append("Set-Cookie", await magicLinkEmailCookie.serialize(email));
229+
}
230+
throw thrown;
231+
}
226232
}
227233
case "reset":
228234
default: {
@@ -254,7 +260,7 @@ export default function LoginMagicLinkPage() {
254260
</Header1>
255261
<Fieldset className="flex w-full flex-col items-center gap-y-2">
256262
<InboxArrowDownIcon className="mb-4 h-12 w-12 text-indigo-500" />
257-
<Paragraph className="mb-6 text-center">
263+
<Paragraph className="mb-6 text-center [text-wrap:balance]">
258264
{email ? (
259265
<>
260266
We emailed a magic link to <span className="text-text-bright">{email}</span> to

apps/webapp/app/services/emailAuth.server.tsx

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,6 @@ const emailStrategy = new EmailLinkStrategy(
1818
secret,
1919
callbackURL: "/magic",
2020
sessionMagicLinkKey: "triggerdotdev:magiclink",
21-
// Pin explicitly to the library default rather than relying on it: the
22-
// /login/magic loader reads the submitted address via
23-
// session.get("auth:email") to name it on the confirmation screen, so a
24-
// future remix-auth-email-link default change can't silently break that.
25-
sessionEmailKey: "auth:email",
2621
},
2722
async ({
2823
email,

0 commit comments

Comments
 (0)