diff --git a/README.md b/README.md index e523f7ed88..f39e87aa49 100644 --- a/README.md +++ b/README.md @@ -142,9 +142,7 @@ Create [new credentials](https://console.cloud.google.com/apis/credentials): 2. In `Application Type`, Choose `Web application` 3. Choose a name for your web client 4. In Authorized JavaScript origins, add a URI and enter `http://localhost:3000` - 5. In `Authorized redirect URIs` enter: - - `http://localhost:3000/api/auth/callback/google` - - `http://localhost:3000/api/google/linking/callback` + 5. In `Authorized redirect URIs` enter `http://localhost:3000/api/auth/callback/google` 6. Click `Create`. 7. A popup will show up with the new credentials, including the Client ID and secret. 3. Update .env file: diff --git a/apps/web/app/(app)/ErrorMessages.tsx b/apps/web/app/(app)/ErrorMessages.tsx index 64faf2c0c3..243a1b17df 100644 --- a/apps/web/app/(app)/ErrorMessages.tsx +++ b/apps/web/app/(app)/ErrorMessages.tsx @@ -1,11 +1,12 @@ import { auth } from "@/utils/auth"; +import { headers } from "next/headers"; import { AlertError } from "@/components/Alert"; import { Button } from "@/components/ui/button"; import { clearUserErrorMessagesAction } from "@/utils/actions/error-messages"; import { getUserErrorMessages } from "@/utils/error-messages"; export async function ErrorMessages() { - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); if (!session?.user) return null; const errorMessages = await getUserErrorMessages(session.user.id); diff --git a/apps/web/app/(app)/[emailAccountId]/debug/rule-history/[ruleId]/page.tsx b/apps/web/app/(app)/[emailAccountId]/debug/rule-history/[ruleId]/page.tsx index 24ad28e2cf..3952c6c222 100644 --- a/apps/web/app/(app)/[emailAccountId]/debug/rule-history/[ruleId]/page.tsx +++ b/apps/web/app/(app)/[emailAccountId]/debug/rule-history/[ruleId]/page.tsx @@ -11,12 +11,13 @@ import { Badge } from "@/components/ui/badge"; import { notFound } from "next/navigation"; import { formatDistanceToNow } from "date-fns"; import { auth } from "@/utils/auth"; +import { headers } from "next/headers"; export default async function RuleHistoryPage(props: { params: Promise<{ emailAccountId: string; ruleId: string }>; }) { const { emailAccountId, ruleId } = await props.params; - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); if (!session?.user.id) notFound(); const rule = await prisma.rule.findFirst({ diff --git a/apps/web/app/(app)/[emailAccountId]/settings/MultiAccountSection.tsx b/apps/web/app/(app)/[emailAccountId]/settings/MultiAccountSection.tsx index 42bc7f741f..5223a2cc1b 100644 --- a/apps/web/app/(app)/[emailAccountId]/settings/MultiAccountSection.tsx +++ b/apps/web/app/(app)/[emailAccountId]/settings/MultiAccountSection.tsx @@ -2,7 +2,7 @@ import { useCallback } from "react"; import { type SubmitHandler, useFieldArray, useForm } from "react-hook-form"; -import { useSession } from "@/utils/auth-client"; +import { authClient } from "@/utils/auth-client"; import { zodResolver } from "@hookform/resolvers/zod"; import useSWR from "swr"; import { usePostHog } from "posthog-js/react"; @@ -31,7 +31,7 @@ import { useAction } from "next-safe-action/hooks"; import { toastError, toastSuccess } from "@/components/Toast"; export function MultiAccountSection() { - const { data: session } = useSession(); + const { data: session } = authClient.useSession(); const { data, isLoading, error, mutate } = useSWR( "/api/user/settings/multi-account", ); diff --git a/apps/web/app/(app)/accounts/AddAccount.tsx b/apps/web/app/(app)/accounts/AddAccount.tsx index 179486a029..e2fad8444a 100644 --- a/apps/web/app/(app)/accounts/AddAccount.tsx +++ b/apps/web/app/(app)/accounts/AddAccount.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { signIn } from "@/utils/auth-client"; +import { authClient } from "@/utils/auth-client"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import { toastError } from "@/components/Toast"; @@ -19,9 +19,10 @@ import { SCOPES as OUTLOOK_SCOPES } from "@/utils/outlook/scopes"; export function AddAccount() { const handleConnectGoogle = async () => { - await signIn.social({ + await authClient.signIn.social({ provider: "google", - callbackURL: "/welcome", + callbackURL: "/accounts", + newUserCallbackURL: "/welcome", scopes: [...GMAIL_SCOPES], }); }; @@ -38,9 +39,10 @@ export function AddAccount() { }; const handleConnectMicrosoft = async () => { - await signIn.social({ + await authClient.signIn.social({ provider: "microsoft", - callbackURL: "/welcome", + callbackURL: "/accounts", + newUserCallbackURL: "/welcome", scopes: [...OUTLOOK_SCOPES], }); }; diff --git a/apps/web/app/(app)/admin/page.tsx b/apps/web/app/(app)/admin/page.tsx index 210abc4acb..1fe170f284 100644 --- a/apps/web/app/(app)/admin/page.tsx +++ b/apps/web/app/(app)/admin/page.tsx @@ -2,6 +2,7 @@ import { AdminUpgradeUserForm } from "@/app/(app)/admin/AdminUpgradeUserForm"; import { AdminUserControls } from "@/app/(app)/admin/AdminUserControls"; import { TopSection } from "@/components/TopSection"; import { auth } from "@/utils/auth"; +import { headers } from "next/headers"; import { ErrorPage } from "@/components/ErrorPage"; import { isAdmin } from "@/utils/admin"; import { @@ -13,7 +14,7 @@ import { export const maxDuration = 800; export default async function AdminPage() { - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); if (!isAdmin({ email: session?.user.email })) { return ( diff --git a/apps/web/app/(app)/layout.tsx b/apps/web/app/(app)/layout.tsx index 968ae3087b..f2b8278629 100644 --- a/apps/web/app/(app)/layout.tsx +++ b/apps/web/app/(app)/layout.tsx @@ -7,6 +7,7 @@ import { redirect } from "next/navigation"; import { SideNavWithTopNav } from "@/components/SideNavWithTopNav"; import { auth } from "@/utils/auth"; +import { headers } from "next/headers"; import { PostHogIdentify } from "@/providers/PostHogProvider"; import { CommandK } from "@/components/CommandK"; import { AppProviders } from "@/providers/AppProviders"; @@ -35,7 +36,7 @@ export default async function AppLayout({ }: { children: React.ReactNode; }) { - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); if (!session?.user.email) redirect("/login"); diff --git a/apps/web/app/(landing)/login/LoginForm.tsx b/apps/web/app/(landing)/login/LoginForm.tsx index bfc738f5d3..5bbfe4765f 100644 --- a/apps/web/app/(landing)/login/LoginForm.tsx +++ b/apps/web/app/(landing)/login/LoginForm.tsx @@ -1,7 +1,7 @@ "use client"; import { useState } from "react"; -import { signIn } from "@/utils/auth-client"; +import { authClient } from "@/utils/auth-client"; import Image from "next/image"; import { useSearchParams } from "next/navigation"; import { Button } from "@/components/Button"; @@ -24,7 +24,7 @@ export function LoginForm() { const handleGoogleSignIn = async () => { setLoadingGoogle(true); - await signIn.social({ + await authClient.signIn.social({ provider: "google", errorCallbackURL: "/login", callbackURL: next && next.length > 0 ? next : "/welcome", @@ -35,7 +35,7 @@ export function LoginForm() { const handleMicrosoftSignIn = async () => { setLoadingMicrosoft(true); - await signIn.social({ + await authClient.signIn.social({ provider: "microsoft", errorCallbackURL: "/login", callbackURL: next && next.length > 0 ? next : "/welcome", diff --git a/apps/web/app/(landing)/login/page.tsx b/apps/web/app/(landing)/login/page.tsx index 86d9ac67fc..3c270457a3 100644 --- a/apps/web/app/(landing)/login/page.tsx +++ b/apps/web/app/(landing)/login/page.tsx @@ -4,6 +4,8 @@ import { redirect } from "next/navigation"; import Link from "next/link"; import { LoginForm } from "@/app/(landing)/login/LoginForm"; import { auth } from "@/utils/auth"; +import { headers } from "next/headers"; +import AutoLogOut from "@/app/(landing)/login/error/AutoLogOut"; import { AlertBasic } from "@/components/Alert"; import { env } from "@/env"; import { Button } from "@/components/ui/button"; @@ -18,7 +20,7 @@ export default async function AuthenticationPage(props: { searchParams?: Promise>; }) { const searchParams = await props.searchParams; - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); if (session?.user && !searchParams?.error) { if (searchParams?.next) { redirect(searchParams?.next); @@ -43,7 +45,7 @@ export default async function AuthenticationPage(props: { {searchParams?.error && ( - + )}

@@ -80,7 +82,7 @@ export default async function AuthenticationPage(props: { ); } -function ErrorAlert({ error }: { error: string; }) { +function ErrorAlert({ error, loggedIn }: { error: string; loggedIn: boolean }) { if (error === "RequiresReconsent") return null; if (error === "OAuthAccountNotLinked") { @@ -101,10 +103,13 @@ function ErrorAlert({ error }: { error: string; }) { } return ( + <> + {/* */} + ); } diff --git a/apps/web/app/(landing)/welcome/page.tsx b/apps/web/app/(landing)/welcome/page.tsx index 5a53735277..07c7f00b32 100644 --- a/apps/web/app/(landing)/welcome/page.tsx +++ b/apps/web/app/(landing)/welcome/page.tsx @@ -2,6 +2,7 @@ import { Suspense } from "react"; import type { Metadata } from "next"; import { redirect } from "next/navigation"; import { auth } from "@/utils/auth"; +import { headers } from "next/headers"; import { OnboardingForm } from "@/app/(landing)/welcome/form"; import { SquaresPattern } from "@/app/(landing)/home/SquaresPattern"; import { env } from "@/env"; @@ -21,7 +22,7 @@ export default async function WelcomePage(props: { searchParams: Promise<{ question?: string; force?: boolean }>; }) { const searchParams = await props.searchParams; - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); if (!session?.user) redirect("/login"); if (!env.NEXT_PUBLIC_POSTHOG_ONBOARDING_SURVEY_ID) diff --git a/apps/web/app/api/auth/[...all]/route.ts b/apps/web/app/api/auth/[...all]/route.ts index 5f4f836663..8b895ded2b 100644 --- a/apps/web/app/api/auth/[...all]/route.ts +++ b/apps/web/app/api/auth/[...all]/route.ts @@ -1,4 +1,4 @@ -import { betterAuthConfig } from "@/utils/auth"; +import { auth } from "@/utils/auth"; import { toNextJsHandler } from "better-auth/next-js"; -export const { POST, GET } = toNextJsHandler(betterAuthConfig); +export const { POST, GET } = toNextJsHandler(auth); diff --git a/apps/web/app/api/outlook/linking/callback/route.ts b/apps/web/app/api/outlook/linking/callback/route.ts index 19e03d692f..f2db3797e8 100644 --- a/apps/web/app/api/outlook/linking/callback/route.ts +++ b/apps/web/app/api/outlook/linking/callback/route.ts @@ -93,17 +93,18 @@ export const GET = withError(async (request: NextRequest) => { } const profile = await profileResponse.json(); + const providerAccountId = profile.id; const providerEmail = profile.mail || profile.userPrincipalName; - if (!providerEmail) { - throw new Error("Profile missing required email"); + if (!providerAccountId || !providerEmail) { + throw new Error("Profile missing required id or email"); } - const existingAccount = await prisma.account.findFirst({ + const existingAccount = await prisma.account.findUnique({ where: { - provider: "microsoft", - user: { - email: providerEmail, + provider_providerAccountId: { + provider: "microsoft", + providerAccountId, }, }, select: { @@ -115,7 +116,7 @@ export const GET = withError(async (request: NextRequest) => { if (!existingAccount) { logger.warn( - `Merge Failed: Microsoft account ${providerEmail} not found in the system. Cannot merge.`, + `Merge Failed: Microsoft account ${providerEmail} (${providerAccountId}) not found in the system. Cannot merge.`, ); redirectUrl.searchParams.set("error", "account_not_found_for_merge"); return NextResponse.redirect(redirectUrl, { headers: response.headers }); @@ -123,7 +124,7 @@ export const GET = withError(async (request: NextRequest) => { if (existingAccount.userId === targetUserId) { logger.warn( - `Microsoft account ${providerEmail} is already linked to the correct user ${targetUserId}. Merge action unnecessary.`, + `Microsoft account ${providerEmail} (${providerAccountId}) is already linked to the correct user ${targetUserId}. Merge action unnecessary.`, ); redirectUrl.searchParams.set("error", "already_linked_to_self"); return NextResponse.redirect(redirectUrl, { @@ -132,7 +133,7 @@ export const GET = withError(async (request: NextRequest) => { } logger.info( - `Merging Microsoft account ${providerEmail} linked to user ${existingAccount.userId}, merging into ${targetUserId}.`, + `Merging Microsoft account ${providerEmail} (${providerAccountId}) linked to user ${existingAccount.userId}, merging into ${targetUserId}.`, ); await prisma.$transaction([ prisma.account.update({ @@ -153,7 +154,7 @@ export const GET = withError(async (request: NextRequest) => { ]); logger.info( - `Account ${providerEmail} re-assigned to user ${targetUserId}. Original user was ${existingAccount.userId}`, + `Account ${providerAccountId} re-assigned to user ${targetUserId}. Original user was ${existingAccount.userId}`, ); redirectUrl.searchParams.set("success", "account_merged"); return NextResponse.redirect(redirectUrl, { diff --git a/apps/web/app/api/user/complete-registration/route.ts b/apps/web/app/api/user/complete-registration/route.ts index 4963243824..1401d2d013 100644 --- a/apps/web/app/api/user/complete-registration/route.ts +++ b/apps/web/app/api/user/complete-registration/route.ts @@ -12,7 +12,7 @@ import type { ReadonlyHeaders } from "next/dist/server/web/spec-extension/adapte const logger = createScopedLogger("complete-registration"); export const POST = withError(async () => { - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); if (!session?.user.email) return NextResponse.json({ error: "Not authenticated" }); diff --git a/apps/web/app/api/user/me/route.ts b/apps/web/app/api/user/me/route.ts index c6a439c871..c69b561c79 100644 --- a/apps/web/app/api/user/me/route.ts +++ b/apps/web/app/api/user/me/route.ts @@ -3,6 +3,7 @@ import prisma from "@/utils/prisma"; import { withError } from "@/utils/middleware"; import { SafeError } from "@/utils/error"; import { auth } from "@/utils/auth"; +import { headers } from "next/headers"; export type UserResponse = Awaited> | null; @@ -40,7 +41,7 @@ async function getUser({ userId }: { userId: string }) { // Intentionally not using withAuth because we want to return null if the user is not authenticated export const GET = withError(async () => { - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); const userId = session?.user.id; if (!userId) return NextResponse.json(null); diff --git a/apps/web/components/TopNav.tsx b/apps/web/components/TopNav.tsx index 265a6e9aa7..450b0114cd 100644 --- a/apps/web/components/TopNav.tsx +++ b/apps/web/components/TopNav.tsx @@ -2,7 +2,7 @@ import Link from "next/link"; import { useRouter } from "next/navigation"; -import { useSession } from "@/utils/auth-client"; +import { authClient } from "@/utils/auth-client"; import { Menu, MenuButton, @@ -43,7 +43,7 @@ export function TopNav({ trigger }: { trigger: React.ReactNode }) { } function ProfileDropdown() { - const { data: session, isPending } = useSession(); + const { data: session, isPending } = authClient.useSession(); const { emailAccountId, emailAccount, provider } = useAccount(); const router = useRouter(); diff --git a/apps/web/env.ts b/apps/web/env.ts index 567a52e121..2e25be99fc 100644 --- a/apps/web/env.ts +++ b/apps/web/env.ts @@ -116,6 +116,8 @@ export const env = createEnv({ LICENSE_25_SEAT_VARIANT_ID: z.coerce.number().optional(), DUB_API_KEY: z.string().optional(), + + COOKIE_DOMAIN: z.string().default("getinboxzero.com"), }, client: { // stripe diff --git a/apps/web/providers/PostHogProvider.tsx b/apps/web/providers/PostHogProvider.tsx index c609ef35ba..3117020603 100644 --- a/apps/web/providers/PostHogProvider.tsx +++ b/apps/web/providers/PostHogProvider.tsx @@ -3,7 +3,7 @@ import { useEffect } from "react"; import posthog from "posthog-js"; import { PostHogProvider as PHProvider } from "posthog-js/react"; -import { useSession } from "@/utils/auth-client"; +import { authClient } from "@/utils/auth-client"; import { usePathname, useSearchParams } from "next/navigation"; import { env } from "@/env"; @@ -29,7 +29,7 @@ export function PostHogPageview() { } export function PostHogIdentify() { - const { data: session } = useSession(); + const { data: session } = authClient.useSession(); useEffect(() => { if (session?.user.email) diff --git a/apps/web/providers/SessionProvider.tsx b/apps/web/providers/SessionProvider.tsx index 725ed84c79..00b5342980 100644 --- a/apps/web/providers/SessionProvider.tsx +++ b/apps/web/providers/SessionProvider.tsx @@ -1,8 +1,8 @@ "use client"; -import { useSession } from "@/utils/auth-client"; +import { authClient } from "@/utils/auth-client"; -export { useSession }; +export const useSession = authClient.useSession; export function SessionProvider({ children }: { children: React.ReactNode }) { return <>{children}; diff --git a/apps/web/utils/account.ts b/apps/web/utils/account.ts index 550452f9df..7cc1e9bf53 100644 --- a/apps/web/utils/account.ts +++ b/apps/web/utils/account.ts @@ -1,4 +1,5 @@ import { auth } from "@/utils/auth"; +import { headers } from "next/headers"; import { getGmailClientWithRefresh, getAccessTokenFromClient, @@ -135,7 +136,7 @@ async function getTokens({ emailAccountId }: { emailAccountId: string }) { } export async function redirectToEmailAccountPath(path: `/${string}`) { - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); const userId = session?.user.id; if (!userId) throw new Error("Not authenticated"); diff --git a/apps/web/utils/actions/safe-action.ts b/apps/web/utils/actions/safe-action.ts index cad1d9b0d9..94d7ba9c65 100644 --- a/apps/web/utils/actions/safe-action.ts +++ b/apps/web/utils/actions/safe-action.ts @@ -2,6 +2,7 @@ import { createSafeActionClient } from "next-safe-action"; import { withServerActionInstrumentation } from "@sentry/nextjs"; import { z } from "zod"; import { auth } from "@/utils/auth"; +import { headers } from "next/headers"; import { createScopedLogger } from "@/utils/logger"; import prisma from "@/utils/prisma"; import { isAdmin } from "@/utils/admin"; @@ -46,7 +47,7 @@ const baseClient = createSafeActionClient({ export const actionClient = baseClient .bindArgsSchemas<[emailAccountId: z.ZodString]>([z.string()]) .use(async ({ next, metadata, bindArgsClientInputs }) => { - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); if (!session?.user) throw new SafeError("Unauthorized"); const userEmail = session.user.email; @@ -87,7 +88,7 @@ export const actionClient = baseClient // doesn't bind to a specific email export const actionClientUser = baseClient.use(async ({ next, metadata }) => { - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); if (!session?.user) throw new SafeError("Unauthorized"); @@ -101,7 +102,7 @@ export const actionClientUser = baseClient.use(async ({ next, metadata }) => { }); export const adminActionClient = baseClient.use(async ({ next, metadata }) => { - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); if (!session?.user) throw new SafeError("Unauthorized"); if (!isAdmin({ email: session.user.email })) throw new SafeError("Unauthorized"); diff --git a/apps/web/utils/assess.ts b/apps/web/utils/assess.ts index 357832ed8a..882903a528 100644 --- a/apps/web/utils/assess.ts +++ b/apps/web/utils/assess.ts @@ -128,7 +128,7 @@ async function getForwardingAddressesCount(client: EmailProvider) { async function getEmailClients(client: EmailProvider) { try { - const messages = await client.getSentMessages(50); + const messages = await client.getMessages("from:me", 50); // go through the messages, and check the headers for the email client const clients = messages diff --git a/apps/web/utils/auth-client.ts b/apps/web/utils/auth-client.ts index 7a58e35514..fa3b3f9184 100644 --- a/apps/web/utils/auth-client.ts +++ b/apps/web/utils/auth-client.ts @@ -1,9 +1,11 @@ import { createAuthClient } from "better-auth/react"; import { env } from "@/env"; -export const { signIn, signOut, signUp, useSession, getSession } = createAuthClient({ +export const authClient = createAuthClient({ baseURL: env.NEXT_PUBLIC_BASE_URL, fetchOptions: { credentials: "include", }, }); + +export const { signIn, signOut, signUp, useSession, getSession } = authClient; diff --git a/apps/web/utils/auth.ts b/apps/web/utils/auth.ts index 31403f104b..10f3c0c2cf 100644 --- a/apps/web/utils/auth.ts +++ b/apps/web/utils/auth.ts @@ -1,6 +1,6 @@ // based on: https://github.com/vercel/platforms/blob/main/lib/auth.ts import { betterAuth } from "better-auth"; -import type { Account, User, AuthContext } from "better-auth"; +import type { Account, User } from "better-auth"; import { prismaAdapter } from "better-auth/adapters/prisma"; import { nextCookies } from "better-auth/next-js"; @@ -14,7 +14,7 @@ import { trackDubSignUp } from "@/utils/dub"; import { createScopedLogger } from "@/utils/logger"; import { captureException } from "@/utils/error"; import { encryptToken } from "@/utils/encryption"; -import { cookies, headers } from "next/headers"; +import { cookies } from "next/headers"; import { updateAccountSeats } from "@/utils/premium/server"; import type { Prisma } from "@prisma/client"; import { getContactsClient as getGoogleContactsClient } from "@/utils/gmail/client"; @@ -22,11 +22,25 @@ import { getContactsClient as getOutlookContactsClient } from "@/utils/outlook/c const logger = createScopedLogger("auth"); -export const betterAuthConfig = betterAuth({ +export const auth = betterAuth({ advanced: { database: { generateId: false, }, + crossSubDomainCookies: { + enabled: true, + domain: env.COOKIE_DOMAIN, + }, + cookie: { + sameSite: "none", + secure: true, + domain: env.COOKIE_DOMAIN, + path: "/", + }, + defaultCookieAttributes: { + secure: true, + sameSite: "none", + }, ipAddress: { disableIpTracking: true, }, @@ -119,10 +133,11 @@ export const betterAuthConfig = betterAuth({ scope: [...OUTLOOK_SCOPES], tenantId: "common", prompt: "consent", + requireSelectAccount: true, disableIdTokenSignIn: true, }, }, - events: { + /* events: { signIn: handleSignIn, }, databaseHooks: { @@ -133,11 +148,11 @@ export const betterAuthConfig = betterAuth({ }, }, }, - }, + }, */ onAPIError: { throw: true, - onError: (error: unknown, ctx: AuthContext) => { - logger.error("Auth API encountered an error", { error, ctx }); + onError: (error, ctx) => { + logger.error("Auth error:", { error, ctx }); }, errorURL: "/login/error", }, @@ -333,6 +348,7 @@ async function handleLinkAccount(account: Account) { ); throw new Error("Missing access token during account linking."); } + const profileData = await getProfileData( account.providerId, account.accessToken, @@ -413,7 +429,7 @@ async function handleLinkAccount(account: Account) { } } -// Used by Outlook and Gmail providers +// Function to save refreshed tokens (compatible with existing structure) export async function saveTokens({ tokens, accountRefreshToken, @@ -456,6 +472,3 @@ export async function saveTokens({ updatedAccount: updatedAccount.id, }); } - -export const auth = async () => - betterAuthConfig.api.getSession({ headers: await headers() }); diff --git a/apps/web/utils/email-account.ts b/apps/web/utils/email-account.ts index c2f4194df6..3024b85e92 100644 --- a/apps/web/utils/email-account.ts +++ b/apps/web/utils/email-account.ts @@ -1,5 +1,6 @@ import { notFound } from "next/navigation"; import { auth } from "@/utils/auth"; +import { headers } from "next/headers"; import prisma from "@/utils/prisma"; export async function checkUserOwnsEmailAccount({ @@ -7,7 +8,7 @@ export async function checkUserOwnsEmailAccount({ }: { emailAccountId: string; }) { - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); const userId = session?.user.id; if (!userId) notFound(); diff --git a/apps/web/utils/error.server.ts b/apps/web/utils/error.server.ts index b7aed9a2b4..98c729b84f 100644 --- a/apps/web/utils/error.server.ts +++ b/apps/web/utils/error.server.ts @@ -1,6 +1,7 @@ import { setUser } from "@sentry/nextjs"; import { trackError } from "@/utils/posthog"; import { auth } from "@/utils/auth"; +import { headers } from "next/headers"; import { createScopedLogger } from "@/utils/logger"; const logger = createScopedLogger("error.server"); @@ -11,7 +12,7 @@ export async function logErrorToPosthog( errorType: string, ) { try { - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); if (session?.user.email) { setUser({ email: session.user.email }); await trackError({ email: session.user.email, errorType, type, url }); diff --git a/apps/web/utils/middleware.ts b/apps/web/utils/middleware.ts index 5ef590c123..56b8cfc0a5 100644 --- a/apps/web/utils/middleware.ts +++ b/apps/web/utils/middleware.ts @@ -5,6 +5,7 @@ import { env } from "@/env"; import { logErrorToPosthog } from "@/utils/error.server"; import { createScopedLogger } from "@/utils/logger"; import { auth } from "@/utils/auth"; +import { headers } from "next/headers"; import { getEmailAccount } from "@/utils/redis/account-validation"; import { EMAIL_ACCOUNT_HEADER, @@ -137,7 +138,7 @@ function withMiddleware( async function authMiddleware( req: NextRequest, ): Promise { - const session = await auth(); + const session = await auth.api.getSession({ headers: await headers() }); if (!session?.user) { return NextResponse.json( { error: "Unauthorized", isKnownError: true }, diff --git a/apps/web/utils/user.ts b/apps/web/utils/user.ts index 935c3d24ae..ede371eb97 100644 --- a/apps/web/utils/user.ts +++ b/apps/web/utils/user.ts @@ -1,9 +1,9 @@ "use client"; -import { signOut } from "@/utils/auth-client"; +import { authClient } from "@/utils/auth-client"; export async function logOut(callbackUrl?: string) { - await signOut({ + await authClient.signOut({ fetchOptions: { onSuccess: () => { if (callbackUrl) {