# nginx auth_request Learning Demo A hands-on demonstration of nginx's `auth_request` module with JWT-based authentication. This project helps you understand how to implement secure authentication and authorization using nginx as a reverse proxy with external authentication services. ## What This Project Demonstrates - **nginx auth_request module**: External authentication for protected resources - **JWT-based security**: Industry-standard token authentication (not forgeable cookies) - **Role-based access control**: Different user roles with different permissions - **Clean URL structure**: Directory-based routing without `.html` extensions - **Custom error pages**: Professional 403/404 pages with no caching - **FastAPI backend**: Modern Python API for authentication logic ## Architecture Overview ``` ┌─────────────┐ auth_request ┌─────────────────┐ │ nginx │ ──────────────────▶│ FastAPI │ │ :8000 │ │ :5115 │ │ │◀──────────────────▶│ │ │ - Routes │ JWT validation │ - Authentication│ │ - Static │ │ - Authorization │ │ - Errors │ │ - User roles │ └─────────────┘ └─────────────────┘ ``` ## Quick Start ### Prerequisites - Docker (for nginx) - Python with uv (for FastAPI) - just (task runner) - curl (for testing) ### 1. Start Services Start the authentication service: ```bash just start-auth ``` Start nginx in a separate terminal: ```bash just start-nginx ``` ### 2. Test Authentication Run the full test suite to see JWT authentication in action: ```bash just test-full-flow ``` ### 3. Manual Testing Visit the application in your browser: - http://localhost:8000/ - Home page (redirects to login if not authenticated) - http://localhost:8000/login/ - Login page - http://localhost:8000/admin/ - Admin-only page ## User Accounts | Username | Password | Role | Access | |----------|----------|---------|-----------------| | admin | admin | admin | All pages | | reader | reader | reader | Home only | ## Available Commands ### Service Management Start the FastAPI authentication service: ```bash just start-auth ``` Stop the authentication service: ```bash just stop-auth ``` Start nginx in Docker: ```bash just start-nginx ``` Stop nginx: ```bash just stop-nginx ``` View nginx logs: ```bash just logs-nginx ``` ### Authentication Testing Login as admin user and save JWT cookie: ```bash just test-login-admin ``` Login as reader user and save JWT cookie: ```bash just test-login-reader ``` Test admin access to protected page: ```bash just test-admin-access ``` Test reader blocked from admin page: ```bash just test-reader-blocked ``` Check current user info (admin): ```bash just test-whoami-admin ``` Check current user info (reader): ```bash just test-whoami-reader ``` Test logout functionality: ```bash just test-logout ``` Run complete authentication test suite: ```bash just test-full-flow ``` Clean up cookie files: ```bash just clean-cookies ``` ## How nginx auth_request Works 1. **User requests protected resource** → nginx receives request 2. **nginx makes auth subrequest** → Internal call to `/authz` endpoint 3. **FastAPI validates JWT token** → Checks cookie and user permissions 4. **Authorization response** → 200 (allow), 401 (login), or 403 (forbidden) 5. **nginx acts on response** → Serves content or shows error page ### Configuration Highlights **nginx.conf key sections:** ```nginx location / { auth_request /authz; # External auth check error_page 401 = @login; # Redirect unauthorized users error_page 403 = @forbidden; # Show 403 page for forbidden } location = /authz { internal; # Only nginx can call this proxy_pass http://127.0.0.1:5115/authz; proxy_set_header X-Original-URI $request_uri; } ``` **FastAPI auth logic:** ```python @app.get("/authz") def authz(request: Request): token = request.cookies.get("access_token") username = verify_jwt_token(token) # Role-based access control if path.startswith("/admin") and user_role != 'admin': return Response("Forbidden", status_code=403) return Response("OK", status_code=200) ``` ## Security Features - **JWT tokens**: Cryptographically signed, cannot be forged - **Token expiration**: 30-minute automatic expiry - **HttpOnly cookies**: Prevent XSS cookie theft - **Role-based access**: Fine-grained permission control - **Cache prevention**: No caching of sensitive pages during demos ## File Structure ``` ├── main_auth.py # FastAPI authentication service ├── nginx.conf # nginx configuration with auth_request ├── justfile # Task automation recipes ├── site/ # Static web content │ ├── index.html # Home page │ ├── admin/index.html # Protected admin page │ ├── login/index.html # Login form │ ├── 403/index.html # Access denied page │ └── 404/index.html # Not found page └── README.md # This documentation ``` ## Learning Exercises ### 1. Basic Flow ```bash # Start services just start-auth just start-nginx # Test unauthenticated access curl -I http://localhost:8000/ # Should redirect to /login/ # Login and get JWT just test-login-admin # Access protected resource just test-admin-access ``` ### 2. Role-Based Access ```bash # Login as different users just test-login-admin just test-login-reader # Compare access levels just test-admin-access # Should succeed just test-reader-blocked # Should fail with 403 ``` ### 3. JWT Security ```bash # View JWT token structure cat admin_cookies.txt # Check user info from token just test-whoami-admin # Try accessing with expired/invalid token # (manually edit cookie file to test) ``` ## Troubleshooting ### Services not starting? ```bash # Check if ports are available lsof -i :5115 # FastAPI lsof -i :8000 # nginx # Check service status docker ps | grep nginx ``` ### Authentication not working? ```bash # Check FastAPI logs just stop-auth ./main_auth.py # Run in foreground to see errors # Check nginx logs just logs-nginx ``` ### Cookie issues? ```bash # Clean up old cookies just clean-cookies # Check cookie contents cat admin_cookies.txt ``` ## Next Steps - Experiment with different user roles - Modify JWT expiration times - Add new protected endpoints - Implement password hashing - Add HTTPS with proper secure cookies - Try different nginx auth_request patterns ## References - [nginx auth_request module](http://nginx.org/en/docs/http/ngx_http_auth_request_module.html) - [FastAPI Security](https://fastapi.tiangolo.com/tutorial/security/) - [JWT.io](https://jwt.io/) - JWT debugger