Protect routes and require authentication before allowing access to specific pages in your application.
Implementation
import { useMoonKey } from '@moon-key/react-auth';
import { ReactNode } from 'react';
import { Navigate } from 'react-router-dom';
interface ProtectedRouteProps {
children: ReactNode;
}
export function ProtectedRoute({ children }: ProtectedRouteProps) {
const { isAuthenticated, ready } = useMoonKey();
// Wait for MoonKey to initialize
if (!ready) {
return (
<div className="loading-screen">
<div className="spinner" />
<p>Loading...</p>
</div>
);
}
// Redirect to login if not authenticated
if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}
// Render protected content
return <>{children}</>;
}
// Usage in your router:
// <Route path="/dashboard" element={
// <ProtectedRoute>
// <Dashboard />
// </ProtectedRoute>
// } />
Usage examples
React Router v6
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { ProtectedRoute } from './ProtectedRoute';
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/login" element={<LoginPage />} />
<Route path="/signup" element={<SignupPage />} />
{/* Protected routes */}
<Route
path="/dashboard"
element={
<ProtectedRoute>
<Dashboard />
</ProtectedRoute>
}
/>
<Route
path="/profile"
element={
<ProtectedRoute>
<ProfilePage />
</ProtectedRoute>
}
/>
<Route
path="/settings"
element={
<ProtectedRoute>
<SettingsPage />
</ProtectedRoute>
}
/>
</Routes>
</BrowserRouter>
);
}
Next.js App Router
'use client';
import { useMoonKey } from '@moon-key/react-auth';
import { useRouter } from 'next/navigation';
import { useEffect, ReactNode } from 'react';
export function ProtectedRoute({ children }: { children: ReactNode }) {
const { isAuthenticated, ready } = useMoonKey();
const router = useRouter();
useEffect(() => {
if (ready && !isAuthenticated) {
router.push('/login');
}
}, [ready, isAuthenticated, router]);
if (!ready) {
return <div>Loading...</div>;
}
if (!isAuthenticated) {
return null; // Will redirect in useEffect
}
return <>{children}</>;
}
// Usage in app/dashboard/page.tsx:
// export default function DashboardPage() {
// return (
// <ProtectedRoute>
// <Dashboard />
// </ProtectedRoute>
// );
// }
Advanced patterns
With redirect to original destination
import { Navigate, useLocation } from 'react-router-dom';
export function ProtectedRoute({ children }: { children: ReactNode }) {
const { isAuthenticated, ready } = useMoonKey();
const location = useLocation();
if (!ready) {
return <div>Loading...</div>;
}
if (!isAuthenticated) {
// Redirect to login, but save the current location
return <Navigate to="/login" state={{ from: location }} replace />;
}
return <>{children}</>;
}
// In your login component, redirect back after login:
// const location = useLocation();
// const from = location.state?.from?.pathname || '/dashboard';
// navigate(from, { replace: true });
With role-based access
interface ProtectedRouteProps {
children: ReactNode;
requiredRole?: string;
}
export function ProtectedRoute({ children, requiredRole }: ProtectedRouteProps) {
const { user, isAuthenticated, ready } = useMoonKey();
if (!ready) {
return <div>Loading...</div>;
}
if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}
if (requiredRole && user?.role !== requiredRole) {
return <Navigate to="/unauthorized" replace />;
}
return <>{children}</>;
}
// Usage:
// <Route path="/admin" element={
// <ProtectedRoute requiredRole="admin">
// <AdminPanel />
// </ProtectedRoute>
// } />
With wallet requirement
export function WalletProtectedRoute({ children }: { children: ReactNode }) {
const { user, isAuthenticated, ready } = useMoonKey();
if (!ready) {
return <div>Loading...</div>;
}
if (!isAuthenticated) {
return <Navigate to="/login" replace />;
}
if (!user?.wallet) {
return <Navigate to="/create-wallet" replace />;
}
return <>{children}</>;
}
Key concepts
- Authentication check - Verifies user is logged in
- Loading state - Shows loading while SDK initializes
- Automatic redirect - Sends unauthenticated users to login
- Preserve location - Can remember where user tried to go
- Flexible protection - Can add additional requirements (roles, wallets, etc.)
Important notes
Always check the ready state before checking isAuthenticated to avoid redirecting users while MoonKey is still initializing.
Use replace prop in Navigate to prevent users from going back to protected routes using the browser back button.
Next steps