Check user authentication status throughout your application.
Throughout your app, you may want to gate certain user experiences based on whether the current user is authenticated or not. MoonKey makes it easy to check your user’s authentication status and handle it appropriately.
Using the React SDK
You can use the useMoonKey hook to determine if your user is authenticated and access their information.
Import
import { useMoonKey } from '@moon-key/react-auth';
Available Properties
The useMoonKey hook provides several properties for managing authentication state:
const {
isAuthenticated, // boolean - true if user is logged in
ready, // boolean - true when SDK has initialized
user, // User object or null
logout, // function to logout user
start // function to start authentication flow
} = useMoonKey();
Indicates whether the current user is authenticated or not.
Indicates whether the MoonKey SDK has finished initializing. Always check this before checking isAuthenticated.
The authenticated user object, or null if no user is logged in.
Function to logout the current user.
Function to initiate the authentication flow.
Before determining a user’s auth status, you should verify that MoonKey has fully initialized and is ready.
Basic Usage
Check if a user is authenticated:
import { useMoonKey } from '@moon-key/react-auth';
export default function MyComponent() {
const { ready, isAuthenticated, user } = useMoonKey();
if (!ready) {
// Show loading state while SDK initializes
return <div>Loading...</div>;
}
if (!isAuthenticated) {
// User is not logged in
return <div>Please log in to continue</div>;
}
// User is authenticated
return <div>Welcome, {user.email}!</div>;
}
Common Patterns
Protected Routes
Redirect unauthenticated users to a login page:
import { useRouter } from 'next/router';
import { useMoonKey } from '@moon-key/react-auth';
import { useEffect } from 'react';
export default function ProtectedPage() {
const { ready, isAuthenticated, user } = useMoonKey();
const router = useRouter();
useEffect(() => {
if (ready && !isAuthenticated) {
// Redirect to login page if not authenticated
router.push('/login');
}
}, [ready, isAuthenticated, router]);
if (!ready) {
// Show loading state while SDK initializes
return <div>Loading...</div>;
}
if (!isAuthenticated) {
// Will redirect, but show loading in the meantime
return <div>Redirecting to login...</div>;
}
// User is authenticated, show protected content
return (
<div>
<h1>Protected Content</h1>
<p>Welcome, {user.email}!</p>
</div>
);
}
Conditional Rendering
Show different UI based on authentication state:
import { useMoonKey } from '@moon-key/react-auth';
export default function HomePage() {
const { ready, isAuthenticated, user, start, logout } = useMoonKey();
if (!ready) {
return <div>Loading...</div>;
}
return (
<div>
<header>
<h1>My App</h1>
{isAuthenticated ? (
<div>
<span>Welcome, {user.email}!</span>
<button onClick={logout}>Logout</button>
</div>
) : (
<button onClick={() => start()}>Login</button>
)}
</header>
<main>
{isAuthenticated ? (
<Dashboard user={user} />
) : (
<LandingPage />
)}
</main>
</div>
);
}
Authentication Wrapper Component
Create a reusable wrapper for protected content:
import { useMoonKey } from '@moon-key/react-auth';
import { ReactNode } from 'react';
interface RequireAuthProps {
children: ReactNode;
fallback?: ReactNode;
}
export function RequireAuth({ children, fallback }: RequireAuthProps) {
const { ready, isAuthenticated, start } = useMoonKey();
if (!ready) {
return <div>Loading...</div>;
}
if (!isAuthenticated) {
return fallback || (
<div>
<p>You must be logged in to view this content.</p>
<button onClick={() => start()}>Login</button>
</div>
);
}
return <>{children}</>;
}
// Usage
export default function ProtectedPage() {
return (
<RequireAuth>
<div>This content is only visible to authenticated users</div>
</RequireAuth>
);
}
Loading States
Handle different loading and authentication states:
import { useMoonKey } from '@moon-key/react-auth';
export default function UserProfile() {
const { ready, isAuthenticated, user } = useMoonKey();
// SDK is still initializing
if (!ready) {
return (
<div className="loading">
<Spinner />
<p>Initializing...</p>
</div>
);
}
// SDK is ready, but user is not authenticated
if (!isAuthenticated) {
return (
<div className="not-authenticated">
<h2>Not Logged In</h2>
<p>Please log in to view your profile.</p>
</div>
);
}
// User is authenticated
return (
<div className="user-profile">
<h2>User Profile</h2>
<div>
<p><strong>Email:</strong> {user.email}</p>
<p><strong>User ID:</strong> {user.id}</p>
<p><strong>Created:</strong> {new Date(user.created_at).toLocaleDateString()}</p>
</div>
</div>
);
}
Once authenticated, you can access detailed user information:
import { useMoonKey } from '@moon-key/react-auth';
export default function UserInfo() {
const { isAuthenticated, user } = useMoonKey();
if (!isAuthenticated || !user) {
return <div>Not logged in</div>;
}
return (
<div>
<h2>User Information</h2>
{/* Basic Info */}
<p>User ID: {user.id}</p>
<p>Email: {user.email}</p>
{/* OAuth Accounts */}
{user.google && (
<div>
<h3>Google Account</h3>
<p>Email: {user.google.email}</p>
<p>Name: {user.google.name}</p>
</div>
)}
{user.apple && (
<div>
<h3>Apple Account</h3>
<p>Email: {user.apple.email}</p>
</div>
)}
{/* Wallet Information */}
{user.wallet && (
<div>
<h3>Wallet</h3>
<p>Address: {user.wallet.address}</p>
<p>Chain: {user.wallet.chainType}</p>
</div>
)}
</div>
);
}
Logout
Log out the current user:
import { useMoonKey } from '@moon-key/react-auth';
export default function LogoutButton() {
const { isAuthenticated, logout } = useMoonKey();
if (!isAuthenticated) {
return null;
}
const handleLogout = async () => {
try {
await logout();
// User is now logged out
// Optionally redirect or show a message
} catch (error) {
console.error('Logout failed:', error);
}
};
return (
<button onClick={handleLogout}>
Logout
</button>
);
}
With Next.js App Router
Handle authentication state in Next.js App Router:
'use client';
import { useMoonKey } from '@moon-key/react-auth';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
export default function DashboardPage() {
const { ready, isAuthenticated, user } = useMoonKey();
const router = useRouter();
useEffect(() => {
if (ready && !isAuthenticated) {
router.push('/login');
}
}, [ready, isAuthenticated, router]);
if (!ready) {
return <div>Loading...</div>;
}
if (!isAuthenticated) {
return <div>Redirecting...</div>;
}
return (
<div>
<h1>Dashboard</h1>
<p>Welcome back, {user.email}!</p>
</div>
);
}
With React Router
Protect routes with React Router:
import { Navigate, Outlet } from 'react-router-dom';
import { useMoonKey } from '@moon-key/react-auth';
export function ProtectedRoute() {
const { ready, isAuthenticated } = useMoonKey();
if (!ready) {
return <div>Loading...</div>;
}
return isAuthenticated ? <Outlet /> : <Navigate to="/login" replace />;
}
// In your router configuration
const router = createBrowserRouter([
{
path: '/',
element: <App />,
children: [
{
path: 'login',
element: <LoginPage />
},
{
element: <ProtectedRoute />,
children: [
{
path: 'dashboard',
element: <DashboardPage />
},
{
path: 'profile',
element: <ProfilePage />
}
]
}
]
}
]);
Server-Side Authentication
For server-side authentication checks, use the REST API to verify sessions:
// app/api/protected/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
const sessionToken = request.cookies.get('session_token')?.value;
if (!sessionToken) {
return NextResponse.json(
{ error: 'Not authenticated' },
{ status: 401 }
);
}
// Verify session with MoonKey API
const response = await fetch('https://api.moonkey.fun/v1/auth/sessions/verify', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.MOONKEY_SECRET_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ session_token: sessionToken })
});
if (!response.ok) {
return NextResponse.json(
{ error: 'Invalid session' },
{ status: 401 }
);
}
const { user } = await response.json();
// Return protected data
return NextResponse.json({
message: 'Protected data',
user
});
}
Best Practices
Always Check Ready State
Always verify the SDK is ready before checking authentication status:
// ❌ Bad - might check auth before SDK is ready
if (isAuthenticated) {
// ...
}
// ✅ Good - wait for SDK to be ready
if (ready && isAuthenticated) {
// ...
}
Handle All States
Consider all possible states in your UI:
export default function MyComponent() {
const { ready, isAuthenticated } = useMoonKey();
// Loading state
if (!ready) {
return <LoadingSpinner />;
}
// Unauthenticated state
if (!isAuthenticated) {
return <LoginPrompt />;
}
// Authenticated state
return <ProtectedContent />;
}
Use useEffect for Side Effects
Use useEffect for redirects and other side effects:
useEffect(() => {
if (ready && !isAuthenticated) {
// Redirect or show modal
router.push('/login');
}
}, [ready, isAuthenticated, router]);
Avoid Unnecessary Re-renders
Destructure only what you need:
// If you only need authentication status
const { ready, isAuthenticated } = useMoonKey();
// If you need user data too
const { ready, isAuthenticated, user } = useMoonKey();
Common Patterns Summary
| Pattern | Use Case | Example |
|---|
| Protected Routes | Require authentication for entire pages | Dashboard, Settings |
| Conditional Rendering | Show different UI for auth states | Login/Logout buttons |
| Auth Wrapper | Reusable protection for components | <RequireAuth> wrapper |
| Loading States | Handle SDK initialization | Loading spinners |
| Server-Side Checks | Verify auth on backend | API routes, SSR |