Private Page Access Control Guide
Learn how to implement secure access control and authentication for your SuperFast application's private pages.
About Access Control
Access control ensures that only authenticated users who have paid for your product can access the dashboard and protected features.
MongoDB Access Control
Implement secure access control with MongoDB and NextAuth:
1. How Private Page Access Works
1
User Attempts Access
A user tries to access your premium dashboard at /dashboard
Access Flow:
- User navigates to
/dashboard
- Route protection logic begins execution
2
Authentication Check
NextAuth verifies if the user has a valid session cookie
Session Exists
User is authenticated, proceeding to payment verification
No Session
Redirecting to /auth/signin
3
Payment Verification
MongoDB checks for a completed order with the user's email
Order Found
User has paid, granting access to dashboard
No Order
Redirecting to /pricing
4
Access Granted
User can now access the protected dashboard content
Success
5
Security Benefits
- Prevents unauthorized access to premium features
- Ensures users have paid before accessing content
- Maintains session state across page refreshes
- Provides clear upgrade paths for non-paying users
2. Dashboard Layout Protection
Protect your dashboard routes with authentication and payment verification:
TypeScript
// app/dashboard/layout.tsx import { auth } from '../../../auth' import { redirect } from 'next/navigation'; import dbConnect from '@/lib/mongoose'; import Order from '@/models/order'; export default async function Layout({ children, }: { children: React.ReactNode }) { const session = await auth(); if (!session) { redirect('/auth/signin'); } // Connect to MongoDB await dbConnect(); // Check if user has a completed order const userEmail = session.user?.email; if (!userEmail) { redirect('/auth/signin'); } const order = await Order.findOne({ email: userEmail, status: 'completed' }); // If no completed order found, redirect to pricing page if (!order) { redirect('/pricing'); } return <main className='mx-auto mt-36 max-w-6xl'>{children}</main> }
3. Order Model
Define your MongoDB Order model for payment tracking:
TypeScript
import mongoose from 'mongoose'; // Define the schema for the Order model const orderSchema = new mongoose.Schema( { email: { type: String, required: true, }, planId: { type: String, required: true, }, planName: { type: String, required: true, }, price: { type: Number, required: false, }, stripeSessionId: { type: String, required: true, unique: true, }, stripeCustomerId: { type: String, required: false, default: 'unknown', }, status: { type: String, enum: ['pending', 'completed', 'failed'], default: 'pending', }, paymentType: { type: String, enum: ['payment', 'subscription'], default: 'payment', }, interval: { type: String, enum: ['month', 'year'], required: false, }, paymentDate: { type: Date, default: Date.now, }, subscriptionEndDate: { type: Date, required: false, }, metadata: { type: mongoose.Schema.Types.Mixed, }, }, { timestamps: true, } ); // Create the model if it doesn't exist, otherwise use the existing one const Order = mongoose.models.Order || mongoose.model('Order', orderSchema); export default Order;
Access Control Complete
Your application now has secure access control with MongoDB. The implementation includes:
- Protected dashboard routes
- Payment verification
- Authentication checks
- Secure redirects
- Comprehensive order tracking