mirror of
https://github.com/tomru/pfadi-bussle.git
synced 2026-03-04 06:57:12 +01:00
migrate auth from next-auth to better-auth with magic link support
Replace next-auth with better-auth, adding magic link email login as the primary auth method and GitHub OAuth as an optional social provider. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
92
lib/auth.ts
Normal file
92
lib/auth.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { betterAuth } from "better-auth"
|
||||
import { magicLink } from "better-auth/plugins"
|
||||
import { mongodbAdapter } from "better-auth/adapters/mongodb"
|
||||
import { MongoClient, ServerApiVersion } from "mongodb"
|
||||
import { MONGO_URI } from "../db"
|
||||
import nodemailer from "nodemailer"
|
||||
|
||||
async function sendEmail({ to, subject, url }: { to: string; subject: string; url: string }) {
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: "wirtanen.uberspace.de",
|
||||
port: 465,
|
||||
secure: true,
|
||||
auth: {
|
||||
user: process.env.SMTP_USER,
|
||||
pass: process.env.SMTP_PASS,
|
||||
},
|
||||
})
|
||||
await transporter.sendMail({
|
||||
from: process.env.FROM_EMAIL,
|
||||
to,
|
||||
subject,
|
||||
text: url,
|
||||
html: `<p>Click <a href="${url}">here</a> to sign in.</p>`,
|
||||
})
|
||||
}
|
||||
|
||||
const ADMIN_EMAIL = process.env.ADMIN_EMAIL
|
||||
const GITHUB_USERS_GRANTED = ['111471']
|
||||
const GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID;
|
||||
const GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET;
|
||||
const GITHUB_ENABLED = Boolean(GITHUB_CLIENT_SECRET?.length && GITHUB_CLIENT_ID?.length);
|
||||
|
||||
const client = new MongoClient(MONGO_URI, {
|
||||
serverApi: {
|
||||
version: ServerApiVersion.v1,
|
||||
strict: true,
|
||||
deprecationErrors: true,
|
||||
}
|
||||
})
|
||||
|
||||
export const auth = betterAuth({
|
||||
database: mongodbAdapter(client.db()),
|
||||
plugins: [
|
||||
magicLink({
|
||||
sendMagicLink: async ({ email, url }) => {
|
||||
await sendEmail({ to: email, subject: "Sign in to Pfadi Bussle", url })
|
||||
},
|
||||
}),
|
||||
],
|
||||
...(GITHUB_ENABLED ? {
|
||||
socialProviders: {
|
||||
github: {
|
||||
provider: 'github',
|
||||
clientId: GITHUB_CLIENT_ID,
|
||||
clientSecret: GITHUB_CLIENT_SECRET,
|
||||
},
|
||||
},
|
||||
} : {}),
|
||||
account: {
|
||||
accountLinking: {
|
||||
enabled: true,
|
||||
trustedProviders: ["github"],
|
||||
},
|
||||
},
|
||||
user: {
|
||||
additionalFields: {
|
||||
role: {
|
||||
type: "string",
|
||||
defaultValue: "user",
|
||||
},
|
||||
},
|
||||
},
|
||||
onRequest: async (request) => {
|
||||
// Authorization logic
|
||||
const session = request.context?.session
|
||||
if (session?.user) {
|
||||
const account = request.context?.account
|
||||
|
||||
// GitHub provider check
|
||||
if (account?.providerId === 'github') {
|
||||
if (!GITHUB_USERS_GRANTED.includes(account.providerAccountId)) {
|
||||
throw new Error('Unauthorized GitHub user')
|
||||
}
|
||||
}
|
||||
|
||||
// Email check - only allow admin email
|
||||
if (session.user.email && session.user.email !== ADMIN_EMAIL) {
|
||||
throw new Error('Unauthorized email')
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
Reference in New Issue
Block a user