User Authentication System Project¶
Authentication systems handle sensitive data — passwords, session tokens, and account state — that must never be exposed or modified directly by external code. Encapsulation enforces these boundaries at the class level, ensuring that password hashes remain hidden, failed-attempt counters cannot be reset arbitrarily, and sessions expire automatically. This project applies the encapsulation patterns introduced earlier in the chapter.
Build a secure user authentication system using encapsulation.
Requirements¶
User Class¶
Private attributes (must not be accessible directly from outside the class):
_username— The user's unique identifier._password_hash— Stored hash of the password; never the plaintext._email— The user's email address._failed_attempts— Counter for consecutive failed login attempts._is_locked— Whether the account is currently locked.
Properties:
username— Read-only after creation.email— Validated format on set (must contain@and a domain).- Password — Expose only a setter that hashes the input (e.g., using
hashlib). No getter; the plaintext is never stored or retrievable.
Methods:
authenticate(password)— Hash the input and compare to_password_hash. Increment_failed_attemptson failure and reset to zero on success. Lock the account if failures exceed the threshold (default: 3 consecutive attempts; make this configurable).lock_account()— Set_is_lockedtoTrue.unlock_account()— Set_is_lockedtoFalseand reset_failed_attemptsto zero.
Session Class¶
Private attributes:
_user— The authenticatedUserinstance._token— Generated securely usingsecrets.token_hex()or similar._expiry— Set to a configurable duration from creation time (e.g., 30 minutes)._is_active— Automatically becomesFalsewhen the current time exceeds_expiry.
Methods:
is_valid()— ReturnTrueonly if_is_activeisTrueand the current time has not exceeded_expiry.
AuthSystem Class¶
register_user(username, password, email)— Create a newUser, validate inputs, and store in an internal user registry. Raise an error if the username already exists.login(username, password)— Look up the user, callauthenticate(), and create aSessionif successful. Raise appropriate errors for locked accounts or invalid credentials.logout(token)— Invalidate the session associated with the given token.
Use Python's name-mangling (_ prefix) and @property decorators to enforce encapsulation. No external code should be able to read password hashes or directly modify account lock status.