Skip to content

Commit 21e927e

Browse files
ericallamTrigger.dev RepoOps
authored andcommitted
feat(webapp): only accept a magic link in the browser that requested it
Magic links now only sign you in from the browser that requested them. Opening a link anywhere else, including when an email security scanner follows it, no longer logs anyone in or creates an account. If you open a link in a different browser or on another device, you'll be asked to request a new one there. Self-hosted instances can allow opening links on another device by setting `MAGIC_LINK_SAME_BROWSER_REQUIRED=false`. Mono-RevId: 20c50ae2200654ace852d8f68afb8435e83c2d30
1 parent 014a19c commit 21e927e

5 files changed

Lines changed: 18 additions & 0 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: improvement
4+
---
5+
6+
Magic links now only sign you in from the browser that requested them, so a link opened elsewhere (including by an email security scanner) no longer logs anyone in. Self-hosted instances can turn this off with `MAGIC_LINK_SAME_BROWSER_REQUIRED=false`.

‎apps/webapp/app/env.server.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ const EnvironmentSchema = z
412412
WEBAPP_TELNET_LOGS_PORT: z.coerce.number().optional(),
413413
LOGIN_ORIGIN: z.string().default("http://localhost:3030"),
414414
LOGIN_RATE_LIMITS_ENABLED: BoolEnv.default(true),
415+
MAGIC_LINK_SAME_BROWSER_REQUIRED: BoolEnv.default(true),
415416
APP_ORIGIN: z.string().default("http://localhost:3030"),
416417
PUBLIC_APP_ORIGIN: z.url().optional(),
417418
// Extra exact origins (comma separated) added to the document `img-src` CSP,

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,15 @@ const emailStrategy = new EmailLinkStrategy(
6262
secret,
6363
callbackURL: "/magic",
6464
sessionMagicLinkKey: "triggerdotdev:magiclink",
65+
/**
66+
* A magic link only signs in from the browser session that requested it. Without this,
67+
* anything that opens the link signs in, including the link scanners corporate mail filters
68+
* run on incoming email, so a request typed with someone else's address created an account.
69+
* Development is exempt: there `sendMagicLinkEmail` redirects straight to the link before the
70+
* strategy has stored it in the session.
71+
*/
72+
validateSessionMagicLink:
73+
env.NODE_ENV !== "development" && env.MAGIC_LINK_SAME_BROWSER_REQUIRED,
6574
},
6675
verifyMagicLink
6776
);

‎docs/self-hosting/env/webapp.mdx‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ mode: "wide"
4444
| `WHITELISTED_EMAILS` | No | — | Whitelisted emails regex. |
4545
| `BLOCKED_EMAIL_DOMAINS` | No | — | Comma-separated email domains that can't sign in or sign up, including their subdomains. |
4646
| `LOGIN_RATE_LIMITS_ENABLED` | No | true | Enable rate limiting on magic-link login. |
47+
| `MAGIC_LINK_SAME_BROWSER_REQUIRED` | No | true | Only accept a magic link opened in the browser that requested it. Set to false to allow opening it on another device.|
4748
| `AUTH_GITHUB_CLIENT_ID` | No | — | GitHub client ID. |
4849
| `AUTH_GITHUB_CLIENT_SECRET` | No | — | GitHub client secret. |
4950
| `CSP_IMG_SRC_ALLOWLIST` | No | — | Extra hosts the dashboard may load images from, e.g. an SSO or avatar host serving profile images. A comma-separated list of exact origins (`https://sso.example.com`); a wildcard host such as `https://*.example.com` is refused. |

‎hosting/docker/webapp/docker-compose.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ services:
5858
DIRECT_URL: ${DIRECT_URL:-postgresql://postgres:${POSTGRES_PASSWORD}@postgres:5432/main?schema=public&sslmode=disable}
5959
SESSION_SECRET: ${SESSION_SECRET}
6060
MAGIC_LINK_SECRET: ${MAGIC_LINK_SECRET}
61+
MAGIC_LINK_SAME_BROWSER_REQUIRED: ${MAGIC_LINK_SAME_BROWSER_REQUIRED:-true}
6162
BLOCKED_EMAIL_DOMAINS: ${BLOCKED_EMAIL_DOMAINS:-}
6263
ENCRYPTION_KEY: ${ENCRYPTION_KEY}
6364
PROVIDER_SECRET: ${PROVIDER_SECRET}

0 commit comments

Comments
 (0)