Added comprehensive authentication and authorization system: Authentication System: - Better Auth integration with session management - Login/logout pages and API routes - Middleware for route protection - Auth utilities and client libraries User Management: - User list, detail, and invite pages - User API endpoints (CRUD operations) - Session management for users - Profile settings page Role-Based Access Control: - Role management pages (list, create, edit) - Permission system with granular controls - Role assignment to users - Role API endpoints Admin Features: - Audit log page for tracking system events - Admin settings page - Audit service for logging user actions Additional Features: - Quotes management pages and components - SalesBldr API integration - Email service for notifications Configuration & Documentation: - Updated docker-compose.yml - MCP server configuration (mcp.json) - CVE-2025-55182 security review documentation - Standards guide and PRD documents - Re-enabling authentication documentation Database Migrations: - 012: Auth tables (users, sessions, accounts, verifications) - 013: Role tables (roles, permissions, role_permissions, user_roles) - 014: Admin settings table UI Updates: - Updated dashboard layout - Enhanced app layout with auth integration
242 lines
7.5 KiB
Markdown
242 lines
7.5 KiB
Markdown
# Re-enabling Authentication
|
|
|
|
This document explains how to re-enable Better Auth authentication that was temporarily disabled for private site access.
|
|
|
|
## Overview
|
|
|
|
Authentication was temporarily disabled to allow access to the private site without requiring Microsoft OAuth or magic link email configuration. When the site has public access and authentication providers are properly configured, follow these steps to re-enable authentication.
|
|
|
|
## Prerequisites
|
|
|
|
Before re-enabling authentication, ensure:
|
|
|
|
1. **Microsoft OAuth is configured** (if using Microsoft sign-in):
|
|
- `MICROSOFT_CLIENT_ID` is set in `.env` and `.env.local`
|
|
- `MICROSOFT_CLIENT_SECRET` is set in `.env` and `.env.local`
|
|
- `MICROSOFT_TENANT_ID` is set (or use "common" for multi-tenant)
|
|
- Azure AD app registration is configured with correct redirect URIs
|
|
|
|
2. **SMTP is configured** (if using magic links):
|
|
- `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASSWORD` are set
|
|
- `SMTP_FROM` email address is configured
|
|
- SMTP server allows sending emails
|
|
|
|
3. **Better Auth URLs are correct**:
|
|
- `BETTER_AUTH_URL` matches your production URL (currently `http://localhost:3100`)
|
|
- `NEXT_PUBLIC_BETTER_AUTH_URL` matches your production URL
|
|
- Update these to `https://pulse.wulfconsulting.cloud` for production
|
|
|
|
4. **Database tables exist**:
|
|
- Auth tables should already be created (migration `012_create_auth_tables.sql`)
|
|
- Verify with: `docker exec pulse-postgres psql -U pulse_user -d pulse_autotask -c "\dt" | grep user`
|
|
|
|
## Steps to Re-enable Authentication
|
|
|
|
### 1. Update Middleware
|
|
|
|
Edit `/opt/stacks/pulse/middleware.ts`:
|
|
|
|
**Find this code:**
|
|
```typescript
|
|
export async function middleware(request: NextRequest) {
|
|
const { pathname } = request.nextUrl;
|
|
|
|
// TEMPORARY: Authentication bypassed for private site access
|
|
// TODO: Re-enable authentication when site has public access
|
|
return NextResponse.next();
|
|
|
|
// Allow public routes
|
|
// if (publicRoutes.some((route) => pathname.startsWith(route))) {
|
|
// return NextResponse.next();
|
|
// }
|
|
// ... rest of commented code
|
|
}
|
|
```
|
|
|
|
**Replace with:**
|
|
```typescript
|
|
export async function middleware(request: NextRequest) {
|
|
const { pathname } = request.nextUrl;
|
|
|
|
// Allow public routes
|
|
if (publicRoutes.some((route) => pathname.startsWith(route))) {
|
|
return NextResponse.next();
|
|
}
|
|
|
|
// Allow static files and API routes (except admin API)
|
|
if (
|
|
pathname.startsWith("/_next") ||
|
|
pathname.startsWith("/favicon") ||
|
|
pathname.includes(".")
|
|
) {
|
|
return NextResponse.next();
|
|
}
|
|
|
|
// Check for session cookie
|
|
const sessionCookie = getSessionCookie(request);
|
|
|
|
if (!sessionCookie) {
|
|
// Redirect to sign-in if no session
|
|
const signInUrl = new URL("/auth/sign-in", request.url);
|
|
signInUrl.searchParams.set("callbackUrl", pathname);
|
|
return NextResponse.redirect(signInUrl);
|
|
}
|
|
|
|
// For admin routes, we need to verify the role
|
|
// This is a basic check - the actual role verification happens in the API routes
|
|
if (adminRoutes.some((route) => pathname.startsWith(route))) {
|
|
// The session cookie exists, but we can't decode it here without the secret
|
|
// Role-based access control is enforced at the API level
|
|
// This middleware just ensures there's a session
|
|
return NextResponse.next();
|
|
}
|
|
|
|
return NextResponse.next();
|
|
}
|
|
```
|
|
|
|
### 2. Update Root Layout
|
|
|
|
Edit `/opt/stacks/pulse/app/layout.tsx`:
|
|
|
|
**Find this code:**
|
|
```typescript
|
|
import { Toaster } from "sonner";
|
|
// TEMPORARY: AuthProvider disabled for private site access
|
|
// import { AuthProvider } from "@/components/auth/auth-provider";
|
|
|
|
// ... later in the file ...
|
|
|
|
<ThemeProvider
|
|
attribute="class"
|
|
defaultTheme="system"
|
|
enableSystem
|
|
disableTransitionOnChange
|
|
>
|
|
{/* TEMPORARY: AuthProvider removed - TODO: Re-enable when site has public access */}
|
|
<div className="min-h-screen bg-background">
|
|
<AppNavigation />
|
|
<main>{children}</main>
|
|
</div>
|
|
<Toaster position="top-right" richColors />
|
|
</ThemeProvider>
|
|
```
|
|
|
|
**Replace with:**
|
|
```typescript
|
|
import { Toaster } from "sonner";
|
|
import { AuthProvider } from "@/components/auth/auth-provider";
|
|
|
|
// ... later in the file ...
|
|
|
|
<ThemeProvider
|
|
attribute="class"
|
|
defaultTheme="system"
|
|
enableSystem
|
|
disableTransitionOnChange
|
|
>
|
|
<AuthProvider>
|
|
<div className="min-h-screen bg-background">
|
|
<AppNavigation />
|
|
<main>{children}</main>
|
|
</div>
|
|
</AuthProvider>
|
|
<Toaster position="top-right" richColors />
|
|
</ThemeProvider>
|
|
```
|
|
|
|
### 3. Update Environment Variables (if needed)
|
|
|
|
If deploying to production, update `.env.local`:
|
|
|
|
```bash
|
|
# Update Better Auth URLs for production
|
|
BETTER_AUTH_URL=https://pulse.wulfconsulting.cloud
|
|
NEXT_PUBLIC_BETTER_AUTH_URL=https://pulse.wulfconsulting.cloud
|
|
|
|
# Ensure Microsoft OAuth is configured
|
|
MICROSOFT_CLIENT_ID=your-actual-client-id
|
|
MICROSOFT_CLIENT_SECRET=your-actual-client-secret
|
|
MICROSOFT_TENANT_ID=common
|
|
|
|
# Ensure SMTP is configured for magic links
|
|
SMTP_HOST=smtp.example.com
|
|
SMTP_PORT=587
|
|
SMTP_USER=your-smtp-user
|
|
SMTP_PASSWORD=your-smtp-password
|
|
SMTP_FROM=noreply@wulfconsulting.com
|
|
```
|
|
|
|
### 4. Rebuild and Restart Docker Container
|
|
|
|
```bash
|
|
cd /opt/stacks/pulse
|
|
|
|
# Rebuild the Docker image with authentication enabled
|
|
docker compose build app
|
|
|
|
# Restart the container
|
|
docker compose up -d app
|
|
|
|
# Verify the container is running
|
|
docker logs pulse-app --tail 20
|
|
```
|
|
|
|
### 5. Create Initial Admin User
|
|
|
|
Once authentication is enabled, you'll need to create an initial admin user. You can do this by:
|
|
|
|
1. **Using Microsoft OAuth**: Sign in with a Microsoft account, then manually update the user's role in the database:
|
|
```sql
|
|
UPDATE "user" SET role = 'super-admin' WHERE email = 'your-email@example.com';
|
|
```
|
|
|
|
2. **Using Magic Link**: Send a magic link to your email, sign in, then update the role as above.
|
|
|
|
3. **Direct Database Insert**: Create a user directly in the database (requires password hashing if using email/password).
|
|
|
|
## Verification
|
|
|
|
After re-enabling authentication:
|
|
|
|
1. Navigate to `https://pulse.wulfconsulting.cloud`
|
|
2. You should be redirected to `/auth/sign-in`
|
|
3. Try signing in with Microsoft OAuth or magic link
|
|
4. Verify you can access the dashboard after authentication
|
|
5. Check that unauthenticated users are redirected to sign-in
|
|
|
|
## Troubleshooting
|
|
|
|
### "Invalid Origin" Error
|
|
- Verify `BETTER_AUTH_URL` matches your actual domain
|
|
- Check `trustedOrigins` in `/opt/stacks/pulse/lib/auth.ts` includes your domain
|
|
|
|
### Microsoft OAuth Not Working
|
|
- Verify Azure AD app registration redirect URIs include:
|
|
- `https://pulse.wulfconsulting.cloud/api/auth/callback/microsoft`
|
|
- Check client ID and secret are correct
|
|
- Ensure tenant ID is set correctly
|
|
|
|
### Magic Links Not Sending
|
|
- Verify SMTP configuration is correct
|
|
- Check SMTP server logs for errors
|
|
- Test SMTP connection manually
|
|
|
|
### Database Adapter Errors
|
|
- Ensure auth tables exist: `docker exec pulse-postgres psql -U pulse_user -d pulse_autotask -c "\dt" | grep user`
|
|
- If missing, run migration: `docker exec pulse-postgres psql -U pulse_user -d pulse_autotask -f /docker-entrypoint-initdb.d/012_create_auth_tables.sql`
|
|
|
|
## Rollback
|
|
|
|
If you need to disable authentication again:
|
|
|
|
1. Revert the changes to `middleware.ts` (uncomment the bypass code)
|
|
2. Revert the changes to `app/layout.tsx` (remove AuthProvider)
|
|
3. Rebuild and restart the container
|
|
|
|
## Additional Resources
|
|
|
|
- [Better Auth Documentation](https://www.better-auth.com)
|
|
- [Better Auth PostgreSQL Adapter](https://www.better-auth.com/docs/adapters/postgresql)
|
|
- [Better Auth Microsoft Provider](https://www.better-auth.com/docs/providers/microsoft)
|
|
- [Better Auth Magic Link Plugin](https://www.better-auth.com/docs/plugins/magic-link)
|