Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions api/internal/auth/handlers.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,103 @@
// Package auth provides authentication and authorization mechanisms for StreamSpace.
// This file implements HTTP handlers for authentication endpoints including local,
// SAML, and password management operations.
//
// AUTHENTICATION HANDLERS:
// - Local authentication (username/password)
// - SAML SSO authentication (enterprise identity providers)
// - Token refresh (JWT token renewal)
// - Password change (local users only)
// - Logout (session termination)
//
// SUPPORTED AUTHENTICATION FLOWS:
//
// 1. Local Authentication (POST /auth/login):
// - User submits username and password
// - System verifies credentials against database
// - Returns JWT token for subsequent requests
// - Supports account status validation (active/disabled)
//
// 2. SAML SSO Authentication (GET /auth/saml/login):
// - User initiates SSO flow
// - Redirects to enterprise IdP (Okta, Azure AD, etc.)
// - IdP sends SAML assertion after authentication
// - System validates assertion and creates local session
// - Returns JWT token for API access
//
// 3. Token Refresh (POST /auth/refresh):
// - Client submits existing JWT token
// - System validates token is within refresh window
// - Issues new token with extended expiration
// - Prevents indefinite token refresh (7-day window)
//
// 4. Password Change (POST /auth/password):
// - Local users can change their password
// - Requires current password verification
// - Not available for SSO users (SAML/OIDC)
//
// SECURITY FEATURES:
//
// - Password verification with bcrypt hashing
// - Account status validation (prevent disabled accounts from logging in)
// - JWT token generation with configurable expiration
// - SAML group synchronization for role-based access control
// - Secure cookie handling for SAML return URLs
// - Auto-provisioning of SSO users on first login
//
// SAML GROUP SYNCHRONIZATION:
//
// When users authenticate via SAML, their group memberships are automatically
// synchronized with StreamSpace groups:
// - SAML assertion contains groups claim from IdP
// - System matches SAML group names to local groups
// - Adds user to matching groups (does not remove from other groups by default)
// - Enables role-based access control based on IdP group membership
//
// SECURITY CONSIDERATIONS:
//
// 1. Password Security:
// - Passwords hashed with bcrypt (cost factor 10+)
// - Never return password hashes in API responses
// - Minimum password length enforced (8 characters)
//
// 2. Account Lockout:
// - Disabled accounts cannot authenticate
// - Returns 403 Forbidden for disabled accounts
// - Prevents unauthorized access to suspended accounts
//
// 3. Token Security:
// - JWT tokens include user ID, role, and groups
// - Tokens expire after configured duration (default: 24 hours)
// - Refresh tokens only valid within 7-day window
// - See jwt.go for detailed token security
//
// 4. SAML Security:
// - Assertion signatures validated by middleware
// - Return URLs stored in secure cookies
// - SAML groups synced on every login
// - See saml.go for detailed SAML security
//
// EXAMPLE USAGE:
//
// // Initialize handler with dependencies
// handler := NewAuthHandler(userDB, jwtManager, samlAuth)
//
// // Register routes
// router := gin.Default()
// handler.RegisterRoutes(router.Group("/api/v1"))
//
// // Routes will be available at:
// // - POST /api/v1/auth/login (local authentication)
// // - POST /api/v1/auth/refresh (token refresh)
// // - POST /api/v1/auth/logout (logout)
// // - GET /api/v1/auth/saml/login (initiate SAML SSO)
// // - POST /api/v1/auth/saml/acs (SAML callback)
// // - GET /api/v1/auth/saml/metadata (SAML SP metadata)
//
// THREAD SAFETY:
//
// All handler methods are thread-safe and can handle concurrent requests.
// Database operations use connection pooling for safe concurrent access.
package auth

