feat(auth): implement web authentication with Keycloak OAuth2

- Add auth routes: /auth/login, /auth/callback, /auth/logout
- Add OAuth2 flow with Keycloak using HTTP-only cookies
- Add web auth dependencies with role checking
- Add profile page (read-only) at /web/profile
- Update header with user menu (sign in/out, profile)
- Filter posts based on user permissions (hide drafts from guests)
- Conditionally show/hide create/edit/delete buttons
- Add authorization rules documentation to AGENTS.md
- Secure post editing/deletion endpoints with auth checks
- Add can_edit, can_delete flags to templates
This commit is contained in:
2026-05-02 15:39:49 +03:00
parent 2aed9f5c8a
commit 0cb706e54b
10 changed files with 915 additions and 26 deletions

View File

@@ -234,6 +234,53 @@ Use the following sections as appropriate:
- Location: `static/` directory at project root
- Served via FastAPI `StaticFiles` middleware
## Authentication & Authorization
### Web UI Authentication
- **Token storage**: HTTP-only secure cookies
- **Login flow**: Redirect to Keycloak login page → Callback → Set cookie → Redirect back
- **Registration**: Only through Keycloak admin interface
- **Profile**: Read-only display of user info
### Authorization Rules
#### Post Visibility
| Role | Published Posts | Own Drafts | Other Drafts |
|------|----------------|------------|--------------|
| GUEST (unauthenticated) | ✅ | ❌ | ❌ |
| USER | ✅ | ✅ | ❌ |
| ADMIN | ✅ | ✅ | ✅ |
#### UI Elements by Role
| Element | GUEST | USER | ADMIN |
|---------|-------|------|-------|
| "New Post" button | ❌ | ✅ | ✅ |
| "Edit" button on own posts | ❌ | ✅ | ✅ |
| "Edit" button on other posts | ❌ | ❌ | ✅ |
| "Delete" button on own posts | ❌ | ✅ | ✅ |
| "Delete" button on other posts | ❌ | ❌ | ✅ |
| Draft badges | ❌ | Own only | All |
| User menu in header | ❌ | ✅ | ✅ |
| Profile page access | ❌ | ✅ | ✅ |
### Auth Routes
- `GET /auth/login` - Redirect to Keycloak
- `GET /auth/callback` - OAuth callback handler
- `GET /auth/logout` - Clear cookie and logout
- `GET /profile` - User profile page (read-only)
### Cookie Settings
```python
response.set_cookie(
key="access_token",
value=token,
httponly=True,
secure=True, # In production
samesite="lax",
max_age=3600, # 1 hour
)
```
### DDD Concepts Used
### Entities