Server Errors - FeitianTech/postquantum-webauthn-platform GitHub Wiki
Server Errors
Table of Contents
- Introduction
- Error Handling Architecture
- HTTP Status Codes
- Flask Abort Usage
- Error Response Structure
- Route-Level Error Handling
- Validation Error Patterns
- Server Configuration Issues
- JSON Payload Validation
- Error Response Examples
- Troubleshooting Guide
Introduction
The Post-Quantum WebAuthn Platform implements comprehensive server-side error handling using Flask's built-in mechanisms and custom error response patterns. The platform follows RESTful API conventions for error reporting, utilizing standard HTTP status codes and structured JSON error responses to communicate various failure scenarios to clients.
The error handling system encompasses multiple layers including route-level validation, middleware processing, storage operations, and cross-cutting concerns like authentication and authorization. All error responses maintain consistent formatting and provide meaningful diagnostic information while preserving security best practices.
Error Handling Architecture
The platform employs a layered error handling approach that integrates Flask's native capabilities with custom error processing logic:
flowchart TD
A["Client Request"] --> B["Flask Route Handler"]
B --> C{"Validation Checks"}
C --> |Pass| D["Business Logic"]
C --> |Fail| E["Validation Error"]
D --> F{"Storage Operations"}
F --> |Success| G["Success Response"]
F --> |Failure| H["Storage Error"]
E --> I["Error Response Generation"]
H --> I
I --> J["JSON Error Payload"]
J --> K["HTTP Status Code"]
K --> L["Client Response"]
M["Global Error Handler"] --> I
N["Logging System"] --> I
Diagram sources
Section sources
HTTP Status Codes
The platform consistently uses standard HTTP status codes to indicate different types of errors and responses:
| Status Code | Category | Description | Usage Context |
|---|---|---|---|
| 200 | Success | Request completed successfully | Successful API operations |
| 201 | Success | Resource created successfully | Registration operations |
| 400 | Client Error | Bad request - invalid input | Malformed JSON, missing fields |
| 401 | Client Error | Unauthorized - authentication failed | Missing or invalid credentials |
| 404 | Client Error | Not found - resource unavailable | Non-existent resources |
| 422 | Client Error | Unprocessable entity | Validation failures |
| 500 | Server Error | Internal server error | Unexpected server failures |
Status Code Distribution by Route Type
pie title HTTP Status Code Distribution
"400 Bad Request" : 25
"404 Not Found" : 15
"422 Unprocessable Entity" : 10
"500 Internal Error" : 5
"200 OK" : 45
Section sources
Flask Abort Usage
The platform extensively uses Flask's abort() function for immediate error responses with appropriate HTTP status codes:
Basic Abort Patterns
# Simple abort with status code
abort(400) # Bad request
# Abort with custom message (handled by Flask's error handlers)
abort(404, description="Resource not found")
Route-Level Abort Usage
The platform implements abort patterns in various scenarios:
- Missing required parameters: Routes that require specific query parameters or headers
- Invalid authentication state: Sessions or tokens that are missing or expired
- Resource not found: Attempts to access non-existent resources
- Validation failures: Input data that doesn't meet business requirements
Section sources
Error Response Structure
All error responses follow a consistent JSON structure that includes error information and contextual details:
Standard Error Response Format
{
"error": "Descriptive error message",
"details": "Additional context information (optional)",
"code": "Error classification code (optional)",
"timestamp": "ISO timestamp of error occurrence"
}
Advanced Error Response with Context
For complex operations, error responses may include additional context:
{
"error": "Invalid challenge format",
"details": "Challenge must be valid base64 or hexadecimal",
"field": "challenge",
"received": "invalid_input_value",
"expected": "base64 or hex string",
"timestamp": "2024-01-15T10:30:00Z"
}
Error Response Variations by Status Code
400 Bad Request Responses
{
"error": "Missing required field: rp",
"field": "rp",
"code": "VALIDATION_ERROR",
"timestamp": "2024-01-15T10:30:00Z"
}
404 Not Found Responses
{
"error": "Verified metadata snapshot is not available.",
"path": "/api/mds/metadata/base",
"code": "RESOURCE_NOT_FOUND",
"timestamp": "2024-01-15T10:30:00Z"
}
500 Internal Server Error Responses
{
"error": "Unable to decode payload.",
"details": "Failed during binary data processing",
"operation": "decode_payload_text",
"code": "INTERNAL_ERROR",
"timestamp": "2024-01-15T10:30:00Z"
}
Section sources
Route-Level Error Handling
Each route implements specific error handling patterns tailored to its operational requirements:
General Routes Error Handling
General routes handle metadata operations with comprehensive error coverage:
sequenceDiagram
participant Client
participant Route as "General Route"
participant Validator as "Input Validator"
participant Storage as "Storage Layer"
participant Logger as "Logger"
Client->>Route : POST /api/mds/metadata/upload
Route->>Validator : Validate JSON payload
alt Invalid JSON
Validator-->>Route : ValidationError(400)
Route->>Logger : Log validation error
Route-->>Client : 400 Bad Request
else Valid JSON
Route->>Storage : Process metadata
alt Storage Error
Storage-->>Route : RuntimeError(500)
Route->>Logger : Log storage error
Route-->>Client : 500 Internal Server Error
else Success
Route-->>Client : 200 OK with results
end
end
Diagram sources
Simple Authentication Error Handling
Simple authentication routes implement specific abort patterns:
flowchart TD
A["Authentication Request"] --> B{"Credentials Present?"}
B --> |No| C["abort(404)"]
B --> |Yes| D["Parse Credentials"]
D --> E{"Valid Credentials?"}
E --> |No| F["abort(400)"]
E --> |Yes| G["Process Authentication"]
G --> H["Success Response"]
C --> I["404 Not Found Response"]
F --> J["400 Bad Request Response"]
Diagram sources
Advanced Registration Error Handling
Advanced registration routes implement sophisticated validation with multiple error categories:
flowchart TD
A["Registration Request"] --> B{"Public Key Present?"}
B --> |No| C["400 Missing publicKey"]
B --> |Yes| D["Validate Required Fields"]
D --> E{"All Required Fields Present?"}
E --> |No| F["400 Missing Required Field"]
E --> |Yes| G["Validate Challenge Format"]
G --> H{"Valid Challenge?"}
H --> |No| I["400 Invalid Challenge Format"]
H --> |Yes| J["Process Registration"]
J --> K{"Success?"}
K --> |No| L["500 Internal Error"]
K --> |Yes| M["200 Success Response"]
Diagram sources
Section sources
Validation Error Patterns
The platform implements comprehensive validation patterns across different input types:
Input Validation Patterns
JSON Payload Validation
# Pattern: Check for required fields
if not data or not data.get("publicKey"):
return jsonify({"error": "Invalid request: Missing publicKey in CredentialCreationOptions"}), 400
# Pattern: Validate field presence
if not public_key.get("rp"):
return jsonify({"error": "Missing required field: rp"}), 400
Binary Data Validation
# Pattern: Validate binary format conversion
try:
challenge_bytes = _extract_binary_value(challenge_value)
if isinstance(challenge_bytes, str):
challenge_bytes = bytes.fromhex(challenge_bytes)
except (ValueError, TypeError) as exc:
return jsonify({"error": f"Invalid challenge format: {exc}"}), 400
String Format Validation
# Pattern: Validate string formats
if not username:
return jsonify({"error": "Username is required in user.name"}), 400
# Pattern: Validate file formats
if not trimmed.lower().endswith(".json"):
errors.append(f"{trimmed} is not a JSON file.")
Validation Error Categories
| Error Category | Status Code | Example Scenarios |
|---|---|---|
| Missing Fields | 400 | Required JSON fields absent |
| Invalid Formats | 400 | Malformed binary data, invalid JSON |
| Business Rules | 400 | Invalid user data, conflicting operations |
| Resource Not Found | 404 | Non-existent credentials, missing metadata |
| Processing Errors | 500 | Unexpected failures in computation |
Section sources
Server Configuration Issues
The platform handles various server configuration scenarios with appropriate error responses:
Configuration Validation
Secret Key Configuration
# Pattern: Validate secret key availability
secret = os.urandom(32)
try:
os.makedirs(os.path.dirname(default_path), exist_ok=True)
except OSError as exc:
app.logger.warning("Unable to store generated session secret: %s", exc)
return secret
Metadata Configuration
# Pattern: Handle missing metadata files
try:
with open(metadata_path, "r", encoding="utf-8") as metadata_file:
payload = json.load(metadata_file)
except FileNotFoundError:
return jsonify({"error": "Verified metadata snapshot is not available."}), 404
Configuration Error Responses
Missing Required Environment Variables
{
"error": "Configuration error: Missing required environment variable",
"variable": "FIDO_SERVER_SECRET_KEY",
"solution": "Set environment variable or provide key file",
"code": "CONFIGURATION_ERROR",
"timestamp": "2024-01-15T10:30:00Z"
}
Invalid File Paths
{
"error": "File not found: Metadata verification failed",
"path": "/path/to/metadata/file",
"code": "FILE_NOT_FOUND",
"timestamp": "2024-01-15T10:30:00Z"
}
Section sources
JSON Payload Validation
The platform implements robust JSON payload validation with comprehensive error reporting:
JSON Parsing Error Handling
Malformed JSON Detection
# Pattern: Safe JSON parsing with error handling
payload = request.get_json(silent=True) or {}
if not isinstance(payload, dict):
return jsonify({"error": "Expected JSON payload."}), 400
Missing Required Fields
# Pattern: Comprehensive field validation
if not isinstance(codec_input, str) or not codec_input.strip():
return jsonify({"error": "Codec payload must be a non-empty string."}), 400
if not isinstance(target_format, str) or not target_format.strip():
return jsonify({"error": "Encoder format must be provided."}), 400
JSON Validation Patterns
Type Checking
# Pattern: Validate input types
if not isinstance(value, str):
raise ValueError("Input must be a string")
Content Validation
# Pattern: Validate content constraints
if not value.strip():
raise ValueError("Input cannot be empty")
Format Validation
# Pattern: Validate specific formats
if not re.match(r'^[A-Za-z0-9+/=]+$', base64_string):
raise ValueError("Invalid base64 format")
JSON Error Response Examples
Invalid JSON Payload
{
"error": "Expected JSON payload.",
"received": "null",
"expected": "JSON object",
"code": "INVALID_JSON",
"timestamp": "2024-01-15T10:30:00Z"
}
Missing Required Field
{
"error": "Codec payload must be a non-empty string.",
"field": "payload",
"received": "",
"code": "MISSING_FIELD",
"timestamp": "2024-01-15T10:30:00Z"
}
Section sources
Error Response Examples
Complete Error Response Catalog
Registration Failures
Missing Public Key
{
"error": "Invalid request: Missing publicKey in CredentialCreationOptions",
"code": "REGISTRATION_VALIDATION_ERROR",
"field": "publicKey",
"timestamp": "2024-01-15T10:30:00Z"
}
Invalid Challenge Format
{
"error": "Invalid challenge format: invalid hexadecimal string",
"code": "CHALLENGE_VALIDATION_ERROR",
"field": "challenge",
"received": "invalid_hex_value",
"expected": "valid_hex_string",
"timestamp": "2024-01-15T10:30:00Z"
}
Authentication Failures
Missing Credentials
{
"error": "No valid credentials found for authentication",
"code": "AUTHENTICATION_ERROR",
"timestamp": "2024-01-15T10:30:00Z"
}
Invalid User ID Format
{
"error": "Invalid user ID format: invalid hexadecimal",
"code": "USER_ID_VALIDATION_ERROR",
"field": "userId",
"received": "invalid_hex",
"expected": "hex_string",
"timestamp": "2024-01-15T10:30:00Z"
}
Metadata Operations
File Upload Errors
{
"error": "No JSON files were provided.",
"code": "UPLOAD_ERROR",
"timestamp": "2024-01-15T10:30:00Z"
}
Corrupted Metadata
{
"error": "Verified metadata snapshot is corrupted.",
"code": "METADATA_CORRUPTION_ERROR",
"path": "/api/mds/metadata/base",
"timestamp": "2024-01-15T10:30:00Z"
}
Decoder Errors
Invalid Payload Format
{
"error": "Decoder input is empty.",
"code": "DECODER_INPUT_ERROR",
"timestamp": "2024-01-15T10:30:00Z"
}
Unsupported Encoding
{
"error": "Input does not appear to be valid base64, base64url, or hexadecimal data.",
"code": "ENCODING_ERROR",
"received": "invalid_input",
"timestamp": "2024-01-15T10:30:00Z"
}
Section sources
Troubleshooting Guide
Common Error Scenarios and Solutions
400 Bad Request Issues
Problem: Invalid JSON payload structure
- Cause: Malformed JSON or missing required fields
- Solution: Validate JSON structure and ensure all required fields are present
- Example:
{"error": "Expected JSON payload."}
Problem: Missing authentication credentials
- Cause: Required headers or parameters not provided
- Solution: Include necessary authentication headers or parameters
- Example:
{"error": "Missing required field: rp"}
404 Not Found Issues
Problem: Resource not available
- Cause: Attempting to access non-existent endpoint or resource
- Solution: Verify endpoint URL and resource existence
- Example:
{"error": "Verified metadata snapshot is not available."}
Problem: Deleted credentials
- Cause: Attempting to access previously deleted credentials
- Solution: Re-register or restore credentials
- Example:
{"error": "Metadata entry not found."}
500 Internal Server Errors
Problem: Unexpected server failure
- Cause: Unhandled exceptions in business logic
- Solution: Check server logs for detailed error information
- Example:
{"error": "Unable to decode payload."}
Problem: Storage operation failure
- Cause: Database or file system access issues
- Solution: Verify storage configuration and permissions
- Example:
{"error": "Failed to store uploaded metadata on the server."}
Debugging Strategies
Enable Detailed Logging
# Enable debug mode for detailed error information
app.debug = True
Validate Input Data
# Log input data for debugging
app.logger.debug(f"Received payload: {payload}")
Monitor Error Patterns
# Track error frequencies
@app.errorhandler(Exception)
def handle_error(error):
app.logger.error(f"Error occurred: {error}")
return jsonify({"error": str(error)}), 500
Error Recovery Patterns
Graceful Degradation
# Provide fallback responses for critical failures
try:
result = perform_operation()
except Exception as e:
app.logger.warning(f"Fallback operation failed: {e}")
return jsonify({"error": "Service temporarily unavailable"}), 503
Retry Mechanisms
# Implement retry logic for transient failures
def safe_operation():
for attempt in range(MAX_RETRIES):
try:
return perform_operation()
except TemporaryFailure as e:
if attempt == MAX_RETRIES - 1:
raise
time.sleep(2 ** attempt) # Exponential backoff
Section sources