Skip to content

fix(express)!: serve OTP generate routes over POST#109

Merged
Bccorb merged 1 commit into
mainfrom
fix/otp-generate-csrf
Jul 20, 2026
Merged

fix(express)!: serve OTP generate routes over POST#109
Bccorb merged 1 commit into
mainfrom
fix/otp-generate-csrf

Conversation

@Bccorb

@Bccorb Bccorb commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

What

Serve the four OTP generate routes over POST instead of GET, closing the same CSRF vector already fixed for /auth/magic-link.

  • GET /auth/otp/generate-phone-otp -> POST
  • GET /auth/otp/generate-email-otp -> POST
  • GET /auth/otp/generate-login-phone-otp -> POST
  • GET /auth/otp/generate-login-email-otp -> POST

Why

Each of these routes sends an SMS or email, so they are state changing. As a GET with no custom headers they were simple cross-site requests: an <img src> on any page could fire them, and because the session cookie defaults to SameSite=None in a secure deployment, the adapter treated them as authenticated. That let a hostile page trigger unbounded OTP messages to a signed-in user, which is a messaging-abuse and SMS toll-fraud vector.

This mirrors the fix already applied to GET /auth/magic-link in the cookie-clearing-and-csrf change. Handler behavior is unchanged, only the browser-facing method. The upstream call to the auth server is still GET, since that hop is server-to-server and not CSRF exposed.

Coordinated release

BREAKING. Pairs with @seamless-auth/react PR (link once open), which switches these four client methods to POST. An older SDK issuing GET will get a 404, and an older adapter will 404 the new SDK, so the two must be released together. Same lockstep as the magic-link change.

Tests

  • loginOtpRoutes.test.js: the existing proxy test now issues POST, with the upstream fetch assertion unchanged
  • Added a guard asserting all four generate routes answer 404/405 to GET, mirroring the no longer exposes GET /magic-link test

Full express suite: 115 passed.

Checks

  • npm test (builds core + express, then jest): 115 passed
  • tsc -p tsconfig.build.json clean
  • README backend-expectations updated
  • Changeset (minor, breaking)

@Bccorb

Bccorb commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

SDK half: fells-code/seamless-auth-react#103. Both must land and publish together (see fells-code/seamless-auth-react#100 for the version-lockstep concern).

@Bccorb
Bccorb merged commit 827b4ed into main Jul 20, 2026
1 of 2 checks passed
@Bccorb
Bccorb deleted the fix/otp-generate-csrf branch July 20, 2026 19:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant