Authentication

Compose credentials, magic links, sessions, passkeys, MFA, and connected-provider access without handing application identity to a framework.

Supported approaches

Email and password

available

Password-grade credentials, breach checks, attempt limits, verification, reset, and session rotation.

Packages

@playstack/auth@playstack/auth-react@playstack/auth-next@playstack/nest-auth

Frameworks and integrations

Magic links

available

Single-use email credentials delivered through an application-owned mail boundary.

Sessions

available

Opaque access and rotating refresh tokens with inventory, revocation, reuse policy, browser, SSR, and request-guard adapters.

Split-origin browser sessions

available

Keep refresh credentials in an API cookie and short-lived bearer access only in browser memory when web and API origins differ.

Passkeys and MFA

available

Passkey-first step-up, TOTP, recovery codes, recent-auth proofs, and trusted-device decisions.

Auth.js provider sign-in

preview

Bridge Auth.js callbacks into Playstack identity and session contracts while the application owns provider configuration.

OAuth connections

available

Encrypted, refreshable credentials for third-party APIs after sign-in; this is distinct from using OAuth as the primary login method.

Frameworks and integrations

framework

React

Headless domain bindings plus optional Chakra application and admin compositions, with server authority kept outside the client.

framework

Next.js

Compose Playstack server contracts, React bindings, SSR handoff, and route adapters at the Next.js application edge.

framework

NestJS

Connect portable Playstack capabilities to dependency injection, guards, decorators, request context, workers, and lifecycle hooks.

framework

Expo

Use Playstack authentication and local-first contracts with Expo SecureStore, SQLite, and React Native lifecycle adapters.

integration

Auth.js

Bridge Auth.js provider callbacks into Playstack identity and session contracts while retaining application-owned provider configuration.

integration

Argon2

Use Playstack's Node.js authentication entrypoint with application-configured Argon2id password hashing.

integration

GitHub

Connect OAuth credentials, GitHub App installation tokens, and verified webhook delivery through explicit Playstack boundaries.

integration

SimpleWebAuthn

Verify passkey registration and authentication ceremonies through Playstack's optional Node.js WebAuthn adapter.

integration

Prisma

Persist Playstack capabilities through explicit application-owned Prisma clients, transactions, and managed schema fragments.

integration

Amazon SES

Deliver rendered messages and SES templates through an application-configured AWS SDK client.

integration

Mailgun

Deliver rendered messages or stored Mailgun templates through an explicit regional provider client.

integration

Postmark

Deliver rendered Playstack mail or Postmark provider templates through an explicit driver and native client escape hatch.

integration

Resend

Deliver transactional mail and synchronize consent-aware audience contacts through explicit Resend adapters.

integration

SendGrid

Deliver rendered messages and dynamic templates through an isolated SendGrid mail client.

integration

SMTP

Deliver portable rendered email through an application-configured Nodemailer transport.

Package reference

@playstack/auth

One identity boundary, several entry paths

Authentication is not one screen or one provider. Playstack keeps credential verification, session behavior, client state, request guards, device identity, and step-up proofs as explicit contracts that can be composed for the paths an application actually supports.

The portable service remains the authority. React, Next.js, NestJS, Auth.js, databases, and delivery providers connect at the application edge.

Start with the method

Choose a sign-in or verification method first, then follow its compatible framework and service paths. Each method identifies the package set and infrastructure it needs so email delivery, persistence, browser state, and server enforcement stay visible.

MethodPortable authorityApplication edges
Email and passwordCredential verification, attempt limits, breach checks, and session issueForm UI, request validation, cookies, persistence
Magic linkSingle-use token lifecycle and session issueEmail template, Postmark or SMTP delivery, callback route
Auth.js provider sign-inNormalized identity and linking policyProvider configuration, callback route, provider secrets
Passkeys and MFAEnrollment, challenge, recovery, and step-up contractsWebAuthn UI, trusted-device policy, persistence
OAuth connectionsEncrypted provider credentials after sign-inConsent UI, provider scopes, API client creation

