MuseMVP Docs
Authentication

Authentication Architecture

Map Better Auth entrypoints, session behavior, and role-based middleware boundaries.

MuseMVP's permission architecture is built on the Better Auth framework, offering a secure, flexible, and scalable authentication solution. Through unified configuration files and middleware, we achieve full-stack coverage from user login and session management to permission control.

Auth Entrypoints

Server Config

src/backend/auth/auth.ts — Defines Better Auth core options, plugins (admin, 2FA, emailOTP, captcha), and Drizzle database adapter.

Client Helper

src/backend/auth/client.ts — Provides hooks and utilities for the frontend (useSession, signIn, signOut).

API Route Mount

src/backend/api/routes/auth.ts — Mounts Better Auth handlers to the Hono API.


Core Configuration

Authentication behavior is configured in the auth object within packages/config, split into auth.gates and auth.lifecycle.

Feature Toggles

Config ItemTypeDefaultDescription
gates.allowRegisterbooleantrueWhether to enable new user registration. If disabled, new users can only be added by admins.
gates.allowSocialSignInbooleantrueWhether to enable social login (GitHub, Google). Requires OAuth env vars.
gates.allowPasswordSignInbooleantrueWhether to allow traditional email/password login.
gates.allowTwoFactorAuthbooleantrueWhether to enable Two-Factor Authentication (2FA).

Session and Redirects

Config ItemDefaultDescription
lifecycle.redirectAfterLogin"/app"Path to redirect after successful login.
lifecycle.redirectAfterSignOut"/"Path to redirect after logout.
lifecycle.redirectWhenSessionExpired"/auth/login"Redirect when session expires or unauthenticated.
lifecycle.sessionTtlSeconds30 daysSession Cookie validity period in seconds.

Config Example

// packages/config
auth: {
  gates: {
    allowRegister: true,
    allowSocialSignIn: true,
    allowPasswordSignIn: true,
    allowTwoFactorAuth: true,
  },
  lifecycle: {
    redirectAfterLogin: "/app",
    redirectAfterSignOut: "/",
    redirectWhenSessionExpired: "/auth/login",
    sessionTtlSeconds: 60 * 60 * 24 * 30,
  },
}

Role and Admin Enforcement

We use a lightweight middleware-based permission control scheme:

User Auth (src/backend/api/middleware/auth.ts): Intercepts unauthenticated requests and returns 401. Validates session integrity.

Admin Auth (src/backend/api/middleware/admin.ts): Checks if user role is admin in addition to login. Protects admin routes.

Middleware Chain

Admin routes use adminMiddleware which first validates session, then checks session.user.role === "admin". Non-admin users receive 403 Forbidden.

MiddlewareApplied ToBehavior
authMiddleware/api/assets, /api/api-keys, /api/upload, etc.Requires valid session; returns 401 if missing
adminMiddleware/api/admin/*, /api/openapi, /api/docsRequires session + admin role; returns 403 if not admin

Extension Points

src/backend/auth/auth.ts
packages/i18n/src/translations/{en,zh}/mvp.json
  • Add Social Login: Configure new Providers in src/backend/auth/auth.ts and add corresponding Keys to environment variables.
  • Custom Auth Logic: Extend complex permission requirements (e.g. organization-based) by writing custom middleware or Better Auth plugins.
  • I18n: Derivative auth copy overlays the template's auth keys in both packages/i18n/src/translations/{en,zh}/mvp.json; there is no separate auth.json.

Current Composition Boundary

Better Auth plugin/adapter factory lives in packages/auth/src/create-auth.ts; app src/backend/auth/auth.ts injects DB, mail, captcha, storage, and contracts. OAuth credentials gate provider UI; allowTwoFactorAuth gates settings UI without removing the plugin. Preserve the three getSessionState() states in page guards. Backend routes separately enforce session, admin, and ownership.

On this page