Authentication Methods
ClassQuiz provides three primary authentication methods:- JWT Bearer Tokens - For web and mobile applications
- Session Cookies - For browser-based authentication
- API Keys - For programmatic access and integrations
- OAuth Providers - Google, GitHub, and custom OpenID providers
JWT Token Authentication
Overview
The primary authentication method uses JSON Web Tokens (JWT) with the HS256 algorithm (seeauth.py:29). Tokens can be provided either as Bearer tokens in the Authorization header or as HTTP-only cookies.
Token Configuration
SECRET_KEY from your configuration and expire after 30 minutes by default (see auth.py:30).
JWT tokens are cached in Redis for the duration of their validity to improve performance. The token’s email is stored with an expiry matching the token lifetime (see
authenticate_user.py:42).Providing Authentication
ClassQuiz accepts authentication tokens in two ways:1. Authorization Header
2. HTTP-Only Cookie
Tokens are automatically sent via cookies after login:OAuth2PasswordBearerWithCookie (see auth.py:33-63), which checks both request.state.access_token and the access_token cookie.
Token Endpoints
The OAuth2 token URL is configured at:Login Flow
ClassQuiz implements a sophisticated multi-step login system that supports various authentication factors.Step 1: Start Login
POST/api/v1/login/start
Initiate the login process by providing email or username.
Request:
- PASSWORD - Traditional password authentication
- PASSKEY - WebAuthn/FIDO2 authentication
- TOTP - Time-based one-time password (2FA)
- BACKUP - Backup recovery code
The login session is stored in Redis with a 10-minute expiry (see
login.py:144). If the user doesn’t exist or isn’t verified, a dummy session is created to prevent user enumeration.Step 2: Complete Authentication Step
POST/api/v1/login/step/{step_id}
Complete the authentication step(s). The step_id is either 1 or 2.
Query Parameters:
session_id- The session ID from the start login response
access_token- The JWT bearer token (expires in 1 year)rememberme_token- Session key for automatic re-authentication (expires in 1 year)
Authentication Types
Password Authentication
auth.py:28, auth.py:69-70).
Passkey (WebAuthn) Authentication
login.py:64-99).
TOTP Authentication
login.py:208-210).
Backup Code Authentication
Backup codes are single-use. After successful authentication, a new backup code is generated (see
login.py:198).Multi-Factor Authentication
Users can configurerequire_password to enforce multi-step authentication:
- When
require_password = true, password is required first (step 1), followed by TOTP/Passkey (step 2) - When
require_password = false, any available method can be used in step 1
login.py:119-136 for the step determination logic.
User Session Management
After successful authentication, ClassQuiz creates aUserSession record containing:
Remember Me Functionality
Therememberme_token cookie enables automatic re-authentication:
- When a user’s access token expires, the middleware checks for a valid
rememberme_token - If valid, a new access token is automatically issued
- The session’s
last_seentimestamp is updated
rememberme_middleware (see __init__.py:77).
API Key Authentication
For programmatic access, ClassQuiz supports API keys stored in theApiKey model.
API Key Structure
Using API Keys
API keys are checked using thecheck_api_key function (see auth.py:184-194):
API key authentication bypasses the standard OAuth2 flow. Ensure API keys are stored securely and never committed to version control.
OAuth Providers
ClassQuiz supports authentication via OAuth providers:Supported Providers
- Google OAuth - Configured via
GOOGLE_CLIENT_IDandGOOGLE_CLIENT_SECRET - GitHub OAuth - Configured via
GITHUB_CLIENT_IDandGITHUB_CLIENT_SECRET - Custom OpenID - Configured via
CUSTOM_OPENID_PROVIDERsettings
User Auth Types
Users authenticated via OAuth have theirauth_type set accordingly (see models.py:30-34):
google_uid- Google user identifiergithub_user_id- GitHub user IDpassword = None- OAuth users don’t require passwords
Custom OpenID Provider
Configure a custom OpenID Connect provider:Accessing Current User
ClassQuiz provides several dependency functions to access the authenticated user:get_current_user
Requires valid authentication, raises 401 if invalid:get_current_user_optional
ReturnsNone if not authenticated (see auth.py:157-169):
get_current_moderator
Requires user to be in the moderators list (seeauth.py:131-145):
get_admin_user
Requires user to be the first registered user (admin) (seeauth.py:148-154):
Security Best Practices
Password Security
- Passwords are hashed using Argon2 (see
auth.py:28) - Never send passwords in GET requests
- Always use HTTPS in production
Token Security
- Tokens expire after 30 minutes by default
- Set
SECRET_KEYto a cryptographically secure random value - Rotate
SECRET_KEYperiodically (invalidates all existing tokens)
Session Security
- Session cookies are
HttpOnlyto prevent XSS attacks - Cookies use
SameSite=Laxto mitigate CSRF - Sessions track IP addresses for security monitoring
API Key Security
- Generate API keys with sufficient entropy (48 characters)
- Store API keys securely, never in client-side code
- Implement key rotation for production systems
- Monitor API key usage for suspicious activity
Error Handling
Authentication errors return appropriate HTTP status codes:401 Unauthorized
401 During Login Flow
Authentication errors are intentionally generic to prevent user enumeration attacks. The start login endpoint returns dummy data for non-existent users (see
login.py:113-115).