Protected Access

Auth

Use Albatroz inside an authenticated application by combining your session provider, route guards, and role-based access rules before users ever reach the recovery flow.

In this section

Follow the same recovery flow across installation, forms, auth, API wiring, and email delivery.

Structure

Keep the existing docs routes, but present them in a cleaner shell that matches the rest of the product UI.

Configure session-aware authentication

A recovery system only feels trustworthy when it is anchored in the same identity model as the rest of the product. NextAuth gives you a clean way to authenticate users, enrich tokens, and keep role information available across the app.

Use a credentials provider when your users already live in MongoDB.
Persist the user id and admin flag inside JWT and session callbacks.
Return a minimal user payload so your UI can make authorization decisions without extra round trips.

NextAuth configuration

import User from '@/models/User';
import db from '@/utils/db';
import NextAuth from 'next-auth';
import CredentialsProvider from 'next-auth/providers/credentials';
import bcrypt from 'bcryptjs';

export default NextAuth({
  session: {
    strategy: 'jwt',
  },
  callbacks: {
    async jwt({ token, user }) {
      if (user?._id) token._id = user._id;
      if (user?.isAdmin) token.isAdmin = user.isAdmin;
      return token;
    },
    async session({ session, token }) {
      if (token?._id) session.user._id = token._id;
      if (token?.isAdmin) session.user.isAdmin = token.isAdmin;
      return session;
    },
  },
  providers: [
    CredentialsProvider({
      async authorize(credentials) {
        await db.connect();
        const user = await User.findOne({ email: credentials?.email });
        await db.disconnect();

        if (user && bcrypt.compareSync(credentials!.password, user.password)) {
          return {
            _id: user._id,
            name: user.name,
            email: user.email,
            isAdmin: user.isAdmin,
          };
        }

        throw new Error('Invalid email or password');
      },
    }),
  ],
});

Protect pages with an auth wrapper

Once the session provider is in place, wrap protected routes with an auth boundary. This keeps your dashboard, admin screens, and settings pages aligned with the same session rules that back your recovery experience.

Custom app wrapper

import { NextComponentType } from 'next';
import { SessionProvider, useSession } from 'next-auth/react';
import type { AppProps } from 'next/app';
import { useRouter } from 'next/router';

type CustomAppProps = AppProps & {
  Component: NextComponentType & { auth?: { adminOnly: boolean } };
};

function Auth({
  children,
  adminOnly,
}: {
  children: React.ReactNode;
  adminOnly: boolean;
}) {
  const router = useRouter();
  const { status, data: session }: any = useSession({
    required: true,
    onUnauthenticated() {
      router.push('/unauthorized?message=login required');
    },
  });

  if (status === 'loading') return <div>Loading...</div>;

  if (adminOnly && !session.user.isAdmin) {
    router.push('/unauthorized?message=admin login required');
  }

  return children;
}

export default function App({
  Component,
  pageProps: { session, ...pageProps },
}: CustomAppProps) {
  return (
    <SessionProvider session={session}>
      {Component.auth ? (
        <Auth adminOnly={Component.auth.adminOnly}>
          <Component {...pageProps} />
        </Auth>
      ) : (
        <Component {...pageProps} />
      )}
    </SessionProvider>
  );
}
Treat recovery screens and authenticated screens as separate concerns: the recovery request can start unauthenticated, but token validation and account updates still need strong server-side checks.

What to validate in production

The auth layer should support the recovery layer, not replace it. Even if a user is logged out, you still need consistent checks around account existence, token ownership, and route access.

Redirect unauthenticated users away from protected routes immediately.
Restrict admin-only pages with explicit role checks.
Mirror these protections on the server so client-side redirects are not your only defense.