diff --git a/app/api/auth/[...nextauth]/auth.config.ts b/app/api/auth/[...nextauth]/auth.config.ts
index 06b80ef1a..378fb9d15 100644
--- a/app/api/auth/[...nextauth]/auth.config.ts
+++ b/app/api/auth/[...nextauth]/auth.config.ts
@@ -2,7 +2,6 @@ import type { NextAuthOptions } from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';
import CredentialsProvider from 'next-auth/providers/credentials';
import { AuthService } from '@/services/auth.service';
-import { AuthSharingService } from '@/services/auth-sharing.service';
// Debug flag - set to true to enable detailed authentication logging
const DEBUG_AUTH = true;
@@ -37,7 +36,6 @@ export const authOptions: NextAuthOptions = {
authToken: credentials.authToken,
};
} catch (error) {
- AuthSharingService.removeSharedAuthToken();
return promptInvalidCredentials();
}
}
diff --git a/app/api/auth/logout/route.ts b/app/api/auth/logout/route.ts
index f5e671bba..e8acc3de5 100644
--- a/app/api/auth/logout/route.ts
+++ b/app/api/auth/logout/route.ts
@@ -1,5 +1,4 @@
import { NextResponse } from 'next/server';
-import { AuthSharingService } from '@/services/auth-sharing.service';
/**
* Gets the cookie prefix based on the environment
@@ -14,7 +13,7 @@ function getCookiePrefix(): string {
}
/**
- * Handles the shared logout process by clearing the authentication cookies
+ * Handles the logout process by clearing the NextAuth cookies
* and redirecting to the callback URL or the origin.
*
* @param request - The HTTP request object
@@ -35,7 +34,6 @@ export async function GET(request: Request) {
'Set-Cookie': [
`${prefix}next-auth.session-token=; Expires=${expiredDate}; Path=/; HttpOnly; Secure`,
`${prefix}next-auth.csrf-token=; Expires=${expiredDate}; Path=/; HttpOnly; Secure`,
- `${AuthSharingService.getAuthCookieName()}=; Expires=${expiredDate}; Path=/; Domain=${AuthSharingService.getParentDomain()}; HttpOnly; Secure`,
].join(', '),
},
});
diff --git a/components/AuthSharingWrapper.tsx b/components/AuthSharingWrapper.tsx
deleted file mode 100644
index 065b2f9c0..000000000
--- a/components/AuthSharingWrapper.tsx
+++ /dev/null
@@ -1,88 +0,0 @@
-'use client';
-
-import { Dialog, Transition } from '@headlessui/react';
-import { Fragment } from 'react';
-import { useSession, signIn } from 'next-auth/react';
-import { useEffect, useState } from 'react';
-import { AuthSharingService } from '@/services/auth-sharing.service';
-import { Loader2 } from 'lucide-react';
-
-export function AuthSharingWrapper({ children }: { children: React.ReactNode }) {
- const { data: session, status } = useSession();
- const [isChecking, setIsChecking] = useState(false);
-
- useEffect(() => {
- const checkSharedToken = async () => {
- // Only check if we're not authenticated
- if (status === 'unauthenticated') {
- const sharedToken = AuthSharingService.getSharedAuthToken();
-
- if (sharedToken) {
- setIsChecking(true);
- await signIn('credentials', {
- authToken: sharedToken,
- redirect: false,
- });
- AuthSharingService.removeSharedAuthToken();
- setIsChecking(false);
- }
- }
- };
-
- checkSharedToken();
- }, [status]);
-
- useEffect(() => {
- if (session?.authToken) {
- AuthSharingService.setSharedAuthToken(session.authToken);
- }
- }, [session?.authToken]);
-
- return (
- <>
- {children}
-
-
-
-
- >
- );
-}
diff --git a/components/menus/UserMenu.tsx b/components/menus/UserMenu.tsx
index a417441cd..c7766ce11 100644
--- a/components/menus/UserMenu.tsx
+++ b/components/menus/UserMenu.tsx
@@ -13,7 +13,7 @@ import { VerifiedBadge } from '@/components/ui/VerifiedBadge';
import { SwipeableDrawer } from '@/components/ui/SwipeableDrawer';
import { ResearchCoinIcon } from '@/components/ui/icons/ResearchCoinIcon';
import Link from 'next/link';
-import { AuthSharingService } from '@/services/auth-sharing.service';
+import { signOut } from 'next-auth/react';
import { navigateToAuthorProfile } from '@/utils/navigation';
import { Button } from '@/components/ui/Button';
import { useVerification } from '@/contexts/VerificationContext';
@@ -245,11 +245,11 @@ export default function UserMenu({
AuthSharingService.signOutFromBothApps()}
+ onClick={() => signOut({ callbackUrl: '/' })}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
- AuthSharingService.signOutFromBothApps();
+ signOut({ callbackUrl: '/' });
}
}}
tabIndex={0}
@@ -417,7 +417,7 @@ export default function UserMenu({
)}
AuthSharingService.signOutFromBothApps()}
+ onClick={() => signOut({ callbackUrl: '/' })}
className="w-full px-4 py-2"
>
diff --git a/components/providers/ClientProviders.tsx b/components/providers/ClientProviders.tsx
index 234047c9c..d0b3cd7f6 100644
--- a/components/providers/ClientProviders.tsx
+++ b/components/providers/ClientProviders.tsx
@@ -14,7 +14,6 @@ import { OnchainProvider } from '@/contexts/OnchainContext';
import { FollowProvider } from '@/contexts/FollowContext';
import { ClickProvider } from '@/contexts/ClickContext';
import { NavigationProvider } from '@/contexts/NavigationContext';
-import { AuthSharingWrapper } from '@/components/AuthSharingWrapper';
import { VerificationProvider } from '@/contexts/VerificationContext';
import SignupModalContainer from '@/components/modals/SignupModalContainer';
import { ShareModalProvider } from '@/contexts/ShareContext';
@@ -40,35 +39,33 @@ export function ClientProviders({ children, session }: ClientProvidersProps) {
-
-
-
-
-
-
-
-
-
-
-
-
-
- {children}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+ {children}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/contexts/UserContext.tsx b/contexts/UserContext.tsx
index 7a9c7d8ef..f608d7363 100644
--- a/contexts/UserContext.tsx
+++ b/contexts/UserContext.tsx
@@ -1,10 +1,9 @@
'use client';
import { createContext, useContext, ReactNode, useState, useEffect } from 'react';
-import { useSession } from 'next-auth/react';
+import { useSession, signOut } from 'next-auth/react';
import { AuthError, AuthService } from '@/services/auth.service';
import type { User } from '@/types/user';
-import { AuthSharingService } from '@/services/auth-sharing.service';
import AnalyticsService from '@/services/analytics.service';
import { Experiment } from '@/utils/experiment';
@@ -39,7 +38,8 @@ export function UserProvider({ children }: { children: ReactNode }) {
} catch (err) {
if (err instanceof AuthError) {
if (err.code === 401) {
- await AuthSharingService.signOutFromBothApps();
+ AnalyticsService.clearUserSession();
+ await signOut({ callbackUrl: '/' });
}
}
setError(err instanceof Error ? err : new Error('Failed to load user data'));
diff --git a/services/auth-sharing.service.ts b/services/auth-sharing.service.ts
deleted file mode 100644
index 902372c6c..000000000
--- a/services/auth-sharing.service.ts
+++ /dev/null
@@ -1,97 +0,0 @@
-import Cookies from 'js-cookie';
-import { AUTH_TOKEN } from '@/config/constants';
-import { signOut } from 'next-auth/react';
-import AnalyticsService from './analytics.service';
-
-/**
- * Service to handle authentication sharing between the old and new ResearchHub applications
- */
-export class AuthSharingService {
- private static readonly ENV_PREFIX = (() => {
- switch (process.env.NEXT_PUBLIC_VERCEL_ENV) {
- case 'production':
- return 'prod';
- case 'preview':
- case 'development':
- return 'stg';
- default:
- return 'local';
- }
- })();
-
- private static readonly AUTH_COOKIE_NAME = `${AuthSharingService.ENV_PREFIX}.${AUTH_TOKEN}`;
-
- /**
- * The parent domain that both applications share (for cookie sharing)
- */
- private static readonly PARENT_DOMAIN = (() => {
- switch (process.env.NEXT_PUBLIC_VERCEL_ENV) {
- case 'production':
- return '.researchhub.com';
- case 'preview':
- case 'development':
- return '.staging.researchhub.com';
- default:
- return 'localhost';
- }
- })();
-
- public static getAuthCookieName(): string {
- return this.AUTH_COOKIE_NAME;
- }
-
- public static getParentDomain(): string {
- return this.PARENT_DOMAIN;
- }
-
- /**
- * Sets the authentication token in a shared cookie that can be accessed by both domains
- * @param token The authentication token to store
- * @param expiryDays Number of days until the cookie expires (default: 14)
- */
- static setSharedAuthToken(token: string, expiryDays = 14): void {
- const cookieOptions: Cookies.CookieAttributes = {
- expires: new Date(Date.now() + expiryDays * 24 * 60 * 60 * 1000),
- path: '/',
- domain: this.PARENT_DOMAIN,
- secure: process.env.NEXT_PUBLIC_VERCEL_ENV !== undefined,
- sameSite: 'lax',
- };
-
- Cookies.set(this.AUTH_COOKIE_NAME, token, cookieOptions);
- }
-
- /**
- * Gets the authentication token from the shared cookie
- * @returns The authentication token or null if not found
- */
- static getSharedAuthToken(): string | null {
- const token = Cookies.get(this.AUTH_COOKIE_NAME);
-
- return token || null;
- }
-
- /**
- * Removes the shared authentication token (logout)
- */
- static removeSharedAuthToken(): void {
- Cookies.remove(this.AUTH_COOKIE_NAME, {
- domain: this.PARENT_DOMAIN,
- path: '/',
- });
- }
-
- /**
- * Signs out from both applications by removing the token
- * and calling the signOut method
- */
- static async signOutFromBothApps(): Promise {
- // First remove the shared cookie
- this.removeSharedAuthToken();
- // Reset analytics session
- AnalyticsService.clearUserSession();
-
- // Finally, sign out from NextAuth
- await signOut({ callbackUrl: '/' });
- }
-}