Skip to main content
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();
isAuthenticated
boolean
Indicates whether the current user is authenticated or not.
ready
boolean
Indicates whether the MoonKey SDK has finished initializing. Always check this before checking isAuthenticated.
user
User | null
The authenticated user object, or null if no user is logged in.
logout
() => Promise<void>
Function to logout the current user.
start
(params?) => void
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>
  );
}

Accessing User Information

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

PatternUse CaseExample
Protected RoutesRequire authentication for entire pagesDashboard, Settings
Conditional RenderingShow different UI for auth statesLogin/Logout buttons
Auth WrapperReusable protection for components<RequireAuth> wrapper
Loading StatesHandle SDK initializationLoading spinners
Server-Side ChecksVerify auth on backendAPI routes, SSR