Private Page Access Control Guide

Learn how to implement secure access control and authentication for your SuperFast application's private pages.

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:

  1. User navigates to /dashboard
  2. 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; 
SuperFast - Go From Idea to Revenue in Just Days | Product Hunt