- Add OIDC login flow with Authentik provider - Implement session-based auth with Redis store - Add avatar display from OIDC claims - Fix input field performance with react-textarea-autosize - Stabilize callbacks to prevent unnecessary re-renders - Fix history loading to skip empty session files - Add 2-row default height for input textarea 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
767 lines
19 KiB
Markdown
767 lines
19 KiB
Markdown
# OIDC Authentication Implementation Plan for Claude Web UI
|
|
|
|
## Project Overview
|
|
|
|
**Project:** Claude Web UI - Web interface for Claude Code CLI
|
|
**URL:** https://agents.sneakercloud.de
|
|
**Auth Provider:** Authentik (https://auth.sneakercloud.de)
|
|
**Implementation Goal:** Add production-ready OIDC authentication with group-based access control
|
|
|
|
## Current Architecture Analysis
|
|
|
|
### Backend (Node.js/Express)
|
|
- **File:** `backend/server.js` (999 lines)
|
|
- **Framework:** Express with WebSocket (ws library)
|
|
- **Current State:** No authentication
|
|
- **Endpoints:**
|
|
- REST: `/api/hosts`, `/api/projects`, `/api/health`, `/api/browse`, `/api/upload/:sessionId`, `/api/history/:project`
|
|
- WebSocket: Single endpoint on root path
|
|
- **Sessions:** In-memory Map with UUIDs, no user association
|
|
|
|
### Frontend (React/Vite)
|
|
- **Main:** `frontend/src/App.jsx` - Application shell
|
|
- **State:** `frontend/src/contexts/SessionContext.jsx` - Session management via React Context
|
|
- **WebSocket:** Direct connections stored in refs
|
|
- **Storage:** localStorage for session persistence
|
|
- **Current State:** No authentication UI or logic
|
|
|
|
### Key Constraints
|
|
1. Single-file backend (consider modular refactoring)
|
|
2. WebSocket architecture must be preserved
|
|
3. No localStorage for tokens (XSS risk)
|
|
4. Production security requirements
|
|
5. Group-based access control needed
|
|
|
|
---
|
|
|
|
## Phase 1: Authentik Configuration & Backend Foundation
|
|
|
|
### Objectives
|
|
- Configure Authentik OIDC Provider and Application
|
|
- Refactor backend into modular structure
|
|
- Add core authentication dependencies
|
|
- Implement session storage mechanism
|
|
|
|
### Tasks
|
|
|
|
#### 1.1 Authentik Setup
|
|
**Provider Configuration:**
|
|
```yaml
|
|
Name: Claude Web UI
|
|
Client Type: Confidential
|
|
Authorization Flow: Authorization Code
|
|
Redirect URIs:
|
|
- https://agents.sneakercloud.de/auth/callback
|
|
- http://localhost:5173/auth/callback (dev)
|
|
Scopes: openid, profile, email, groups
|
|
```
|
|
|
|
**Application Configuration:**
|
|
```yaml
|
|
Name: Claude Web UI
|
|
Provider: [linked to above]
|
|
Launch URL: https://agents.sneakercloud.de
|
|
```
|
|
|
|
**Group Mappings:**
|
|
- Create groups: `agent-admin`, `agent-users`
|
|
- Configure scope mappings to include groups in ID token
|
|
- Test with user accounts
|
|
|
|
**Deliverables:**
|
|
- Client ID and Client Secret
|
|
- Discovery URL: `https://auth.sneakercloud.de/application/o/claude-web-ui/.well-known/openid-configuration`
|
|
- Documented group structure
|
|
|
|
#### 1.2 Backend Refactoring
|
|
**Current:** Single `backend/server.js` (999 lines)
|
|
|
|
**New Structure:**
|
|
```
|
|
backend/
|
|
├── server.js # Main entry, app initialization
|
|
├── config/
|
|
│ └── auth.js # Auth config from env
|
|
├── middleware/
|
|
│ ├── auth.js # Authentication middleware
|
|
│ └── session.js # Session management
|
|
├── routes/
|
|
│ ├── api.js # Existing API routes
|
|
│ ├── auth.js # OIDC auth routes
|
|
│ └── websocket.js # WebSocket handler
|
|
└── utils/
|
|
└── oidc.js # OIDC client wrapper
|
|
```
|
|
|
|
**Migration Strategy:**
|
|
1. Create new file structure
|
|
2. Extract route handlers into modules
|
|
3. Extract WebSocket logic
|
|
4. Update server.js to import modules
|
|
5. Test that existing functionality works
|
|
|
|
#### 1.3 Dependencies
|
|
**Add to `backend/package.json`:**
|
|
```json
|
|
{
|
|
"express-session": "^1.18.0",
|
|
"connect-redis": "^7.1.0",
|
|
"redis": "^4.6.0",
|
|
"openid-client": "^5.6.0",
|
|
"cookie-parser": "^1.4.6"
|
|
}
|
|
```
|
|
|
|
**Rationale:**
|
|
- `express-session`: Session management
|
|
- `connect-redis`: Session store (persistent, production-ready)
|
|
- `redis`: Session backend
|
|
- `openid-client`: Official OIDC client (certified)
|
|
- `cookie-parser`: Cookie handling
|
|
|
|
#### 1.4 Session Storage
|
|
**Redis Configuration:**
|
|
- Use existing Redis instance or add to docker-compose
|
|
- Configure session store with httpOnly cookies
|
|
- Session TTL: 24 hours (configurable)
|
|
- Secure flag in production
|
|
|
|
**Session Schema:**
|
|
```javascript
|
|
{
|
|
sessionId: "uuid",
|
|
userId: "oidc-sub",
|
|
email: "user@example.com",
|
|
name: "User Name",
|
|
groups: ["agent-users"],
|
|
accessToken: "encrypted",
|
|
refreshToken: "encrypted",
|
|
expiresAt: timestamp,
|
|
createdAt: timestamp
|
|
}
|
|
```
|
|
|
|
### Verification Criteria
|
|
- [ ] Authentik provider and application created
|
|
- [ ] Test user can authenticate via Authentik UI
|
|
- [ ] Backend refactored, all tests pass
|
|
- [ ] Dependencies installed
|
|
- [ ] Redis session store connected
|
|
- [ ] Session CRUD operations working
|
|
|
|
---
|
|
|
|
## Phase 2: OIDC Authentication Flow
|
|
|
|
### Objectives
|
|
- Implement authorization code flow
|
|
- Create auth routes (login, callback, logout)
|
|
- Secure session cookies
|
|
- Handle token refresh
|
|
|
|
### Tasks
|
|
|
|
#### 2.1 OIDC Client Setup
|
|
**File:** `backend/utils/oidc.js`
|
|
|
|
**Functionality:**
|
|
- Discover OIDC configuration from Authentik
|
|
- Initialize Issuer and Client
|
|
- Generate authorization URL
|
|
- Handle token exchange
|
|
- Validate ID tokens
|
|
- Refresh access tokens
|
|
|
|
**Configuration (from env):**
|
|
```bash
|
|
OIDC_ISSUER=https://auth.sneakercloud.de/application/o/claude-web-ui/
|
|
OIDC_CLIENT_ID=<from_authentik>
|
|
OIDC_CLIENT_SECRET=<from_authentik>
|
|
OIDC_REDIRECT_URI=https://agents.sneakercloud.de/auth/callback
|
|
SESSION_SECRET=<generate_with_openssl>
|
|
REDIS_URL=redis://localhost:6379
|
|
```
|
|
|
|
#### 2.2 Authentication Routes
|
|
**File:** `backend/routes/auth.js`
|
|
|
|
**Routes:**
|
|
|
|
**GET `/auth/login`**
|
|
- Generate OIDC authorization URL with PKCE
|
|
- Store state and nonce in session
|
|
- Redirect to Authentik
|
|
|
|
**GET `/auth/callback`**
|
|
- Validate state parameter
|
|
- Exchange authorization code for tokens
|
|
- Validate ID token signature and claims
|
|
- Extract user info and groups
|
|
- Create session with user data
|
|
- Redirect to frontend (`/`)
|
|
|
|
**POST `/auth/logout`**
|
|
- Destroy session
|
|
- Optionally redirect to Authentik logout
|
|
- Clear cookies
|
|
|
|
**GET `/auth/user`**
|
|
- Return current user info from session
|
|
- Return 401 if not authenticated
|
|
|
|
**POST `/auth/refresh`**
|
|
- Use refresh token to get new access token
|
|
- Update session
|
|
- Return success/failure
|
|
|
|
#### 2.3 Session Cookie Configuration
|
|
```javascript
|
|
{
|
|
name: 'claude.sid',
|
|
secret: process.env.SESSION_SECRET,
|
|
resave: false,
|
|
saveUninitialized: false,
|
|
cookie: {
|
|
httpOnly: true, // No JavaScript access
|
|
secure: true, // HTTPS only in production
|
|
sameSite: 'lax', // CSRF protection
|
|
maxAge: 24 * 60 * 60 * 1000 // 24 hours
|
|
},
|
|
store: redisStore // Redis session store
|
|
}
|
|
```
|
|
|
|
#### 2.4 Token Management
|
|
- Store access token in Redis session (encrypted)
|
|
- Store refresh token in Redis session (encrypted)
|
|
- Implement token refresh 5 minutes before expiry
|
|
- Handle refresh failures (force re-login)
|
|
|
|
### Verification Criteria
|
|
- [ ] Login redirects to Authentik
|
|
- [ ] Callback successfully exchanges code for tokens
|
|
- [ ] ID token validated and parsed
|
|
- [ ] Groups extracted from token
|
|
- [ ] Session created in Redis
|
|
- [ ] Cookie set with correct flags
|
|
- [ ] `/auth/user` returns user info
|
|
- [ ] Logout destroys session
|
|
- [ ] Token refresh works
|
|
|
|
---
|
|
|
|
## Phase 3: Backend API Protection
|
|
|
|
### Objectives
|
|
- Protect all API endpoints with authentication
|
|
- Secure WebSocket connections
|
|
- Implement group-based authorization
|
|
- Handle unauthorized access gracefully
|
|
|
|
### Tasks
|
|
|
|
#### 3.1 Authentication Middleware
|
|
**File:** `backend/middleware/auth.js`
|
|
|
|
**Middleware Functions:**
|
|
|
|
**`requireAuth`**
|
|
- Check if session exists and is valid
|
|
- Verify session in Redis
|
|
- Attach `req.user` with user data
|
|
- Return 401 if not authenticated
|
|
|
|
**`requireGroup(groups)`**
|
|
- Check if `req.user.groups` includes required group
|
|
- Return 403 if insufficient permissions
|
|
- Usage: `requireGroup(['agent-admin'])`
|
|
|
|
**`optionalAuth`**
|
|
- Attach user if authenticated
|
|
- Continue if not authenticated
|
|
- For endpoints that support both modes
|
|
|
|
#### 3.2 Protect REST Endpoints
|
|
**Apply Middleware:**
|
|
```javascript
|
|
// All API routes require auth
|
|
app.use('/api', requireAuth);
|
|
|
|
// Admin-only endpoints
|
|
app.get('/api/admin/*', requireGroup(['agent-admin']));
|
|
|
|
// Health check remains public
|
|
app.get('/api/health', (req, res) => ...);
|
|
```
|
|
|
|
**Protected Endpoints:**
|
|
- `/api/hosts` - Read: agent-users, Write: agent-admin
|
|
- `/api/projects` - Read: agent-users
|
|
- `/api/browse` - agent-users
|
|
- `/api/upload/:sessionId` - agent-users
|
|
- `/api/history/:project` - agent-users (own history only)
|
|
|
|
#### 3.3 WebSocket Authentication
|
|
**Challenge:** WebSocket upgrade happens before HTTP middleware
|
|
|
|
**Solution: Cookie-based Auth**
|
|
1. Parse cookies from upgrade request
|
|
2. Load session from Redis
|
|
3. Validate session
|
|
4. Attach user to WebSocket connection
|
|
5. Reject upgrade if not authenticated
|
|
|
|
**Implementation:**
|
|
```javascript
|
|
wss.on('connection', async (ws, req) => {
|
|
// Parse cookies from req.headers.cookie
|
|
// Load session from Redis
|
|
// Validate user
|
|
if (!user) {
|
|
ws.close(1008, 'Unauthorized');
|
|
return;
|
|
}
|
|
|
|
// Attach user to connection
|
|
ws.user = user;
|
|
|
|
// Continue with Claude session logic
|
|
});
|
|
```
|
|
|
|
#### 3.4 Session Association
|
|
**Current:** Sessions stored by UUID, no user association
|
|
|
|
**New:**
|
|
- Associate Claude sessions with authenticated user
|
|
- Store user ID in session metadata
|
|
- Allow users to only access their own sessions
|
|
- Admin users can view all sessions (optional)
|
|
|
|
**Session Schema Update:**
|
|
```javascript
|
|
{
|
|
sessionId: "uuid",
|
|
userId: "oidc-sub", // NEW
|
|
userEmail: "user@example.com", // NEW
|
|
project: "/path/to/project",
|
|
host: "neko",
|
|
// ... existing fields
|
|
}
|
|
```
|
|
|
|
#### 3.5 Error Handling
|
|
- 401 Unauthorized: Not authenticated
|
|
- 403 Forbidden: Insufficient permissions
|
|
- Redirect to `/auth/login` for API calls
|
|
- WebSocket: Close with error code
|
|
- Frontend: Display login prompt
|
|
|
|
### Verification Criteria
|
|
- [ ] Unauthenticated API calls return 401
|
|
- [ ] WebSocket upgrades require valid session
|
|
- [ ] Group-based access control works
|
|
- [ ] Admin users have extended permissions
|
|
- [ ] Sessions isolated by user
|
|
- [ ] Error responses are clear
|
|
|
|
---
|
|
|
|
## Phase 4: Frontend Authentication UI
|
|
|
|
### Objectives
|
|
- Create AuthContext for authentication state
|
|
- Implement login/logout UI
|
|
- Add protected routes
|
|
- Handle authentication errors
|
|
- Integrate with existing SessionContext
|
|
|
|
### Tasks
|
|
|
|
#### 4.1 AuthContext
|
|
**File:** `frontend/src/contexts/AuthContext.jsx`
|
|
|
|
**State:**
|
|
```javascript
|
|
{
|
|
user: null | {
|
|
id: string,
|
|
email: string,
|
|
name: string,
|
|
groups: string[]
|
|
},
|
|
isLoading: boolean,
|
|
error: string | null
|
|
}
|
|
```
|
|
|
|
**Methods:**
|
|
- `login()` - Redirect to `/auth/login`
|
|
- `logout()` - Call `/auth/logout`, clear state
|
|
- `refreshUser()` - Call `/auth/user` to get current user
|
|
- `checkAuth()` - Verify authentication on mount
|
|
|
|
**Auto-refresh:**
|
|
- Poll `/auth/user` every 5 minutes
|
|
- Handle 401 by redirecting to login
|
|
- Update user state on success
|
|
|
|
#### 4.2 Login Flow
|
|
**Current:** App loads directly to ChatPanel
|
|
|
|
**New:**
|
|
1. App mounts
|
|
2. AuthContext checks `/auth/user`
|
|
3. If 401: Show login page
|
|
4. If 200: Show app
|
|
5. User clicks "Login with Authentik"
|
|
6. Redirect to `/auth/login`
|
|
7. Authentik authentication
|
|
8. Callback redirects to `/`
|
|
9. AuthContext refreshes user
|
|
10. App shows
|
|
|
|
#### 4.3 Login Page Component
|
|
**File:** `frontend/src/components/LoginPage.jsx`
|
|
|
|
**UI:**
|
|
- Centered card
|
|
- Claude Web UI branding
|
|
- "Login with Authentik" button
|
|
- Loading state during redirect
|
|
- Error messages
|
|
|
|
**Design:**
|
|
- Match existing dark theme
|
|
- Simple, professional
|
|
- No local credentials (OIDC only)
|
|
|
|
#### 4.4 Protected App Wrapper
|
|
**File:** `frontend/src/App.jsx` (update)
|
|
|
|
**Logic:**
|
|
```javascript
|
|
function App() {
|
|
return (
|
|
<AuthProvider>
|
|
<AuthenticatedApp />
|
|
</AuthProvider>
|
|
);
|
|
}
|
|
|
|
function AuthenticatedApp() {
|
|
const { user, isLoading } = useAuth();
|
|
|
|
if (isLoading) return <LoadingSpinner />;
|
|
if (!user) return <LoginPage />;
|
|
|
|
return (
|
|
<SessionProvider>
|
|
<AppContent />
|
|
</SessionProvider>
|
|
);
|
|
}
|
|
```
|
|
|
|
#### 4.5 User Menu
|
|
**Location:** Header component
|
|
|
|
**Elements:**
|
|
- User name/email display
|
|
- Group badges (admin/user)
|
|
- Logout button
|
|
- Account settings link (optional)
|
|
|
|
**Functionality:**
|
|
- Dropdown menu
|
|
- Logout calls `logout()` method
|
|
- Shows current user info
|
|
|
|
#### 4.6 Session Integration
|
|
**Update:** `frontend/src/contexts/SessionContext.jsx`
|
|
|
|
**Changes:**
|
|
- Include user in WebSocket connection metadata
|
|
- Filter sessions by current user
|
|
- Add user info to session creation
|
|
- Handle 401 errors by triggering AuthContext logout
|
|
|
|
**WebSocket Headers:**
|
|
- Session cookie automatically included
|
|
- Backend validates on upgrade
|
|
|
|
### Verification Criteria
|
|
- [ ] Unauthenticated users see login page
|
|
- [ ] Login redirects to Authentik
|
|
- [ ] Successful login shows app
|
|
- [ ] User info displayed in UI
|
|
- [ ] Logout clears session and returns to login
|
|
- [ ] 401 errors trigger re-authentication
|
|
- [ ] WebSocket connects with auth
|
|
- [ ] Sessions filtered by user
|
|
|
|
---
|
|
|
|
## Phase 5: Production Hardening & Polish
|
|
|
|
### Objectives
|
|
- Implement security best practices
|
|
- Add monitoring and logging
|
|
- Handle edge cases
|
|
- Document configuration
|
|
- Test thoroughly
|
|
|
|
### Tasks
|
|
|
|
#### 5.1 Security Enhancements
|
|
|
|
**CSRF Protection:**
|
|
- Use `sameSite: 'lax'` on cookies
|
|
- Add CSRF tokens for state-changing operations
|
|
- Validate origin headers on WebSocket upgrade
|
|
|
|
**Rate Limiting:**
|
|
- Add `express-rate-limit` to auth endpoints
|
|
- Limit login attempts per IP
|
|
- Limit token refresh attempts
|
|
|
|
**Token Security:**
|
|
- Encrypt tokens at rest in Redis (using `crypto`)
|
|
- Validate token expiry before use
|
|
- Clear tokens on logout
|
|
|
|
**Content Security Policy:**
|
|
- Add CSP headers
|
|
- Allow only Authentik domain for redirects
|
|
- Restrict inline scripts
|
|
|
|
#### 5.2 Logging & Monitoring
|
|
|
|
**Authentication Events:**
|
|
- Log successful logins (user ID, IP, timestamp)
|
|
- Log failed auth attempts
|
|
- Log token refresh failures
|
|
- Log logout events
|
|
|
|
**Metrics:**
|
|
- Active sessions count
|
|
- Authentication failures rate
|
|
- Token refresh rate
|
|
- WebSocket auth failures
|
|
|
|
**Integration:**
|
|
- Use existing Gotify webhook for alerts
|
|
- Log to stdout (Docker logs)
|
|
- Consider structured logging (winston)
|
|
|
|
#### 5.3 Error Handling
|
|
|
|
**Token Expiry:**
|
|
- Detect access token expiry
|
|
- Auto-refresh using refresh token
|
|
- Prompt re-login if refresh fails
|
|
- Show clear error messages
|
|
|
|
**Session Expiry:**
|
|
- Handle expired sessions gracefully
|
|
- Show "Session expired, please login again"
|
|
- Preserve unsaved work if possible
|
|
|
|
**Network Errors:**
|
|
- Retry logic for auth endpoint calls
|
|
- Offline detection
|
|
- Clear error messages
|
|
|
|
**Authentik Downtime:**
|
|
- Cache user info for graceful degradation
|
|
- Allow continued use of valid sessions
|
|
- Queue auth checks
|
|
|
|
#### 5.4 Environment Configuration
|
|
|
|
**Required Env Vars:**
|
|
```bash
|
|
# OIDC
|
|
OIDC_ISSUER=https://auth.sneakercloud.de/application/o/claude-web-ui/
|
|
OIDC_CLIENT_ID=<client_id>
|
|
OIDC_CLIENT_SECRET=<client_secret>
|
|
OIDC_REDIRECT_URI=https://agents.sneakercloud.de/auth/callback
|
|
|
|
# Session
|
|
SESSION_SECRET=<generate_with_openssl_rand_hex_32>
|
|
SESSION_DOMAIN=.sneakercloud.de
|
|
SESSION_SECURE=true
|
|
SESSION_MAX_AGE=86400000 # 24 hours
|
|
|
|
# Redis
|
|
REDIS_URL=redis://localhost:6379
|
|
REDIS_PASSWORD=<optional>
|
|
|
|
# App
|
|
NODE_ENV=production
|
|
FRONTEND_URL=https://agents.sneakercloud.de
|
|
```
|
|
|
|
**docker-compose.yml Updates:**
|
|
```yaml
|
|
services:
|
|
backend:
|
|
environment:
|
|
- OIDC_ISSUER=${OIDC_ISSUER}
|
|
- OIDC_CLIENT_ID=${OIDC_CLIENT_ID}
|
|
- OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET}
|
|
- SESSION_SECRET=${SESSION_SECRET}
|
|
- REDIS_URL=redis://redis:6379
|
|
depends_on:
|
|
- redis
|
|
|
|
redis:
|
|
image: redis:7-alpine
|
|
networks:
|
|
- claude-internal
|
|
volumes:
|
|
- redis-data:/data
|
|
|
|
volumes:
|
|
redis-data:
|
|
```
|
|
|
|
#### 5.5 Documentation
|
|
|
|
**Create Files:**
|
|
- `docs/AUTHENTICATION.md` - Overview of auth system
|
|
- `docs/SETUP.md` - Step-by-step Authentik setup
|
|
- `docs/CONFIGURATION.md` - Environment variables
|
|
- `docs/TROUBLESHOOTING.md` - Common issues
|
|
|
|
**Update README.md:**
|
|
- Add authentication section
|
|
- Document required groups
|
|
- Link to setup docs
|
|
|
|
#### 5.6 Testing
|
|
|
|
**Manual Tests:**
|
|
- [ ] Fresh login flow
|
|
- [ ] Logout and re-login
|
|
- [ ] Session persistence across browser refresh
|
|
- [ ] Token refresh
|
|
- [ ] Expired session handling
|
|
- [ ] WebSocket auth
|
|
- [ ] Group-based access control
|
|
- [ ] Multiple users simultaneously
|
|
- [ ] Admin vs regular user permissions
|
|
|
|
**Edge Cases:**
|
|
- [ ] Authentik downtime during login
|
|
- [ ] Redis downtime (session loss)
|
|
- [ ] Concurrent logins from same user
|
|
- [ ] Token refresh during active WebSocket
|
|
- [ ] Cookie disabled in browser
|
|
- [ ] CORS issues
|
|
|
|
**Security Tests:**
|
|
- [ ] Cannot access API without auth
|
|
- [ ] Cannot access other users' sessions
|
|
- [ ] XSS attacks blocked (httpOnly cookies)
|
|
- [ ] CSRF protection works
|
|
- [ ] Token replay attacks prevented
|
|
|
|
### Verification Criteria
|
|
- [ ] All security enhancements implemented
|
|
- [ ] Logging captures auth events
|
|
- [ ] Error handling covers all cases
|
|
- [ ] Documentation complete
|
|
- [ ] All tests pass
|
|
- [ ] Production deployment successful
|
|
|
|
---
|
|
|
|
## Implementation Timeline
|
|
|
|
**Phase 1:** Authentik Configuration & Backend Foundation
|
|
**Duration:** 2-3 days
|
|
**Blockers:** None
|
|
|
|
**Phase 2:** OIDC Authentication Flow
|
|
**Duration:** 2-3 days
|
|
**Blockers:** Phase 1 complete
|
|
|
|
**Phase 3:** Backend API Protection
|
|
**Duration:** 2-3 days
|
|
**Blockers:** Phase 2 complete
|
|
|
|
**Phase 4:** Frontend Authentication UI
|
|
**Duration:** 3-4 days
|
|
**Blockers:** Phase 3 complete
|
|
|
|
**Phase 5:** Production Hardening & Polish
|
|
**Duration:** 2-3 days
|
|
**Blockers:** Phase 4 complete
|
|
|
|
**Total Estimated Time:** 11-16 days
|
|
|
|
---
|
|
|
|
## Success Metrics
|
|
|
|
1. **Security:**
|
|
- Zero XSS vulnerabilities (httpOnly cookies)
|
|
- Zero unauthorized access incidents
|
|
- All tokens encrypted at rest
|
|
|
|
2. **User Experience:**
|
|
- Seamless login flow (<5 seconds)
|
|
- Clear error messages
|
|
- No unnecessary re-authentication
|
|
|
|
3. **Reliability:**
|
|
- 99.9% authentication availability
|
|
- Session persistence across restarts
|
|
- Graceful degradation on errors
|
|
|
|
4. **Performance:**
|
|
- <100ms auth middleware overhead
|
|
- No impact on WebSocket latency
|
|
- Redis session lookups <10ms
|
|
|
|
---
|
|
|
|
## Rollback Plan
|
|
|
|
**If Critical Issues Arise:**
|
|
|
|
1. **Immediate:** Disable authentication middleware
|
|
2. **Revert:** Return to unauthenticated mode
|
|
3. **Investigate:** Review logs and error reports
|
|
4. **Fix:** Address issues in isolated environment
|
|
5. **Redeploy:** With fixes applied
|
|
|
|
**Feature Flags:**
|
|
- `AUTH_ENABLED=false` to disable auth
|
|
- Keep unauthenticated code path intact during initial rollout
|
|
|
|
---
|
|
|
|
## Future Enhancements
|
|
|
|
**Post-MVP:**
|
|
- Multi-factor authentication (MFA) via Authentik
|
|
- API keys for programmatic access
|
|
- OAuth2 scopes for fine-grained permissions
|
|
- Audit log for all user actions
|
|
- Session management UI (view/revoke sessions)
|
|
- SSO with other services via Authentik
|
|
- User preferences storage
|
|
- Role-based access control (RBAC) expansion
|
|
|
|
---
|
|
|
|
## References
|
|
|
|
- **Authentik Docs:** https://docs.goauthentik.io/
|
|
- **OIDC Spec:** https://openid.net/connect/
|
|
- **openid-client:** https://github.com/panva/node-openid-client
|
|
- **express-session:** https://github.com/expressjs/session
|
|
- **OWASP Auth Cheatsheet:** https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
|