Source: https://www.hype-stack.dev/docs/backend/authentication

# Authentication

Authentication arrives with a starter pack. The free template has no login. Pick exactly one starter:

- [Auth Starter (Better Auth)](/docs/packs-templates/packs/starter-auth-betterauth), free: sign-in, sessions, a profile,
  a personal workspace per account, and a minimal admin console
- [SaaS Starter (Better Auth)](/docs/packs-templates/packs/starter-saas-betterauth): the above plus organizations,
  invitations, onboarding, feature flags, and the full admin app
- [SaaS Starter (WorkOS)](/docs/packs-templates/packs/starter-saas-workos): the same product on WorkOS identity

All three share one schema, one middleware chain, and one permission layer, so everything below applies to each of them.
This page is the architecture. Credential setup stays on the pack pages.

## Where auth lives

| Concern                   | Typical path after install                                           |
| ------------------------- | -------------------------------------------------------------------- |
| Auth middleware           | `apps/backend/src/middleware/auth/auth-middleware.ts`                |
| Authenticated app helper  | `apps/backend/src/utils/auth/auth-hono.ts` (`getAuthenticatedApp()`) |
| Auth HTTP routes          | `apps/backend/src/routes/auth/`                                      |
| Permissions middleware    | `apps/backend/src/middleware/permissions/has-access.ts`              |
| Ability builder           | `apps/backend/src/libs/permissions/permissions.ts`                   |
| Private frontend layout   | `apps/frontend/src/routes/(private)/route.tsx`                       |
| Onboarding layout         | `apps/frontend/src/routes/onboarding/route.tsx`                      |
| Post-auth redirect helper | `apps/frontend/src/features/auth/utils/post-auth-redirect.ts`        |

WorkOS keeps session state in a sealed cookie (`wos-session`). Better Auth mounts its handler under `/api/auth/*` and
reads the session through `auth.api.getSession`.

## Sign-in flow (Better Auth)

**Email or social sign-in**

1. **Browser submits credentials** — The frontend auth forms call the Better Auth client or the pack's /auth routes.
2. **Better Auth handler** — Requests under /api/auth/* hit the betterAuth() config in apps/backend/src/libs/auth/auth.ts.
3. **Session + user records** — Better Auth creates or updates the user and session (organization plugin enabled in the starter).
4. **Optional transactional email** — Password reset and verification emails go out through Resend when RESEND_API_KEY is set. (See Mailing)
5. **Redirect into the app** — Users without an organization land on /onboarding. Everyone else goes to /.

WorkOS follows the same product shape (login → session cookie → onboarding or app), but identity and memberships are
resolved through the WorkOS API instead of local Better Auth tables. Google OAuth callback URLs differ per provider; set
them on the pack setup page.

## Protected API requests

Authenticated routers use `getAuthenticatedApp()`, which runs `withAuthUser` first. That middleware:

1. Resolves the current user from the session
2. Resolves organization membership and permissions for the active org
3. Builds a CASL ability and stores `user`, `organizationId`, and `ability` on the Hono context

Routes then gate actions with:

```ts
hasAccess({ action: "read", subject: "project" });
```

`hasAccess` requires a user, an `organizationId`, and `ability.can(action, subject)`. Presets ship in the enums package
(`admin` gets `manage:all`; `member` gets a narrower set). See [Organizations](/docs/backend/organizations).

## Frontend route protection

| Layout            | Behavior                                                                                                                                                                        |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `(private)`       | Loads `sdk.users.me`. Unauthenticated users go to `/login`. Users with no organization go to `/onboarding` (SaaS starters; the free starter always has the personal workspace). |
| `onboarding`      | Reverse guard: if the user already has an organization, leave onboarding.                                                                                                       |
| Admin `(private)` | Separate admin app login; requires an admin role or `SUPER_ADMIN_EMAIL`.                                                                                                        |

## Side effects to remember

- Auth changes can trigger email (verification, password reset, invitations). See [Mailing](/docs/backend/mailing).
- Wrong `FRONTEND_URL`, `BETTER_AUTH_URL`, or WorkOS redirect URLs break callbacks. See
  [Troubleshooting](/docs/development/troubleshooting).
- The [admin app](/docs/packs-templates/packs/admin) uses the same identity providers with a separate allowlist.

## Related setup pages

- [WorkOS credentials](/docs/packs-templates/packs/starter-saas-workos)
- [Better Auth credentials](/docs/packs-templates/packs/starter-saas-betterauth)
- [Env variables](/docs/backend/env-variables)
