Public vs protected endpoints
Public endpoints (no authentication required)
These endpoints are accessible without authentication and are ideal for public-facing applications.
GET /api/cities/all- List all cities (minimal format)GET /api/cities/{cityId}- Get city detailsGET /api/cities/{cityId}/meetings- List meetings for a cityGET /api/cities/{cityId}/meetings/{meetingId}- Get meeting transcriptGET /api/cities/{cityId}/parties- List partiesGET /api/cities/{cityId}/people- List peoplePOST /api/search- Search subjects
Protected endpoints (authentication required)
GET /api/cities?includeUnlisted=true- List cities including unlisted onesPOST /api/cities- Create a new cityPOST /api/cities/{cityId}/meetings- Create a meetingPATCH /api/cities/{cityId}/people/{personId}- Update person- Admin endpoints under
/api/admin/*
Authentication methods
Email-based authentication
OpenCouncil uses magic link authentication via email. Users receive a verification link to sign in without passwords.Receive magic link
Check your email for a message from
[email protected] containing a sign-in linkAuthentication provider
The API uses Resend as the email provider:Session management
Session cookies
Authentication is managed via HTTP-only session cookies:Session structure
Authenticated sessions include:Authorization
User roles
OpenCouncil supports role-based access control:Super admin
Full access to all cities and administrative functions
City admin
Manage specific cities they’re assigned to
Regular user
Access public data and manage personal preferences
Anonymous
Access only public endpoints
Permission checking
API routes use centralized authorization functions fromsrc/lib/auth.ts:
Check user authorization (returns boolean)
Require authorization (throws if unauthorized)
Example: Protected endpoint
Configuration
Environment variables
Authentication requires these environment variables:Generating auth secret
Generate a secure secret forNEXTAUTH_SECRET:
The
NEXTAUTH_SECRET is used to encrypt session tokens and must be kept secure.Database integration
OpenCouncil uses Prisma Adapter for Auth.js to store:- User accounts
- Session data
- Verification tokens
User model
Users are stored in PostgreSQL with these key fields:Development mode
Port-specific sessions
In development, OpenCouncil uses port-specific session cookies to allow multiple instances:Test users
Development environments can use test users with email override:When
DEV_EMAIL_OVERRIDE is set, all test user authentication emails are sent to the override address instead.Security best practices
Use HTTPS in production
Use HTTPS in production
Always use HTTPS to protect session cookies from interception. Set
secure: true in cookie options.Keep secrets secure
Keep secrets secure
Never commit
NEXTAUTH_SECRET or RESEND_API_KEY to version control. Use environment variables.Validate all inputs
Validate all inputs
Use Zod schemas to validate request bodies before processing, even on authenticated endpoints.
Check permissions explicitly
Check permissions explicitly
Always await authorization functions. Never skip permission checks for convenience.
Rotate secrets regularly
Rotate secrets regularly
Update
NEXTAUTH_SECRET and API keys periodically for enhanced security.Error handling
Authentication errors
Handling auth errors
Testing authentication
Manual testing
- Start the development server
- Navigate to
/auth/signin - Enter a test email address
- Check your email inbox for the magic link
- Click the link to authenticate
- Verify session cookie is set in browser DevTools
Integration tests
Use the provided test utilities:Common issues
Session not persisting
Session not persisting
Cause: Missing or incorrect
NEXTAUTH_URL environment variable.Solution: Ensure NEXTAUTH_URL matches your deployment URL exactly, including protocol and port.Magic link expired
Magic link expired
Cause: Verification tokens expire after a set time period.Solution: Request a new magic link. Tokens expire for security reasons.
Unauthorized despite being logged in
Unauthorized despite being logged in
Email not received
Email not received
Cause: Email provider issue or incorrect
RESEND_API_KEY.Solution: Verify API key is valid and check Resend dashboard for delivery logs.Next steps
Explore endpoints
Learn about available API endpoints
View examples
See authentication in action with code examples
User management
Manage users and permissions
API reference
Complete API specification