mirror of
https://github.com/LukeHagar/better-auth.git
synced 2025-12-06 12:27:44 +00:00
146 lines
3.6 KiB
TypeScript
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 || "",
|
|
},
|
|
},
|
|
});
|