import (
Expand Down
132 changes: 132 additions & 0 deletions api/internal/auth/middleware.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,135 @@
// Package auth provides authentication and authorization mechanisms for StreamSpace.
// This file implements Gin middleware for JWT token validation and role-based access control.
//
// MIDDLEWARE COMPONENTS:
// - JWT authentication middleware (required authentication)
// - Optional authentication middleware (authentication not required)
// - Role-based authorization middleware (require specific roles)
// - Helper functions for extracting user context
//
// AUTHENTICATION FLOW:
//
// 1. Client Request:
// - Client includes JWT token in Authorization header
// - Format: "Authorization: Bearer <token>"
// - Example: "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
//
// 2. Token Extraction:
// - Middleware extracts token from Authorization header
// - Validates header format (must start with "Bearer ")
// - Rejects requests with missing or malformed headers
//
// 3. Token Validation:
// - Validates JWT signature using secret key
// - Checks token expiration (exp claim)
// - Verifies token issuer (iss claim)
// - Ensures algorithm is HMAC (prevents algorithm substitution)
//
// 4. User Validation:
// - Extracts user ID from validated token claims
// - Queries database to verify user still exists
// - Checks if user account is active (not disabled)
// - Rejects requests from disabled or deleted users
//
// 5. Context Population:
// - Stores user information in Gin context
// - Available to downstream handlers via c.Get()
// - Includes: userID, username, email, role, groups
//
// MIDDLEWARE TYPES:
//
// 1. Middleware (Required Authentication):
// - Rejects requests without valid JWT token
// - Returns 401 Unauthorized for invalid/missing tokens
// - Returns 403 Forbidden for disabled accounts
// - Use for protected API endpoints
//
// 2. OptionalAuth (Optional Authentication):
// - Accepts requests with or without token
// - Validates token if present, ignores if absent
// - Useful for endpoints that behave differently for authenticated users
// - Example: Public catalog with favorites for logged-in users
//
// 3. RequireRole (Role-Based Authorization):
// - Requires specific role (admin, operator, user)
// - Must be used after Middleware (requires authentication)
// - Returns 403 Forbidden if user lacks required role
//
// 4. RequireAnyRole (Multi-Role Authorization):
// - Accepts any of multiple roles
// - Example: RequireAnyRole("admin", "operator") for management endpoints
// - Returns 403 if user has none of the allowed roles
//
// SECURITY FEATURES:
//
// - Token signature validation prevents tampering
// - Expiration checking limits token lifetime
// - Active user validation prevents disabled account access
// - Role checking enforces principle of least privilege
// - Context isolation prevents request cross-contamination
//
// SECURITY CONSIDERATIONS:
//
// 1. Token Transmission:
// - Tokens must be sent over HTTPS in production
// - Never log or expose tokens in error messages
// - Clear tokens from memory after use
//
// 2. Account Status:
// - Always check user.Active before allowing access
// - Disabled accounts cannot authenticate even with valid token
// - Supports immediate access revocation
//
// 3. Token Expiration:
// - Tokens expire after configured duration (default: 24 hours)
// - Expired tokens rejected with 401 Unauthorized
// - Forces periodic re-authentication
//
// 4. Role Validation:
// - Roles stored in JWT claims (tamper-proof via signature)
// - Role hierarchy: admin > operator > user
// - Always validate role before privileged operations
//
// EXAMPLE USAGE:
//
// // Require authentication for all /api routes
// api := router.Group("/api")
// api.Use(auth.Middleware(jwtManager, userDB))
// {
// api.GET("/sessions", listSessions) // Requires valid token
// }
//
// // Admin-only endpoints
// admin := api.Group("/admin")
// admin.Use(auth.RequireRole("admin"))
// {
// admin.GET("/users", listAllUsers) // Requires admin role
// }
//
// // Optional authentication (public + user features)
// router.GET("/catalog", auth.OptionalAuth(jwtManager, userDB), showCatalog)
//
// // Extract user info in handler
// func listSessions(c *gin.Context) {
// userID, _ := auth.GetUserID(c)
// role, _ := auth.GetUserRole(c)
// // ... use user info
// }
//
// CONTEXT KEYS:
//
// The middleware stores the following keys in Gin context:
// - "userID": string - Unique user identifier
// - "username": string - Username for display
// - "userEmail": string - User's email address
// - "userRole": string - Role (admin, operator, user)
// - "userGroups": []string - Group memberships
// - "claims": *Claims - Full JWT claims object
//
// THREAD SAFETY:
//
// All middleware functions are thread-safe and can handle concurrent requests.
// Each request gets its own Gin context, preventing data leakage between requests.
package auth

import (
Expand Down
Loading
Loading