README
This commit is contained in:
parent
298d3223f0
commit
bd77731487
3 changed files with 297 additions and 5 deletions
296
README.md
Normal file
296
README.md
Normal file
|
|
@ -0,0 +1,296 @@
|
|||
# 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue