Authentication

Authentication identifies who is using your app. Roles and permissions control what they can see and do.

Configure sign-in through the auth option in sixb.config.ts. Sixb handles the sign-in routes, sessions, and sign-out for Atlas and your custom app.

Configure sign-in

Choose a strategy:

StrategyUse when
Magic linkUsers should sign in through a link sent to their email.
OIDCYou use an identity provider such as Google Workspace or Microsoft Entra.

For magic links, install the strategy:

BASH
bun add @sixb/auth-magic-link

Add it to your existing configuration. sendEmail below is your application's email delivery function; Sixb supplies the rendered message.

TS
// sixb.config.ts
import { magicLink } from "@sixb/auth-magic-link"
import { createSixb } from "@sixb/core"
import { sendEmail } from "./lib/email"
import { financeAdmins } from "./security/groups/finance-admins"

export const sixb = createSixb({
  // ...your existing providers
  auth: magicLink({
    allowedDomains: ["example.com"],
    bootstrapUsers: ["admin@example.com"],
    bootstrapGroups: [financeAdmins],
    sendMagicLink: async ({ email, subject, text, html }) => {
      await sendEmail({ to: email, subject, text, html })
    },
  }),
})

During local development, you can print the supplied url instead of sending an email. Use an email service in production.

For OIDC, install @sixb/auth-oidc and use its strategy as the auth value:

TS
import { oidc } from "@sixb/auth-oidc"
import { financeAdmins } from "./security/groups/finance-admins"

const auth = oidc({
  issuer: "https://accounts.google.com",
  clientId: process.env.OIDC_CLIENT_ID!,
  clientSecret: process.env.OIDC_CLIENT_SECRET!,
  allowedDomains: ["example.com"],
  bootstrapUsers: ["admin@example.com"],
  bootstrapGroups: [financeAdmins],
})

Configure your provider's callback URL using the public API origin and /auth/callback. Sign-in completes only in the browser that started it, so the callback URL must use the same host as the API URL your app signs in through. To support email invitations with OIDC, also supply sendInvitation.

Sign-in trusts an address only when the provider marks it verified. Microsoft Entra never does, so return the address to trust with trustedEmail. Entra's preferred_username is the name people sign in to Microsoft with, and every user has one, including users without a mailbox:

TS
const auth = oidc({
  issuer: `https://login.microsoftonline.com/${process.env.ENTRA_TENANT_ID}/v2.0`,
  clientId: process.env.ENTRA_CLIENT_ID!,
  clientSecret: process.env.ENTRA_CLIENT_SECRET!,
  trustedEmail: (claims) => claims.preferred_username,
  bootstrapUsers: ["admin@example.com"],
  bootstrapGroups: [financeAdmins],
})

To let the identity provider decide group membership instead of inviting each person, return the groups it grants from groups. A user granted at least one group signs in without an invitation, and the groups are synced on every sign-in. See the strategy's README for provider setup and group mapping.

Set up the first administrator

bootstrapUsers lists people who may create an account without an invitation. bootstrapGroups assigns their starting groups. Define the group in security/groups/:

TS
// security/groups/finance-admins.ts
import { defineGroup } from "@sixb/core"

export const financeAdmins = defineGroup("finance-admins", {
  label: "Finance admins",
})

The group name does not grant access by itself. Add a role for its permissions and a membership policy if its members should invite or manage other users.

Bootstrap groups are applied on every sign-in. Use invitations for subsequent users rather than expanding the bootstrap list. allowedDomains restricts sign-in and invitations; it does not assign permissions.

Sessions

Use persistent storage so accounts and sessions survive restarts. Browser sessions expire after 30 days without foreground activity by default. Active sessions renew automatically.

To change the lifetime, wrap the strategy in an auth configuration:

TS
const DAY = 24 * 60 * 60 * 1000

const authentication = {
  strategy: auth,
  session: {
    idleTimeoutMs: 30 * DAY,
    renewalWindowMs: 7 * DAY,
    absoluteTimeoutMs: 90 * DAY,
  },
}

Use authentication as the auth option. The optional absolute lifetime applies to newly created sessions. Background polling and WebSocket traffic do not extend a session.

Sixb-served apps handle cookies, CSRF, and sign-in redirects. For a separate frontend, use the browser client setup. To customize the sign-in screen, see Custom sign-in.

Development and production

Omitting auth allows unrestricted local access. Production requires an authentication strategy unless you explicitly opt out. Configure the API and browser public origins before deploying.

For scripts and external services, use personal access tokens or service accounts.

Search docs

Search the documentation