diff --git a/teressa-copeland-homes/middleware.ts b/teressa-copeland-homes/middleware.ts
index 561ec35..c6c296b 100644
--- a/teressa-copeland-homes/middleware.ts
+++ b/teressa-copeland-homes/middleware.ts
@@ -1,25 +1,9 @@
-import { auth } from "@/lib/auth";
-import { NextResponse } from "next/server";
+import NextAuth from "next-auth";
+import { authConfig } from "@/lib/auth.config";
-export default auth((req) => {
- const isLoggedIn = !!req.auth;
- const isAgentRoute = req.nextUrl.pathname.startsWith("/agent");
- const isLoginPage = req.nextUrl.pathname === "/agent/login";
-
- // Protect all /agent/* routes except the login page itself
- if (isAgentRoute && !isLoginPage && !isLoggedIn) {
- return NextResponse.redirect(new URL("/agent/login", req.nextUrl.origin));
- }
-
- // Redirect already-authenticated users away from the login page
- if (isLoginPage && isLoggedIn) {
- return NextResponse.redirect(new URL("/agent/dashboard", req.nextUrl.origin));
- }
-});
+const { auth } = NextAuth(authConfig);
+export default auth;
export const config = {
- matcher: [
- // Run on /agent/* routes, excluding Next.js internals and static files
- "/((?!_next/static|_next/image|favicon.ico).*)",
- ],
+ matcher: ["/agent/:path*"],
};
diff --git a/teressa-copeland-homes/src/app/agent/(protected)/dashboard/page.tsx b/teressa-copeland-homes/src/app/agent/(protected)/dashboard/page.tsx
new file mode 100644
index 0000000..c07d97e
--- /dev/null
+++ b/teressa-copeland-homes/src/app/agent/(protected)/dashboard/page.tsx
@@ -0,0 +1,17 @@
+import { auth } from "@/lib/auth";
+import { redirect } from "next/navigation";
+
+export default async function DashboardPage() {
+ // Defense-in-depth session check (layout also checks, this is belt-and-suspenders)
+ const session = await auth();
+ if (!session) redirect("/agent/login");
+
+ return (
+
+
Dashboard
+
+ Welcome back, {session.user?.email}. Portal content coming in Phase 3.
+
+
+ );
+}
diff --git a/teressa-copeland-homes/src/app/agent/(protected)/layout.tsx b/teressa-copeland-homes/src/app/agent/(protected)/layout.tsx
new file mode 100644
index 0000000..a521b11
--- /dev/null
+++ b/teressa-copeland-homes/src/app/agent/(protected)/layout.tsx
@@ -0,0 +1,26 @@
+import { auth } from "@/lib/auth";
+import { redirect } from "next/navigation";
+import { LogoutButton } from "@/components/ui/LogoutButton";
+
+export default async function AgentLayout({
+ children,
+}: {
+ children: React.ReactNode;
+}) {
+ // Defense-in-depth: middleware handles most cases, this catches edge cases
+ const session = await auth();
+ if (!session) redirect("/agent/login");
+
+ return (
+
+ );
+}
diff --git a/teressa-copeland-homes/src/lib/auth.config.ts b/teressa-copeland-homes/src/lib/auth.config.ts
new file mode 100644
index 0000000..a57632e
--- /dev/null
+++ b/teressa-copeland-homes/src/lib/auth.config.ts
@@ -0,0 +1,44 @@
+import type { NextAuthConfig } from "next-auth";
+
+/**
+ * Edge-compatible auth config — no DB imports.
+ * Used by middleware.ts (Edge Runtime).
+ * Full auth.ts adds the Credentials provider with DB access.
+ */
+export const authConfig = {
+ session: {
+ strategy: "jwt",
+ maxAge: 7 * 24 * 60 * 60,
+ updateAge: 24 * 60 * 60,
+ },
+ pages: {
+ signIn: "/agent/login",
+ },
+ providers: [], // Providers added in auth.ts — not needed for middleware JWT check
+ callbacks: {
+ authorized({ auth, request: { nextUrl } }) {
+ const isLoggedIn = !!auth?.user;
+ const isLoginPage = nextUrl.pathname === "/agent/login";
+ const isAgentRoute = nextUrl.pathname.startsWith("/agent");
+
+ if (isLoginPage) {
+ if (isLoggedIn) return Response.redirect(new URL("/agent/dashboard", nextUrl.origin));
+ return true; // Always allow unauthenticated access to login page
+ }
+
+ if (isAgentRoute) {
+ return isLoggedIn; // Redirect unauthenticated users to login
+ }
+
+ return true;
+ },
+ jwt({ token, user }) {
+ if (user) token.id = user.id;
+ return token;
+ },
+ session({ session, token }) {
+ session.user.id = token.id as string;
+ return session;
+ },
+ },
+} satisfies NextAuthConfig;
diff --git a/teressa-copeland-homes/src/lib/auth.ts b/teressa-copeland-homes/src/lib/auth.ts
index e5288c5..9303b66 100644
--- a/teressa-copeland-homes/src/lib/auth.ts
+++ b/teressa-copeland-homes/src/lib/auth.ts
@@ -5,6 +5,7 @@ import { users } from "@/lib/db/schema";
import { eq } from "drizzle-orm";
import bcrypt from "bcryptjs";
import { z } from "zod";
+import { authConfig } from "./auth.config";
const loginSchema = z.object({
email: z.string().email(),
@@ -12,14 +13,7 @@ const loginSchema = z.object({
});
export const { handlers, auth, signIn, signOut } = NextAuth({
- session: {
- strategy: "jwt",
- maxAge: 7 * 24 * 60 * 60, // 7 days — rolling session per user decision
- updateAge: 24 * 60 * 60, // Refresh cookie once per day (not every request)
- },
- pages: {
- signIn: "/agent/login", // Custom login page — per user decision
- },
+ ...authConfig,
providers: [
Credentials({
async authorize(credentials) {
@@ -44,14 +38,4 @@ export const { handlers, auth, signIn, signOut } = NextAuth({
},
}),
],
- callbacks: {
- jwt({ token, user }) {
- if (user) token.id = user.id;
- return token;
- },
- session({ session, token }) {
- session.user.id = token.id as string;
- return session;
- },
- },
});