OAuth connections are deliberately separate from provider sign-in. A GitHub connection used to call the GitHub API should not silently become the application's primary identity policy.

Security pages can list token-free session activity and revoke an individual session. Refresh-token reuse revokes the compromised session family by default, or every active user session when the application selects the stricter policy. A bounded maintenance operation removes expired and retained consumed credentials under an application scheduler.

Compose email and password end to end

The server authenticates the credential and issues the session. The browser receives only the safe session projection through the React transport.

ts
import { createCredentialService, databaseSessions } from '@playstack/auth'

export const credentials = createCredentialService({
  persistence,
  crypto,
  passwordHasher,
  breachChecker,
  limiter,
  delivery,
  stepUp,
  events,
  clock,
  ids,
  dummyPasswordHash,
})

export const sessions = databaseSessions({
  persistence,
  crypto,
  events,
  clock,
  ids,
})

export async function signInWithPassword(input, request) {
  const user = await credentials.authenticatePassword(
    input.email,
    input.password,
    { ip: requestIp(request) },
  )
  const tokens = await sessions.issue(user.id, {
    deviceId: input.deviceId,
  })

  await writeApplicationSessionCookies(tokens)
  return resolveSafeSessionView(tokens.accessToken)
}
tsx
import { useAuth } from '@playstack/auth-react'

export function SignInForm() {
  const auth = useAuth()

  return (
    <form onSubmit={(event) => {
      event.preventDefault()
      const data = new FormData(event.currentTarget)
      void auth.signIn({
        method: 'password',
        email: data.get('email'),
        password: data.get('password'),
      })
    }}>
      {/* Application-owned fields, errors, and recovery links. */}
    </form>
  )
}

createFetchAuthTransport sends that input to the application-owned sign-in endpoint. Playstack does not choose the URL handler, cookie names, or product UI.

Swap the entry path, keep the session boundary

A magic-link request calls credentials.requestToken('magicLink', email, { ip }); the callback redeems it with credentials.redeemMagicLink(token) and then issues the same session shape. Auth.js provider callbacks can enter through @playstack/auth-authjs. Both paths can reuse the same React session provider, Next.js SSR handoff, device checks, account resolution, and server authorization.

For a separately hosted browser and API, createBearerAuthTransport() keeps the refresh token in a secure API cookie and holds the returned opaque access token only in memory. Same-origin deployments retain the host-only cookie transport.

Security boundary

Client guards are navigation behavior, not authorization. Server operations validate sessions, CSRF where cookies are ambient, account scope, and any step-up requirement before acting.

Explicit identity and replay policies

providerIdentityPolicy: { linking: 'explicit', email: 'optional' } supports email-less provider users without silently linking a matching email. Trusted server normalization and step-up-backed identity linking remain required. The compatible default is verified-email linking with required email. Safe user/session projections and registration-event email may be null; first-contact email enrollment remains an application-owned verified workflow.

New provider users emit the same transactional registration event as password signup. Required account/audit provisioning must join the actual transaction, not a post-login callback.

refreshReplayPolicy: 'strict' rejects every consumed-token replay without returning replacement material. The default bounded-grace policy retains encrypted replacement credentials for a bounded interval. reusePolicy: 'all-user-sessions' separately widens revocation scope. Strict mode rejects refreshGraceMs and requires shared client refresh coordination.

Authorization-code consumption and session issuance can commit together through required transaction-aware issuance/authorization seams with account context. A committed code cannot be replayed to recover lost credentials. Optional device authorization follows the same one-time boundary. See Client authentication.

Go

Playstack Pro tag
OriginsPricingBlogNewsletterChangelogStatusRoadmap
ContributorsCommunityIn Use ShowcaseCase StudiesPartnersSponsors
FAQsSupportContact

© 2026 Playstack. All rights reserved.

With OSS
Terms of ServicePrivacy PolicyCookie PolicyImprint

By

Commune Software