wiki/appdoc/doc_userauth_process_concept_review.md
2025-12-29 23:54:13 +01:00

13 KiB

Critical Review: User Authentication Process Concept

Issues Found

1. CRITICAL: Data Model Inconsistency

Location: Line 277 in concept document Issue: resetTokenExpires is shown as Optional[str] but should be Optional[float]

# WRONG (line 277):
resetTokenExpires: Optional[str] = Field(None, description="Reset token expiration (ISO datetime)")

# CORRECT:
resetTokenExpires: Optional[float] = Field(None, description="Reset token expiration (UTC timestamp in seconds)")

Impact: Implementation confusion, type errors

2. CRITICAL: Config Value Inconsistency

Location: Line 429 in concept document Issue: Config shows 48 hours but requirement is 24 hours

# WRONG (line 429):
Auth_RESET_TOKEN_EXPIRY_HOURS = 48

# CORRECT:
Auth_RESET_TOKEN_EXPIRY_HOURS = 24

Impact: Wrong expiration time in implementation

3. SECURITY: Missing Rate Limiting

Issue: Password reset request endpoint needs stricter rate limiting than registration Current: Registration has @limiter.limit("10/minute") Needed: Password reset request should have stricter limits to prevent:

  • Email enumeration attacks
  • Spam/DoS attacks
  • Brute force attempts

Recommendation:

  • Password reset request: @limiter.limit("5/minute") or @limiter.limit("3/minute")
  • Password reset (token usage): @limiter.limit("10/minute") (less critical, token is single-use)

4. SECURITY: Token Invalidation Strategy CLARIFIED

Issue: What happens when user requests password reset multiple times? Current: Concept doesn't specify behavior Clarification:

  • Token is stored in the UserInDB record (single field: resetToken)
  • When new reset token is generated, old token is overwritten in the database
  • No risk: Only one token can exist per user at any time (the last one generated)
  • The old token is automatically invalidated because it no longer exists in the database

Status: No risk - token overwriting ensures only one valid token exists

5. SECURITY: Token Reuse Prevention CLARIFIED

Issue: What prevents token from being used multiple times? Current: Concept says "Tokens are single-use (cleared after password reset)" but doesn't specify validation Clarification:

  • Token is cleared immediately after successful password reset (atomic operation)
  • Once cleared, token no longer exists in database
  • No risk: If token is used again, validation will fail because token doesn't exist
  • Token reuse is prevented by the fact that token is removed from database after use

Status: No risk - token clearing after use prevents reuse automatically

6. SECURITY: Email Case Sensitivity

Issue: Email uniqueness check - are emails case-sensitive? Current: Concept doesn't specify Risk:

  • User@Example.com and user@example.com could be treated as different
  • Email enumeration could reveal accounts

Recommendation:

  • Normalize emails to lowercase before storage and comparison
  • Use email.lower().strip() in all email operations
  • Document this in the concept

7. SECURITY: Email Enumeration Prevention APPROACH SELECTED

Issue: Registration endpoint reveals if email exists Current: Registration rejects if email exists → reveals email is registered Risk: Attacker can enumerate registered emails

Selected Approach:

  • If email exists for LOCAL auth user: Send password reset email to existing user, don't create duplicate account
  • Return generic success message: "Registration successful. Please check your email to set your password."
  • Don't reveal: Whether email already existed or new account was created
  • This prevents email enumeration while providing good UX

Status: Approach selected - send reset email to existing user if email exists

8. EDGE CASE: Multiple Reset Requests CLARIFIED

Issue: User requests reset multiple times before using first token Current: Concept doesn't specify behavior Clarification:

  • Token is stored in UserInDB record (single field)
  • Only one token can exist at a time - the last one generated
  • When new reset request comes in, old token is overwritten in database
  • Only the last token is valid - previous tokens are automatically invalidated
  • No special handling needed - database structure ensures single token

Status: No risk - database structure prevents multiple tokens

9. EDGE CASE: User State Changes During Reset

Issue: What happens if user state changes while reset token is active? Scenarios:

  • User is disabled (enabled=False) while reset token is active
  • User changes email while reset token is active
  • User account is deleted while reset token is active
  • User sets password via admin while reset token is active

Recommendation:

  • On password reset, check user still exists and is enabled
  • If user is disabled, allow reset but keep enabled=False (admin must activate)
  • If email changed, token should still work (token is tied to user, not email)
  • If user deleted, token validation should fail (user not found)

10. EDGE CASE: Expired Token Cleanup APPROACH SELECTED

Issue: Expired tokens remain in database indefinitely Current: Concept doesn't mention cleanup Risk: Database bloat, potential security issues

Selected Approach:

  • Check token expiration during user authentication (on each login attempt)
  • Clear expired token if found during authentication check
  • Also check during token validation (password reset endpoint) and clear if expired
  • Simplest approach: No separate cleanup job needed, tokens cleaned on access
  • This ensures expired tokens are cleaned automatically without additional jobs

Status: Approach selected - check and clean expired tokens during auth/validation

Issue: How exactly to search across all mandates? Current: Concept says "use root interface" but doesn't specify implementation Questions:

  • Does getRecordsetWithRBAC work with root interface?
  • Should we bypass RBAC for this search?
  • How to ensure we search ALL mandates?

Recommendation:

  • Use root interface with mandateId=None or empty filter
  • Use direct database query if RBAC filtering interferes
  • Document exact implementation approach

12. IMPLEMENTATION: Email Search Method

