Skip to content

Authentication

hypar uses better-auth with a Prisma adapter. Every request to a non-public route requires a signed-in session; admin routes additionally require role === 'admin'.

Sign-in / sign-up

RoutePagePurpose
/auth/signinpages/auth/signin.vueEmail + password sign-in. Social buttons appear when the corresponding env vars are set.
/auth/signuppages/auth/signup.vueEmail + password account creation. New users are created with role = 'user'.
/setuppages/setup.vueFirst-run wizard. See First-run setup.

The minimum password length is 8 characters (server/lib/auth.ts).

Providers

  • Email + password — always on.
  • Google OAuth — enabled when both GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET are set.
  • GitHub OAuth — enabled when both GITHUB_CLIENT_ID and GITHUB_CLIENT_SECRET are set.

See Environment variables for the full list.

Sessions

Cookies issued by better-auth.

SettingValue
expiresIn7 days
updateAgerefreshed on activity older than 1 day
SecretBETTER_AUTH_SECRET (or AUTH_SECRET) — required, generate with openssl rand -hex 32

server/middleware/auth-session.ts attaches the session to every H3 request as event.context.auth. Server handlers should read the user id via requireSessionUserId(event) from server/utils/session.ts.

In Vue components and pages use the useAuth() composable:

ts
const { user, userId, isAdmin, isAuthenticated, isPending } = useAuth()

The browser client lives in utils/auth-client.ts and exposes signIn, signUp, signOut, useSession.

Route protection

A global route middleware redirects unauthenticated visitors to /auth/signin for every page except PUBLIC_ROUTES (/setup, /auth/signin, /auth/signup). See middleware/auth.global.ts.

API routes that return user-scoped data call requireSessionUserId(event) and use that id in their Prisma where clauses, so user A can never read user B's documents, conversations or queries.

First-run setup

On a fresh database, every page request is redirected to /setup. The wizard collects provider, DB, embedding, chunking, search and RAG configuration, then asks for a name, email and password.

The account created by the wizard is the first admin (role = 'admin'). After completion the app writes Setting { key: 'app.configured', value: 'true' } and subsequent users that sign up at /auth/signup get the default user role.

See Environment variables → First-run setup for what gets written to the DB versus to .env.

Next steps