t-convex-nextjs-saas/convex/auth.ts

78 lines
2.2 KiB
TypeScript
Raw Permalink Normal View History

import { createClient, type GenericCtx } from '@convex-dev/better-auth';
import { convex } from '@convex-dev/better-auth/plugins';
2026-04-01 18:59:46 +00:00
import { betterAuth, type BetterAuthOptions } from 'better-auth/minimal';
import { haveIBeenPwned } from 'better-auth/plugins';
import { components } from './_generated/api';
import { DataModel } from './_generated/dataModel';
import { query } from './_generated/server';
import authConfig from './auth.config';
import authSchema from './betterAuth/schema';
import { sendEmail } from './lib/resend';
const siteUrl = process.env.SITE_URL!;
export const authComponent = createClient<DataModel, typeof authSchema>(
components.betterAuth,
{
local: {
schema: authSchema,
},
2026-04-01 18:59:46 +00:00
},
);
2026-04-01 18:59:46 +00:00
export const createAuthOptions = (
ctx: GenericCtx<DataModel>,
): BetterAuthOptions => {
return {
baseURL: siteUrl,
database: authComponent.adapter(ctx),
emailAndPassword: {
2026-04-01 18:59:46 +00:00
minPasswordLength: 8,
maxPasswordLength: 128,
autoSignIn: true,
enabled: true,
requireEmailVerification: true,
sendResetPassword: async ({ user, url }) => {
void sendEmail({
to: user.email,
subject: 'Reset your password',
html: `<p>Click <a href="${url}">here</a> to reset your password.</p>`,
});
},
},
emailVerification: {
sendOnSignUp: true,
sendVerificationEmail: async ({ user, url }) => {
void sendEmail({
to: user.email,
subject: 'Verify your email',
html: `<p>Click <a href="${url}">here</a> to verify your email address.</p>`,
});
},
},
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
},
github: {
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
},
},
2026-04-01 18:59:46 +00:00
plugins: [convex({ authConfig }), haveIBeenPwned()],
};
};
export const createAuth = (ctx: GenericCtx<DataModel>) => {
return betterAuth(createAuthOptions(ctx));
};
export const getCurrentUser = query({
args: {},
handler: async (ctx) => {
return authComponent.getAuthUser(ctx);
},
});