68 lines
2.8 KiB
TypeScript
68 lines
2.8 KiB
TypeScript
import { betterAuth } from 'better-auth'
|
|
import { admin } from 'better-auth/plugins'
|
|
import { actor, fabric } from '@pikku/better-auth'
|
|
import { pikkuBetterAuth } from '#pikku/pikku-types.gen.js'
|
|
|
|
export const auth = pikkuBetterAuth(async ({ kysely, secrets, variables }) => {
|
|
const BETTER_AUTH_SECRET = await secrets.getSecret('BETTER_AUTH_SECRET')
|
|
// Genuinely optional: unset simply disables /api/auth/sign-in/actor (scenarios
|
|
// off for this deployment) — the actor plugin refuses all sign-ins
|
|
// without it.
|
|
const SCENARIO_ACTOR_SECRET = await secrets
|
|
.getSecret('SCENARIO_ACTOR_SECRET')
|
|
.catch(() => undefined)
|
|
// Fabric operator admin: the RSA public key the control plane's token is
|
|
// verified against. The Fabric deployer pushes FABRIC_AUTH_PUBLIC_KEY onto
|
|
// every stage; locally it's simply absent, which disables /sign-in/fabric.
|
|
// Asymmetric — the app verifies, it can never forge an operator login.
|
|
const FABRIC_AUTH_PUBLIC_KEY = await variables.get('FABRIC_AUTH_PUBLIC_KEY')
|
|
|
|
return betterAuth({
|
|
secret: BETTER_AUTH_SECRET,
|
|
database: { db: kysely as any, type: 'sqlite' },
|
|
emailAndPassword: { enabled: true },
|
|
session: {
|
|
cookieCache: { enabled: true, maxAge: 5 * 60 },
|
|
},
|
|
advanced: { database: { generateId: 'uuid' } },
|
|
user: {
|
|
additionalFields: {
|
|
role: {
|
|
type: 'string',
|
|
required: false,
|
|
defaultValue: 'client',
|
|
input: false,
|
|
},
|
|
locale: {
|
|
type: 'string',
|
|
required: false,
|
|
defaultValue: 'de',
|
|
input: true,
|
|
},
|
|
},
|
|
},
|
|
// Scenario actors: synthetic users (user.actor = true, see
|
|
// db/sqlite/0012-user-actor.sql) signed in by pikkuScenario via
|
|
// POST /api/auth/sign-in/actor { email, secret }. Never signs in real users.
|
|
//
|
|
// admin(): exposes /api/auth/admin/* (listUsers, setRole, impersonateUser,
|
|
// …) so an app admin can list and "view as" their end-users — this is what
|
|
// the Fabric console's Users tab drives. Adds role/banned/impersonatedBy
|
|
// columns (see db/sqlite/0013-admin.sql). No user is an admin by default:
|
|
// grant it by setting a user's `role` to 'admin' (or pass
|
|
// `adminUserIds: [...]` here) — the admin API refuses non-admins.
|
|
//
|
|
// fabric(): exposes /api/auth/sign-in/fabric — the Fabric control plane
|
|
// mints a short-lived RS256 token and signs in as a synthetic `fabric: true`
|
|
// admin operator (db/sqlite/0014-fabric.sql), so the console Users tab can
|
|
// list/impersonate real users without the operator being one of them. It
|
|
// pairs with admin() and verifies against FABRIC_AUTH_PUBLIC_KEY; missing
|
|
// key disables the endpoint.
|
|
plugins: [
|
|
actor({ secret: SCENARIO_ACTOR_SECRET }),
|
|
admin(),
|
|
fabric({ publicKey: FABRIC_AUTH_PUBLIC_KEY }),
|
|
],
|
|
})
|
|
})
|