Files
beenvoice-web/src/lib/auth.ts
T
2026-01-14 03:17:54 -05:00

70 lines
2.8 KiB
TypeScript

import { betterAuth } from "better-auth";
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { nextCookies } from "better-auth/next-js";
import { sso } from "@better-auth/sso";
import { db } from "~/server/db";
import * as schema from "~/server/db/schema";
export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg",
schema: {
user: schema.users,
session: schema.sessions,
account: schema.accounts,
verification: schema.verificationTokens,
},
}),
trustedOrigins: [
"https://beenvoice.soconnor.dev",
"https://auth.soconnor.dev", // Authentik IdP for OIDC discovery
],
accountLinking: {
enabled: true,
trustedProviders: ["authentik"],
},
emailAndPassword: {
enabled: true,
password: {
hash: async (password) => {
const bcrypt = await import("bcryptjs");
return bcrypt.hash(password, 12);
},
verify: async ({ hash, password }) => {
const bcrypt = await import("bcryptjs");
return bcrypt.compare(password, hash);
},
},
},
plugins: [
nextCookies(),
sso({
// Only configure default SSO if Authentik credentials are provided
defaultSSO:
process.env.AUTHENTIK_ISSUER &&
process.env.AUTHENTIK_CLIENT_ID &&
process.env.AUTHENTIK_CLIENT_SECRET
? [
{
providerId: "authentik",
domain: "beenvoice.soconnor.dev",
oidcConfig: {
issuer: process.env.AUTHENTIK_ISSUER,
clientId: process.env.AUTHENTIK_CLIENT_ID,
clientSecret: process.env.AUTHENTIK_CLIENT_SECRET,
discoveryEndpoint: `${process.env.AUTHENTIK_ISSUER}/.well-known/openid-configuration`,
// Explicit endpoints to bypass discovery issues
authorizationEndpoint: "https://auth.soconnor.dev/application/o/authorize/",
tokenEndpoint: "https://auth.soconnor.dev/application/o/token/",
userInfoEndpoint: "https://auth.soconnor.dev/application/o/userinfo/",
jwksEndpoint: "https://auth.soconnor.dev/application/o/beenvoice/jwks/",
scopes: ["openid", "email", "profile"],
pkce: true,
},
},
]
: [],
}),
],
});