Skip to content
All articles
4 min read

SaaS authentication is more than a login form

Follow identity through sessions, workspace ownership, protected actions, and sign-out — the parts a polished sign-in screen cannot prove.

supastack team

Let one system own identity

The login form collects a request. The authentication system decides whether that request establishes an identity and issues the session the rest of the application trusts. Keeping that responsibility in one place prevents each route from inventing its own interpretation of a signed-in user.

supastack composes Better Auth for identity and session handling. Application code resolves the session at protected boundaries and connects it to a workspace. The interface can show helpful access states, but client state must not become evidence that an operation is authorized.

The rule has to hold on every surface the product ships. Web, mobile, and desktop clients should consume the same identity decision rather than implementing it three times — three interpretations of “signed in” is where account bugs come from.

Choose sign-in methods deliberately

Every method trades friction against attack surface and an outside dependency. Passwords need reset flows and rate limiting. Magic links and one-time codes depend on email deliverability. OAuth delegates identity to providers like Google, GitHub, or Apple — and inherits their outages, consent screens, and callback rules.

supastack composes these through Better Auth — email OTP, password, magic link, OAuth, with two-factor and passkeys available — behind a single identity decision. Ship the smallest set your audience actually needs; each additional method is another callback path, another failure mode, and another flow to verify before launch. The authentication guide covers the wiring.

When a person can sign in more than one way, decide how the methods join. A Google account and an email magic link that resolve to the same address should land on one identity, not two. Account-linking rules are part of the identity decision, and getting them wrong creates duplicate users that surface months later as mysteriously missing data.

Sessions are the credential that matters

After sign-in, the session — not the password — is what every request carries. Its expiry, storage, and invalidation rules define the real security posture. A session that survives sign-out, or one a removed workspace member can keep using, is an authentication failure no polished login screen can fix.

Decide the lifecycle up front: how long sessions live, whether users can see and revoke their active sessions, and what a password change, email change, or workspace removal does to them. Session management exists as a module in the kit precisely because these decisions are easy to postpone and expensive to retrofit.

Connect the session to the requested record

Being signed in does not grant access to every record. Resolve the user's workspace on the server and include that scope in reads and mutations. A task identifier or recovery link is a reference to work, not permission to retrieve it — the workspace boundaries post covers that side of the boundary in detail.

Resolve the scope in a fixed order: authenticate the session, load the membership, then read or write with that workspace context — never the other way around. Middleware can redirect an anonymous visitor, but it cannot authorize the operation; the check belongs in the server action or route handler where the record is touched.

Accounts have a lifecycle, not just a beginning

Provisioning is the first test of that boundary. When a user signs up, the workspace and ownership records that follow must be safe to create more than once — lifecycle hooks can be replayed by providers, retries, or support tools. A duplicate event should be a no-op, not a duplicate organization.

The end of the lifecycle deserves the same care. Email changes, password resets, member removal, account deletion, and data export are each small flows with their own abuse cases — a reset link that works twice, an export that leaks a teammate's records. supastack ships GDPR export and session management for this reason; whatever you build on, budget for the boring flows.

Test the lifecycle, including its end

A successful login test is useful, but incomplete. Exercise invalid credentials, expired or reused verification codes, anonymous requests, and cross-workspace access. Verify that sign-out invalidates the session and that a returning client cannot keep using a previously authorized screen to perform protected work.

Distinguish handler tests from deployment acceptance. A memory adapter can establish the semantics of a real authentication handler without proving Postgres persistence or a provider callback. Verify the configured origin, callback path, session restoration, and sign-out with the deployed dependencies before claiming that the complete sign-in journey works.

  • Invalid credentials and expired or reused verification codes are rejected.
  • Anonymous and cross-workspace requests receive no owned data.
  • Sign-out invalidates the session — a stale client cannot keep acting.
  • Provisioned records stay idempotent when lifecycle hooks replay.
  • Real-provider callbacks work on the configured origin — verified, not assumed.

Common authentication questions

The questions below surface once the login form is done and the system has to keep working.

  • Is middleware enough to protect routes? — Middleware is a convenient redirect, not an authorization layer. Each server action and route resolves the session and workspace itself; page-level guards hide screens without authorizing operations.
  • Build auth myself or use a library? — Session semantics are rarely where a SaaS differentiates. A maintained library like Better Auth behind clear module boundaries gives you tested primitives while keeping the decisions that matter — scoping, lifecycle — in your code.
  • How do sessions relate to workspaces? — The session identifies the person; the workspace identifies the records they may touch. Resolve membership on the server for every request and never trust a workspace ID the client sends.
  • What do B2B customers expect from authentication? — Team workspaces with roles, OAuth sign-in, session visibility and revocation, and an audit trail. Two-factor and passkeys are increasingly expected for admin roles.
  • What breaks authentication in production? — Usually the edges: a callback URL that only exists locally, a hook that provisions twice, a session that outlives a membership. Test the ends of flows, not just the starts.

Frequently asked questions

14 questions

What is supastack?

supastack is a modular foundation for building AI-powered SaaS products. It brings together common infrastructure so you can focus on product-specific features.

Does it support web and mobile?

Yes. supastack includes Next.js and Expo apps as starting points for web and mobile experiences.

What authentication is included?

Better Auth covers email OTP, magic-link, and social sign-in; email/password stays available at the API layer and through the Auth.js credentials engine for products that need it. Personal workspaces are provisioned with the account so product records stay scoped from day one.

How does it support AI?

supastack includes configurable multi-provider AI, usage tracking, budgets, and encrypted bring-your-own-key support.

How are subscriptions handled?

For products built on the kit, Stripe billing, subscriptions, and entitlements form the paid-access foundation. Provider secrets stay server-only.

Where does my product-specific code live?

Product-specific features remain in a separate codebase while the product configures and integrates supastack’s foundation modules.

How does supastack pricing work?

The kit is a one-time purchase with lifetime updates: One Platform at $249 (temporary launch price, $100 off the regular $349) — your pick of Next.js (Web), Expo (iOS & Android), or Tauri (macOS & Windows Desktop) — or the All Platforms Bundle at $499 (temporary launch price, $100 off the regular $599) with every platform and the full monorepo, plus $75 per extra developer seat. No kit subscription. Checkout on this site delivers your license key by email, with repository access via GitHub invite.

How do workspaces scope my data?

User-owned records are scoped by workspaceId. Identity, entitlements, AI usage, billing events, and audit entries stay inside the personal workspace boundary.

How do background jobs work?

Trigger.dev is the explicit job runtime. The JobRunner contract only promises enqueue, status, and cancel—workflow semantics stay Trigger.dev-specific and explicit.

How is email different from outreach?

Transactional email covers product workflows such as completion notices. Cold outreach and campaigns are product concerns outside this kit’s email module.

How do mobile purchases work?

Mobile includes native purchases and restore through RevenueCat, with access verified by your server. Configure the store accounts and complete device testing before release. Web billing remains separate.

Where do AI provider keys live?

Bring-your-own-key credentials are encrypted and stay server-only. Keys are redacted from logs; usage and budgets remain visible at the workspace level.

Which payment methods does checkout accept?

The Stripe-hosted checkout accepts cards and can also offer Alipay and WeChat Pay once those wallets are enabled on the Stripe account — handy for buyers in China. Wallet authorizations confirm asynchronously, so the license page updates as soon as the payment clears.

Can I get a refund?

After you've got access to the repository, supastack is yours forever, so it cannot be refunded. But rest assured, you get the complete source code with lifetime updates to build and ship unlimited products for yourself or clients. You just cannot resell the code or redistribute the repository as a starter kit or template.

EN