feat: implement local authentication mode and update related components

This commit is contained in:
Abhimanyu Saharan
2026-02-11 19:10:23 +05:30
parent 0ff645f795
commit 06ff1a9720
23 changed files with 563 additions and 93 deletions

View File

@@ -16,21 +16,33 @@ import {
} from "@clerk/nextjs";
import { isLikelyValidClerkPublishableKey } from "@/auth/clerkKey";
import { getLocalAuthToken, isLocalAuthMode } from "@/auth/localAuth";
function hasLocalAuthToken(): boolean {
return Boolean(getLocalAuthToken());
}
export function isClerkEnabled(): boolean {
// IMPORTANT: keep this in sync with AuthProvider; otherwise components like
// <SignedOut/> may render without a <ClerkProvider/> and crash during prerender.
if (isLocalAuthMode()) return false;
return isLikelyValidClerkPublishableKey(
process.env.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY,
);
}
export function SignedIn(props: { children: ReactNode }) {
if (isLocalAuthMode()) {
return hasLocalAuthToken() ? <>{props.children}</> : null;
}
if (!isClerkEnabled()) return null;
return <ClerkSignedIn>{props.children}</ClerkSignedIn>;
}
export function SignedOut(props: { children: ReactNode }) {
if (isLocalAuthMode()) {
return hasLocalAuthToken() ? null : <>{props.children}</>;
}
if (!isClerkEnabled()) return <>{props.children}</>;
return <ClerkSignedOut>{props.children}</ClerkSignedOut>;
}
@@ -49,6 +61,13 @@ export function SignOutButton(
}
export function useUser() {
if (isLocalAuthMode()) {
return {
isLoaded: true,
isSignedIn: hasLocalAuthToken(),
user: null,
} as const;
}
if (!isClerkEnabled()) {
return { isLoaded: true, isSignedIn: false, user: null } as const;
}
@@ -56,6 +75,16 @@ export function useUser() {
}
export function useAuth() {
if (isLocalAuthMode()) {
const token = getLocalAuthToken();
return {
isLoaded: true,
isSignedIn: Boolean(token),
userId: token ? "local-user" : null,
sessionId: token ? "local-session" : null,
getToken: async () => token,
} as const;
}
if (!isClerkEnabled()) {
return {
isLoaded: true,

View File

@@ -0,0 +1,43 @@
"use client";
let localToken: string | null = null;
const STORAGE_KEY = "mc_local_auth_token";
export function isLocalAuthMode(): boolean {
return process.env.NEXT_PUBLIC_AUTH_MODE === "local";
}
export function setLocalAuthToken(token: string): void {
localToken = token;
if (typeof window === "undefined") return;
try {
window.sessionStorage.setItem(STORAGE_KEY, token);
} catch {
// Ignore storage failures (private mode / policy).
}
}
export function getLocalAuthToken(): string | null {
if (localToken) return localToken;
if (typeof window === "undefined") return null;
try {
const stored = window.sessionStorage.getItem(STORAGE_KEY);
if (stored) {
localToken = stored;
return stored;
}
} catch {
// Ignore storage failures (private mode / policy).
}
return null;
}
export function clearLocalAuthToken(): void {
localToken = null;
if (typeof window === "undefined") return;
try {
window.sessionStorage.removeItem(STORAGE_KEY);
} catch {
// Ignore storage failures (private mode / policy).
}
}