93 lines
2.2 KiB
TypeScript
93 lines
2.2 KiB
TypeScript
|
|
import { betterAuth } from "better-auth";
|
||
|
|
import { magicLink, twoFactor, admin } from "better-auth/plugins";
|
||
|
|
import { nextCookies } from "better-auth/next-js";
|
||
|
|
import { Pool } from "pg";
|
||
|
|
import { sendMagicLinkEmail } from "./services/email";
|
||
|
|
import { ac, adminRole, userRole, superAdminRole } from "./permissions";
|
||
|
|
|
||
|
|
// Create a PostgreSQL pool for Better Auth
|
||
|
|
const pool = new Pool({
|
||
|
|
connectionString: process.env.DATABASE_URL,
|
||
|
|
});
|
||
|
|
|
||
|
|
export const auth = betterAuth({
|
||
|
|
database: pool,
|
||
|
|
appName: "Pulse",
|
||
|
|
baseURL: process.env.BETTER_AUTH_URL,
|
||
|
|
secret: process.env.BETTER_AUTH_SECRET,
|
||
|
|
trustedOrigins: [
|
||
|
|
"http://localhost:3100",
|
||
|
|
"https://pulse.wulfconsulting.cloud"
|
||
|
|
],
|
||
|
|
|
||
|
|
// Email & Password disabled - using magic link and Microsoft OAuth only
|
||
|
|
emailAndPassword: {
|
||
|
|
enabled: false,
|
||
|
|
},
|
||
|
|
|
||
|
|
// Session configuration
|
||
|
|
session: {
|
||
|
|
expiresIn: parseInt(process.env.SESSION_TIMEOUT_SECONDS || "86400"),
|
||
|
|
updateAge: 60 * 60, // Update session every hour
|
||
|
|
cookieCache: {
|
||
|
|
enabled: true,
|
||
|
|
maxAge: 5 * 60, // 5 minutes
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
// Social providers
|
||
|
|
socialProviders: {
|
||
|
|
microsoft: {
|
||
|
|
clientId: process.env.MICROSOFT_CLIENT_ID || "",
|
||
|
|
clientSecret: process.env.MICROSOFT_CLIENT_SECRET || "",
|
||
|
|
tenantId: process.env.MICROSOFT_TENANT_ID || "common",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
|
||
|
|
// Plugins
|
||
|
|
plugins: [
|
||
|
|
// Magic link authentication
|
||
|
|
magicLink({
|
||
|
|
sendMagicLink: async ({ email, url, token }) => {
|
||
|
|
await sendMagicLinkEmail({ email, url, token });
|
||
|
|
},
|
||
|
|
expiresIn: 300, // 5 minutes
|
||
|
|
}),
|
||
|
|
|
||
|
|
// Two-factor authentication
|
||
|
|
twoFactor({
|
||
|
|
issuer: "Pulse",
|
||
|
|
}),
|
||
|
|
|
||
|
|
// Admin plugin with RBAC
|
||
|
|
admin({
|
||
|
|
ac,
|
||
|
|
roles: {
|
||
|
|
"super-admin": superAdminRole,
|
||
|
|
admin: adminRole,
|
||
|
|
user: userRole,
|
||
|
|
},
|
||
|
|
}),
|
||
|
|
|
||
|
|
// Next.js cookie handling - must be last
|
||
|
|
nextCookies(),
|
||
|
|
],
|
||
|
|
|
||
|
|
// User configuration
|
||
|
|
user: {
|
||
|
|
additionalFields: {
|
||
|
|
role: {
|
||
|
|
type: "string",
|
||
|
|
defaultValue: "user",
|
||
|
|
},
|
||
|
|
requires_setup: {
|
||
|
|
type: "boolean",
|
||
|
|
defaultValue: false,
|
||
|
|
},
|
||
|
|
},
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
export type Session = typeof auth.$Infer.Session;
|
||
|
|
export type User = typeof auth.$Infer.Session.user;
|