Skip to content

feat(auth): migrate onto @aswincloud/auth, access policy gate, central OAuth broker - #13

Merged
Aswinmcw merged 3 commits into
mainfrom
feat/auth-broker-migration
Aug 14, 2026
Merged

feat(auth): migrate onto @aswincloud/auth, access policy gate, central OAuth broker#13
Aswinmcw merged 3 commits into
mainfrom
feat/auth-broker-migration

Conversation

@Aswinmcw

Copy link
Copy Markdown
Member

The three commits that were sitting unpushed on local main. Rebased onto current main (clean — no conflicts with the dependabot bumps).

What's here

  • feat(auth): migrate onto @aswincloud/auth — moves session/OAuth/password primitives and the /d1 flows (signup, login, OTP, reset, email change, account delete) onto the shared package. src/lib/oauth.ts, otp.ts, passwords.ts are dropped; src/lib/authpkg.ts is the new bridge to our env + Resend transport. Cookie names and token format are unchanged, so existing sessions and in-flight OAuth round-trips survive the swap.
  • feat: access-policy gate on account creationACCESS_MODE / ACCESS_DOMAINS / OWNER_EMAILS gate account creation only; existing users are never re-gated. Unset ⇒ public, preserving current open signup.
  • feat: route OAuth sign-in through the central broker — when AUTH_BROKER_URL + RELAY_SECRET are set, sign-in relays through auth.aswincloud.com (one OAuth client per provider, shared across sites) instead of per-site clients. Nonce-bound, and linking still runs on the provider's stable user id. Falls back to the local clients when the broker isn't configured.

Notes

  • tsc --noEmit passes.
  • Email-change moved to token-verified self-service, so the email_change_requests table is no longer read or written. The table is left in place — no destructive migration.
  • Follow-up: .env.example still documents only the original five vars and is missing every OAuth / broker / access-policy var. Worth a separate docs pass along with the README, which still describes alerts as owner-only.

@Aswinmcw
Aswinmcw requested review from a team and Aswin-coder as code owners August 14, 2026 09:58
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
shiptrack 9eeaff0 Aug 14 2026, 09:58 AM

@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
shiptrack-poller 9eeaff0 Aug 14 2026, 09:58 AM

@Aswincloud-Bot Aswincloud-Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Auto-approved: @Aswinmcw is a member of @Aswincloud/admins.

Aswin-coder and others added 3 commits August 14, 2026 10:06
…Auth)

Make the published package the single source of truth for auth. Delete the
duplicated primitives (lib/passwords, lib/otp, lib/oauth) and rewrite the auth
route handlers onto the package's /d1 flows (signup, verifyOtp, resendOtp,
requestPasswordReset, resetPassword, changePassword, changeUsername,
requestEmailChange, confirmEmailChange, removeUser) plus core startOAuth/
handleOAuthCallback. A small lib/authpkg.ts bridges our AppEnv → OAuthConfig
and wraps our Resend sendEmail as the package's EmailSender; ShipTrack-branded
auth emails are preserved via the new render* template overrides (pkg 0.3.0).

Session/OAuth cookie names (shiptrack_session, shiptrack_oauth_state) and the
token/hash formats are unchanged, so existing sessions and stored password
hashes stay valid. lib/auth.ts stays as the thin Next adapter (next/headers,
requireAdmin); lib/tokens.ts and lib/email.ts stay for watches + the poller.

Email change switches from admin-approval to the package's self-service,
token-verified flow: new /confirm-email page + /api/auth/confirm-email route;
removed the admin review queue (routes, db functions, dashboard UI) and the
settings pending-request panel. The email_change_requests table is left in
place (no destructive migration); it's simply no longer read or written.

Verified: tsc clean, opennextjs-cloudflare build OK, and a local D1 smoke run
(14 checks) covering signup/verify, login (+unverified), forgot/reset,
change-password, change-name, self-service email change, last-admin delete
guard, removed admin routes 404, and the regression that an existing session
cookie + stored hash still authenticate, plus watch unsubscribe links intact.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a per-site access policy that gates *account creation* only — existing
users (password or returning OAuth identity) are never re-gated:

- lib/authpkg.ts: emailAllowedForSite(env,email). Unlike the package default
  (fail-closed to 'owners'), shiptrack fails OPEN to 'public' when ACCESS_MODE
  is unset, preserving historical open signup. ACCESS_MODE=domain (+ACCESS_DOMAINS)
  or =owners (+OWNER_EMAILS) restrict it.
- signup route: 403 not_allowed before any DB read (no account-existence leak).
- OAuth callback: gate only the brand-new-user branch; returning/link flows
  unchanged. New disallowed email → /login?oauth_error=not_allowed.
- env.ts: ACCESS_MODE / ACCESS_DOMAINS / OWNER_EMAILS.

Bumps @aswincloud/auth to ^0.4.0. Password/email-change/watch flows untouched.
…-id linking)

When AUTH_BROKER_URL + RELAY_SECRET are set, OAuth goes through the broker
(one client per provider, shared across sites) instead of shiptrack's own
provider clients; falls back to the local clients when unset.

- authpkg.ts: brokerConfigured / brokerStart (302 + signed nonce cookie) /
  verifyBrokerRelay (relay sig + provider + nonce match) / clearBrokerNonceCookie.
- start route: broker 302 when configured, else local startOAuth.
- callback: broker path reads ?relay, verifyBrokerRelay, then the SAME
  account-linking as before — now keyed on claims.providerUserId (relayed by the
  broker since pkg 0.5.0), so links stay on (provider, provider_user_id), no
  email-only downgrade. Linking extracted into a shared loginWithIdentity().
- providers route: proxies the broker's per-site list (id-only shape kept).
- env.ts: AUTH_BROKER_URL, RELAY_SECRET.

Bumps @aswincloud/auth to ^0.5.0. Password/OTP/email-change/watch flows
untouched. Registered shiptrack with the broker for [google,github,microsoft];
only Google is configured on the broker today, so the login page shows Google
until the other apps are added (then they appear automatically).
@Aswinmcw
Aswinmcw force-pushed the feat/auth-broker-migration branch from 9eeaff0 to b7ad19a Compare August 14, 2026 10:08
@Aswinmcw
Aswinmcw added this pull request to the merge queue Aug 14, 2026
Merged via the queue into main with commit 0f98ea6 Aug 14, 2026
4 checks passed
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.

3 participants