Issue: No existing method to find user by email across mandates Current: Concept mentions findUserByEmailLocalAuth() but doesn't specify how it works Questions:

  • Does database support case-insensitive email search?
  • Should we use exact match or LIKE?
  • How to handle NULL emails?

Recommendation:

  • Implement method that:
    1. Uses root interface
    2. Searches with recordFilter={"email": email.lower(), "authenticationAuthority": AuthAuthority.LOCAL}
    3. Returns first match or None
    4. Handles NULL emails gracefully

13. USER EXPERIENCE: Email Delivery Failure MESSAGE TO ADD

Issue: What if user never receives email? Current: Concept doesn't address this Scenarios:

  • Email goes to spam
  • Email server is down
  • User enters wrong email
  • Email delivery is delayed

Selected Approach:

  • Show message about spam folder: "If you don't receive an email within 5 minutes, please check your spam folder"
  • Display this message after registration and password reset request
  • Future enhancement: Consider "Resend email" functionality (with rate limiting)

Status: Message to add - show spam folder reminder

14. USER EXPERIENCE: Password Reset After Registration NO SPECIAL HANDLING

Issue: User registers, sets password, then immediately forgets it Current: User must use password reset flow Decision:

  • No special handling required - use standard password reset flow
  • User can request password reset like any other user
  • Same token expiration (24 hours) applies to all reset tokens

Status: No special handling needed

15. MISSING: Token Validation Order

Issue: Order of validation checks not specified Current: Concept lists validations but not order Risk: Inefficient validation, potential security issues

Recommendation:

  • Validate in this order:
    1. Token format (UUID format check)
    2. Token exists in database
    3. User exists and is not deleted
    4. Token matches user's resetToken
    5. Token not expired (compare timestamps)
    6. Password strength
    7. Set password and clear token (atomic operation)

16. MISSING: Atomic Operations CONFIRMED

Issue: Password reset involves multiple database operations Current: Concept doesn't specify transaction handling Risk:

  • Partial updates if operation fails
  • Token cleared but password not set
  • Race conditions

Confirmation:

  • Use database transaction for password reset operation
  • Atomic operation ensures all-or-nothing:
    • Setting passwordHash
    • Clearing resetToken and resetTokenExpires
    • Setting enabled=True
  • All operations succeed or all fail together

Status: Confirmed - atomic operations required

17. MISSING: Audit Logging

Issue: No mention of audit logging for security events Current: Concept doesn't specify logging Risk: No audit trail for security incidents

Recommendation:

  • Log all password reset requests (with email hash for privacy)
  • Log successful password resets
  • Log failed token validations
  • Log token generation events

18. MISSING: Error Messages

Issue: Error messages could reveal too much information Current: Some error messages are specified, but not all Risk: Information leakage

Recommendation:

  • Use generic error messages:
    • "Invalid or expired reset token" (don't specify which)
    • "Registration failed" (don't specify why)
    • "Password reset request processed" (always same message)
  • Log detailed errors server-side only

19. MISSING: Frontend Token Validation

Issue: Frontend should validate token format before API call Current: Concept doesn't specify frontend validation Risk: Unnecessary API calls, poor UX

Recommendation:

  • Validate UUID format in frontend before calling API
  • Show error immediately if token format is invalid
  • Extract token from URL and validate on page load

Issue: Magic link generation needs frontend base URL Current: Concept mentions "Should use frontend base URL from config" but doesn't specify Selected Approach:

  • Add frontend URL to frontend env files: frontend_agents/public/config/env_*.env
  • Files to update:
    • env_int.env - Integration environment URL
    • env_prod.env - Production environment URL
    • (Add env_dev.env if exists)
  • Variable name: APP_FRONTEND_URL or Frontend_BASE_URL
  • Usage: Backend reads from frontend config or gets from request origin
  • Environment-specific: Each env file has its own URL

Status: Location specified - add to frontend env files

Recommendations Summary

High Priority (Security & Correctness)

  1. Fix data model inconsistency (resetTokenExpires type)
  2. Fix config value (24 hours, not 48)
  3. Add rate limiting to password reset endpoints
  4. Implement token invalidation on new reset request
  5. Normalize emails to lowercase
  6. Prevent token reuse (clear immediately after use)
  7. Add atomic transaction for password reset

Medium Priority (Edge Cases)

  1. Handle user state changes during reset
  2. Implement expired token cleanup
  3. Add email delivery failure handling
  4. Specify cross-mandate search implementation
  5. Add audit logging

Low Priority (UX & Polish)

  1. Add frontend token validation
  2. Specify magic link base URL configuration
  3. Improve error messages (generic, secure)
  4. Add resend email functionality (future enhancement)

Security Checklist

  • Rate limiting on all endpoints
  • Token invalidation strategy implemented
  • Token reuse prevention
  • Email normalization (lowercase)
  • Email enumeration prevention
  • Atomic database operations
  • Audit logging
  • Generic error messages
  • Token expiration validation
  • User state validation during reset
  • Cross-mandate search security (RBAC bypass only for root operations)

Testing Checklist (Additional)

  • Multiple reset requests (old token invalidated)
  • Token reuse attempt (should fail)
  • Expired token usage (should fail)
  • User disabled during reset (should handle gracefully)
  • Email case variations (User@Example.com vs user@example.com)
  • Concurrent reset requests (race condition handling)
  • Email delivery failure scenarios
  • Invalid token format handling
  • Cross-mandate email search accuracy
  • Atomic operation rollback on failure