From 3571f2628487ecb7df137ddc0906efeda425afc6 Mon Sep 17 00:00:00 2001 From: azad-technext Date: Mon, 3 Nov 2025 12:02:20 +0600 Subject: [PATCH 1/2] chore: draft sign in commit --- apps/client/package.json | 3 ++- .../authentication/default/signup/page.tsx | 20 ++++++++++++------- .../authentications/default/SignupForm.tsx | 3 +-- apps/client/src/lib/auth-client.ts | 7 +++++++ apps/server/.env.example | 2 ++ apps/server/auth.ts | 1 + apps/server/package.json | 1 + apps/server/src/main.ts | 15 ++++++++++++-- package.json | 3 ++- pnpm-lock.yaml | 15 ++++++++++---- 10 files changed, 53 insertions(+), 17 deletions(-) create mode 100644 apps/client/src/lib/auth-client.ts diff --git a/apps/client/package.json b/apps/client/package.json index 76def19..f9c8db0 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -3,7 +3,7 @@ "version": "1.0.0", "private": true, "scripts": { - "dev": "next dev --turbopack -p 3001", + "dev": "next dev --turbopack -p 3000", "build": "next build", "start": "next start", "lint": "next lint" @@ -34,6 +34,7 @@ "@mui/x-data-grid": "^8.14.1", "@mui/x-date-pickers": "^8.14.1", "axios": "^1.12.2", + "better-auth": "^1.3.34", "clsx": "^2.1.1", "dayjs": "^1.11.18", "gsap": "^3.13.0", diff --git a/apps/client/src/app/authentication/default/signup/page.tsx b/apps/client/src/app/authentication/default/signup/page.tsx index 2635c1f..18b31c7 100644 --- a/apps/client/src/app/authentication/default/signup/page.tsx +++ b/apps/client/src/app/authentication/default/signup/page.tsx @@ -1,16 +1,22 @@ 'use client'; -import { signIn } from 'next-auth/react'; +import { authClient } from 'lib/auth-client'; import SignupForm from 'components/sections/authentications/default/SignupForm'; const Page = () => { const handleSignup = async (data: { name: string; email: string; password: string }) => { - return await signIn('signup', { - name: data.name, - email: data.email, - password: data.password, - redirect: false, - }); + + try { + const response = await authClient.signUp.email({ + name: data.name, + email: data.email, + password: data.password, + }); + return response; + } catch (error) { + console.error(error); + return error; + } }; return ; diff --git a/apps/client/src/components/sections/authentications/default/SignupForm.tsx b/apps/client/src/components/sections/authentications/default/SignupForm.tsx index ae39919..19e930e 100644 --- a/apps/client/src/components/sections/authentications/default/SignupForm.tsx +++ b/apps/client/src/components/sections/authentications/default/SignupForm.tsx @@ -14,14 +14,13 @@ import { import Grid from "@mui/material/Grid"; import IconifyIcon from "components/base/IconifyIcon"; import PasswordTextField from "components/common/PasswordTextField"; -import { SignInResponse } from "next-auth/react"; import { useForm } from "react-hook-form"; import paths from "routes/paths"; import * as yup from "yup"; import SocialAuth from "./SocialAuth"; interface SignupFormProps { - handleSignup: (data: SignupFormValues) => Promise; + handleSignup: (data: SignupFormValues) => Promise; socialAuth?: boolean; } diff --git a/apps/client/src/lib/auth-client.ts b/apps/client/src/lib/auth-client.ts new file mode 100644 index 0000000..016c82d --- /dev/null +++ b/apps/client/src/lib/auth-client.ts @@ -0,0 +1,7 @@ +import { createAuthClient } from "better-auth/react" + +export const authClient = createAuthClient({ + /** The base URL of the server (optional if you're using the same domain) */ + baseURL: process.env.BETTER_AUTH_URL || "http://localhost:4000/api/auth", + fetchOptions: { credentials: 'include' }, +}) \ No newline at end of file diff --git a/apps/server/.env.example b/apps/server/.env.example index 5a17660..f25679c 100644 --- a/apps/server/.env.example +++ b/apps/server/.env.example @@ -21,4 +21,6 @@ STRIPE_SECRET_KEY=sk_test_ GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= +TRUSTED_ORIGINS=http://localhost:3000 + diff --git a/apps/server/auth.ts b/apps/server/auth.ts index 78d64c7..9ff2d04 100644 --- a/apps/server/auth.ts +++ b/apps/server/auth.ts @@ -25,6 +25,7 @@ export const auth: AuthInstance = betterAuth({ transaction: true, debugLogs: true, }), + trustedOrigins: ['http://localhost:3000'], // npx @better-auth/cli@latest generate appName: 'Server', plugins: [ diff --git a/apps/server/package.json b/apps/server/package.json index 84c8398..57ec9b7 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -15,6 +15,7 @@ "nest": "nest", "dev": "pnpm run start:dev", "prisma:generate": "pnpx prisma generate", + "prisma:dev": "pnpx prisma migrate dev", "build": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", "start": "nest start", diff --git a/apps/server/src/main.ts b/apps/server/src/main.ts index 06d079d..d2c8b75 100644 --- a/apps/server/src/main.ts +++ b/apps/server/src/main.ts @@ -36,6 +36,7 @@ async function bootstrap() { "'self'", 'https://cdn.jsdelivr.net', 'http://localhost:3000', + 'http://localhost:4000', ], }, }, @@ -45,7 +46,17 @@ async function bootstrap() { origin: corsConfig.origins, credentials: corsConfig.credentials, methods: corsConfig.methods, - allowedHeaders: corsConfig.allowedHeaders, + // allowedHeaders: corsConfig.allowedHeaders, + allowedHeaders: + corsConfig.allowedHeaders.length > 0 + ? corsConfig.allowedHeaders + : [ + 'Content-Type', + 'Authorization', + 'X-Requested-With', + 'Accept', + 'Origin', + ], }); app.useGlobalPipes( new ValidationPipe({ @@ -72,7 +83,7 @@ async function bootstrap() { const documentFactory = () => SwaggerModule.createDocument(app, config); SwaggerModule.setup('api', app, documentFactory); - // app.setGlobalPrefix('api'); + app.setGlobalPrefix('api'); await app.listen(port); Logger.debug(`Server started on http://localhost:${port}`); Logger.debug( diff --git a/package.json b/package.json index 941ef62..ab9549f 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "dev:client": "pnpm --filter client dev", "prebuild": "pnpm -r --filter server run prisma:generate", "dev:server": "pnpm --filter server start:dev", - "build:client": "pnpm --filter client build", + "build:client": "pnpm --filter client build", + "prisma:dev": "pnpm --filter server run prisma:dev", "build:server": "pnpm --filter server build", "start:client": "pnpm --filter client start", "start:server": "pnpm --filter server start", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3fd5168..cf3300e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -99,6 +99,9 @@ importers: axios: specifier: ^1.12.2 version: 1.13.1 + better-auth: + specifier: ^1.3.34 + version: 1.3.34(next@15.5.6(@babel/core@7.28.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -246,7 +249,7 @@ importers: version: 1.13.1 better-auth: specifier: ^1.3.34 - version: 1.3.34 + version: 1.3.34(next@15.5.6(@babel/core@7.28.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) cache-manager: specifier: ^7.2.4 version: 7.2.4 @@ -6039,7 +6042,7 @@ snapshots: '@better-auth/stripe@1.3.34(@better-auth/core@1.3.34(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.0.19)(jose@6.1.0)(kysely@0.28.8)(nanostores@1.0.1))(better-auth@1.3.34)(stripe@19.2.0(@types/node@22.18.12))': dependencies: '@better-auth/core': 1.3.34(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.0.19)(jose@6.1.0)(kysely@0.28.8)(nanostores@1.0.1) - better-auth: 1.3.34 + better-auth: 1.3.34(next@15.5.6(@babel/core@7.28.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) defu: 6.1.4 stripe: 19.2.0(@types/node@22.18.12) zod: 4.1.12 @@ -7727,7 +7730,7 @@ snapshots: '@nestjs/common': 11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/core': 11.1.6(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/platform-express@11.1.6)(reflect-metadata@0.2.2)(rxjs@7.8.2) '@nestjs/graphql': 13.2.0(@nestjs/common@11.1.6(class-transformer@0.5.1)(class-validator@0.14.2)(reflect-metadata@0.2.2)(rxjs@7.8.2))(@nestjs/core@11.1.6)(class-transformer@0.5.1)(class-validator@0.14.2)(graphql@16.11.0)(reflect-metadata@0.2.2) - better-auth: 1.3.34 + better-auth: 1.3.34(next@15.5.6(@babel/core@7.28.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0) express: 5.1.0 graphql: 16.11.0 typescript: 5.9.3 @@ -8422,7 +8425,7 @@ snapshots: baseline-browser-mapping@2.8.18: {} - better-auth@1.3.34: + better-auth@1.3.34(next@15.5.6(@babel/core@7.28.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(react-dom@19.2.0(react@19.2.0))(react@19.2.0): dependencies: '@better-auth/core': 1.3.34(@better-auth/utils@0.3.0)(@better-fetch/fetch@1.1.18)(better-call@1.0.19)(jose@6.1.0)(kysely@0.28.8)(nanostores@1.0.1) '@better-auth/telemetry': 1.3.34(better-call@1.0.19)(jose@6.1.0)(kysely@0.28.8)(nanostores@1.0.1) @@ -8438,6 +8441,10 @@ snapshots: kysely: 0.28.8 nanostores: 1.0.1 zod: 4.1.12 + optionalDependencies: + next: 15.5.6(@babel/core@7.28.4)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) better-call@1.0.19: dependencies: From 8372d0819eaaf3e5d7fcb3b3d0aa7ff32a14ac60 Mon Sep 17 00:00:00 2001 From: azad-technext Date: Mon, 3 Nov 2025 13:13:00 +0600 Subject: [PATCH 2/2] feat(client): integrate login with better auth --- .../app/authentication/default/login/page.tsx | 22 ++++++++++--------- .../authentications/default/LoginForm.tsx | 10 +++++---- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/apps/client/src/app/authentication/default/login/page.tsx b/apps/client/src/app/authentication/default/login/page.tsx index 0f71830..6b7ad8d 100644 --- a/apps/client/src/app/authentication/default/login/page.tsx +++ b/apps/client/src/app/authentication/default/login/page.tsx @@ -1,17 +1,20 @@ 'use client'; -import { signIn } from 'next-auth/react'; import LoginForm from 'components/sections/authentications/default/LoginForm'; -import paths from 'routes/paths'; -import { defaultJwtAuthCredentials } from 'config'; +import paths, { rootPaths } from 'routes/paths'; +import { authClient } from 'lib/auth-client'; +import { useRouter } from 'next/navigation'; const Page = () => { - const handleLogin = async (data: { email: string; password: string }) => { - return await signIn('credentials', { - email: data.email, - password: data.password, - redirect: false, - }); + const router = useRouter() + const handleLogin = async (data: { email: string; password: string , rememberDevice: boolean }) => { + try { + const response = await authClient.signIn.email(data) + return response + + } catch (error) { + return error + } }; return ( @@ -21,7 +24,6 @@ const Page = () => { forgotPasswordLink={paths.forgotPassword} socialAuth={false} rememberDevice={true} - defaultCredential={defaultJwtAuthCredentials} /> ); }; diff --git a/apps/client/src/components/sections/authentications/default/LoginForm.tsx b/apps/client/src/components/sections/authentications/default/LoginForm.tsx index 168fa02..4baa90e 100644 --- a/apps/client/src/components/sections/authentications/default/LoginForm.tsx +++ b/apps/client/src/components/sections/authentications/default/LoginForm.tsx @@ -24,7 +24,7 @@ import DefaultCredentialAlert from '../common/DefaultCredentialAlert'; import SocialAuth from './SocialAuth'; interface LoginFormProps { - handleLogin: (data: LoginFormValues) => Promise; + handleLogin: (data: LoginFormValues) => Promise; signUpLink: string; socialAuth?: boolean; forgotPasswordLink?: string; @@ -34,6 +34,7 @@ interface LoginFormProps { export interface LoginFormValues { email: string; password: string; + rememberDevice: boolean; } const schema = yup @@ -43,6 +44,7 @@ const schema = yup .email('Please provide a valid email address.') .required('This field is required'), password: yup.string().required('This field is required'), + rememberDevice: yup.boolean().optional().default(false), }) .required(); @@ -70,7 +72,7 @@ const LoginForm = ({ const onSubmit = async (data: LoginFormValues) => { const res = await handleLogin(data); - if (res?.ok) { + if (res?.data?.token) { router.refresh(); router.push(callbackUrl ? callbackUrl : rootPaths.root); } @@ -193,8 +195,8 @@ const LoginForm = ({ }} > {rememberDevice && ( - } + } label={