Files
better-auth/demo/nextjs/lib/auth.ts
2024-10-17 21:19:31 +03:00

146 lines
3.6 KiB
TypeScript

import { betterAuth } from "better-auth";
import {
bearer,
organization,
passkey,
twoFactor,
admin,
} from "better-auth/plugins";
import { reactInvitationEmail } from "./email/invitation";
import { LibsqlDialect } from "@libsql/kysely-libsql";
import { reactResetPasswordEmail } from "./email/rest-password";
import { resend } from "./email/resend";
const from = process.env.BETTER_AUTH_EMAIL || "delivered@resend.dev";
const to = process.env.TEST_EMAIL || "";
const libsql = new LibsqlDialect({
url: process.env.TURSO_DATABASE_URL || "",
authToken: process.env.TURSO_AUTH_TOKEN || "",
});
export const auth = betterAuth({
database: {
dialect: libsql,
type: "sqlite",
},
emailAndPassword: {
enabled: true,
async sendResetPassword(url, user) {
await resend.emails.send({
from,
to: user.email,
subject: "Reset your password",
react: reactResetPasswordEmail({
username: user.email,
resetLink: url,
}),
});
},
sendEmailVerificationOnSignUp: true,
async sendVerificationEmail(email, url) {
console.log("Sending verification email to", email);
const res = await resend.emails.send({
from,
to: to || email,
subject: "Verify your email address",
html: `<a href="${url}">Verify your email address</a>`,
});
console.log(res, email);
},
},
plugins: [
organization({
async sendInvitationEmail(data) {
const res = await resend.emails.send({
from,
to: data.email,
subject: "You've been invited to join an organization",
react: reactInvitationEmail({
username: data.email,
invitedByUsername: data.inviter.user.name,
invitedByEmail: data.inviter.user.email,
teamName: data.organization.name,
inviteLink:
process.env.NODE_ENV === "development"
? `http://localhost:3000/accept-invitation/${data.id}`
: `https://${
process.env.NEXT_PUBLIC_APP_URL ||
process.env.VERCEL_URL ||
process.env.BETTER_AUTH_URL
}/accept-invitation/${data.id}`,
}),
});
console.log(res, data.email);
},
}),
twoFactor({
otpOptions: {
async sendOTP(user, otp) {
await resend.emails.send({
from,
to: user.email,
subject: "Your OTP",
html: `Your OTP is ${otp}`,
});
},
},
}),
passkey(),
bearer(),
admin(),
{
id: "last-login-ip",
hooks: {
after: [
{
matcher(context) {
return true;
},
async handler(ctx) {
const header = ctx.headers;
const response = ctx.context.returned;
if (response instanceof Response) {
const hasSetCookie = response.headers.get("set-cookie");
const hasSessionCookie = response.headers
.get("set-cookie")
?.includes("session_token");
if (hasSessionCookie) {
const ipAddress =
header?.get("x-forwarded-for") ||
header?.get("cf-connecting-ip");
if (ipAddress) {
//update the user's last login IP
}
}
}
},
},
],
},
},
],
socialProviders: {
github: {
clientId: process.env.GITHUB_CLIENT_ID || "",
clientSecret: process.env.GITHUB_CLIENT_SECRET || "",
},
google: {
clientId: process.env.GOOGLE_CLIENT_ID || "",
clientSecret: process.env.GOOGLE_CLIENT_SECRET || "",
},
discord: {
clientId: process.env.DISCORD_CLIENT_ID || "",
clientSecret: process.env.DISCORD_CLIENT_SECRET || "",
},
microsoft: {
clientId: process.env.MICROSOFT_CLIENT_ID || "",
clientSecret: process.env.MICROSOFT_CLIENT_SECRET || "",
},
twitch: {
clientId: process.env.TWITCH_CLIENT_ID || "",
clientSecret: process.env.TWITCH_CLIENT_SECRET || "",
},
},
});