Files
thrillwiki_django_no_react/docs/architecture/adr-005-authentication-approach.md
pacnpal edcd8f2076 Add secret management guide, client-side performance monitoring, and search accessibility enhancements
- Introduced a comprehensive Secret Management Guide detailing best practices, secret classification, development setup, production management, rotation procedures, and emergency protocols.
- Implemented a client-side performance monitoring script to track various metrics including page load performance, paint metrics, layout shifts, and memory usage.
- Enhanced search accessibility with keyboard navigation support for search results, ensuring compliance with WCAG standards and improving user experience.
2025-12-23 16:41:42 -05:00

217 lines
6.5 KiB
Markdown

# ADR-005: Authentication Approach
## Status
Accepted
## Context
ThrillWiki needs to authenticate users for:
- Web browsing (session-based)
- API access (token-based)
- Social login (Google, Discord)
We needed an authentication approach that would:
- Support multiple authentication methods
- Provide secure token handling for API
- Enable social authentication
- Work seamlessly with Django + HTMX architecture
## Decision
We implemented a **Hybrid Authentication System** using django-allauth for social auth and djangorestframework-simplejwt for API tokens.
### Authentication Methods
| Context | Method | Library |
|---------|--------|---------|
| Web browsing | Session-based | Django sessions |
| API access | JWT tokens | djangorestframework-simplejwt |
| Social login | OAuth2 | django-allauth |
| Password reset | Email tokens | Django built-in |
### Architecture
```
┌─────────────────────────────────────────────────────────┐
│ User Request │
└─────────────────────────────────────────────────────────┘
┌───────────────┼───────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Web Request │ │ API Request │ │ Social Auth │
│ │ │ │ │ │
│ Session Cookie │ │ Bearer Token │ │ OAuth Flow │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│ │ │
└───────────────┼───────────────┘
┌─────────────────────┐
│ Django User │
│ (Authenticated) │
└─────────────────────┘
```
### JWT Token Configuration
```python
# backend/config/settings/rest_framework.py
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME': timedelta(minutes=15),
'REFRESH_TOKEN_LIFETIME': timedelta(days=7),
'ROTATE_REFRESH_TOKENS': True,
'BLACKLIST_AFTER_ROTATION': True,
'ALGORITHM': 'HS256',
'SIGNING_KEY': SECRET_KEY,
'AUTH_HEADER_TYPES': ('Bearer',),
}
```
### Social Authentication
```python
# backend/config/settings/third_party.py
SOCIALACCOUNT_PROVIDERS = {
'google': {
'SCOPE': ['profile', 'email'],
'AUTH_PARAMS': {'access_type': 'online'},
},
'discord': {
'SCOPE': ['identify', 'email'],
},
}
```
## Consequences
### Benefits
1. **Flexibility**: Multiple auth methods for different use cases
2. **Security**: JWT with short-lived access tokens
3. **User Experience**: Social login reduces friction
4. **Standards-Based**: OAuth2 and JWT are industry standards
5. **Django Integration**: Seamless with Django's user model
### Trade-offs
1. **Complexity**: Multiple auth systems to maintain
2. **Token Management**: Must handle token refresh client-side
3. **Social Provider Dependency**: Reliance on third-party OAuth providers
### Authentication Flow
#### Web Session Authentication
```
1. User visits /login/
2. User submits credentials
3. Django validates credentials
4. Session created, cookie set
5. Subsequent requests include session cookie
```
#### API JWT Authentication
```
1. Client POST /api/v1/auth/login/
{username, password}
2. Server validates, returns tokens
{access: "...", refresh: "..."}
3. Client includes in requests:
Authorization: Bearer <access_token>
4. On 401, client refreshes:
POST /api/v1/auth/token/refresh/
{refresh: "..."}
```
#### Social Authentication
```
1. User clicks "Login with Google"
2. Redirect to Google OAuth
3. User authorizes application
4. Google redirects with auth code
5. Server exchanges code for tokens
6. Server creates/updates user
7. Session created
```
## Alternatives Considered
### Session-Only Authentication
**Rejected because:**
- Not suitable for mobile apps
- Not RESTful for API access
- CSRF complexity for API clients
### JWT-Only Authentication
**Rejected because:**
- More complex for web browsing
- Token storage in browser has security concerns
- Session logout not immediate
### OAuth2 Server (Self-Hosted)
**Rejected because:**
- Significant complexity for current needs
- django-oauth-toolkit overkill
- django-allauth sufficient for social auth
## Implementation Details
### Permission Classes
```python
# API views use JWT or session authentication
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework_simplejwt.authentication.JWTAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticatedOrReadOnly',
],
}
```
### Custom User Model
```python
# backend/apps/accounts/models.py
class User(AbstractUser):
email = models.EmailField(unique=True)
display_name = models.CharField(max_length=50, blank=True)
avatar_url = models.URLField(blank=True)
email_verified = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username']
```
### Email Verification
```python
# Required before full access
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_AUTHENTICATION_METHOD = 'email'
```
### Security Measures
1. **Password Hashing**: Django's PBKDF2 with SHA256
2. **Token Blacklisting**: Invalidated refresh tokens stored
3. **Rate Limiting**: Login attempts limited
4. **HTTPS Required**: Tokens only sent over secure connections
## References
- [django-allauth Documentation](https://django-allauth.readthedocs.io/)
- [djangorestframework-simplejwt](https://django-rest-framework-simplejwt.readthedocs.io/)
- [OAuth 2.0 Specification](https://oauth.net/2/)
- [JWT Best Practices](https://auth0.com/blog/jwt-security-best-practices/)