Skip to main content

Login Authentication Simulator

This project transforms control flow into a real system.

You are not writing:

if password == "123":

You are designing:

  • A state machine
  • A retry system
  • A lock mechanism
  • A deterministic branching architecture

This is how real authentication logic works.

Concept Overview

While watching, focus on:

  • State transitions
  • Retry logic
  • Early termination
  • Guard clauses
  • Deterministic branching

Step 1 - Define System Requirements

Our system must:

  1. Ask for username and password
  2. Allow maximum 3 attempts
  3. Lock account after 3 failures
  4. Exit immediately on success
  5. Prevent infinite loops
  6. Clearly separate validation logic
note

Always define system behavior before writing code.

Step 2 - Model the State

Authentication system state includes:

  • Stored username
  • Stored password
  • Attempt counter
  • Lock status

We start simple.

Step 3 - Basic Version (State + Loop)

stored_username = "admin"
stored_password = "secure123"

attempts = 0
max_attempts = 3

while attempts < max_attempts:
username = input("Username: ")
password = input("Password: ")

if username == stored_username and password == stored_password:
print("Login successful.")
break

attempts += 1
print(f"Invalid credentials. Attempts left: {max_attempts - attempts}")

else:
print("Account locked.")

Execution Analysis

This demonstrates:

  • While loop as state machine
  • break for early success
  • loop-else for lock behavior
  • Controlled termination

Possible execution paths:

  1. Success on first attempt
  2. Success on second attempt
  3. Success on third attempt
  4. Three failures → lock

Deterministic.

tip

loop-else executes only if no break occurred. Perfect for retry systems.

Step 4 - Add Guard Clauses

Refactor validation into function.

def validate_credentials(input_user, input_pass, stored_user, stored_pass):
if not input_user:
return False
if not input_pass:
return False
return input_user == stored_user and input_pass == stored_pass

This isolates logic.

Updated main loop:

while attempts < max_attempts:
username = input("Username: ")
password = input("Password: ")

if validate_credentials(username, password, stored_username, stored_password):
print("Login successful.")
break

attempts += 1
print(f"Invalid credentials. Attempts left: {max_attempts - attempts}")

Step 5 - Add Account Lock State

We now model lock explicitly.

is_locked = False

while attempts < max_attempts and not is_locked:
username = input("Username: ")
password = input("Password: ")

if validate_credentials(username, password, stored_username, stored_password):
print("Login successful.")
break

attempts += 1

if attempts >= max_attempts:
is_locked = True
print("Account locked.")
else:
print(f"Invalid credentials. Attempts left: {max_attempts - attempts}")

Now lock is explicit state.

note

Explicit state modeling improves clarity.

Step 6 - Prevent Timing Attacks (Conceptual)

Real systems do not reveal whether username or password failed.

Instead of:

if username != stored_username:
print("Invalid username")
elif password != stored_password:
print("Invalid password")

We use unified message:

print("Invalid credentials")

Security through uniform behavior.

Step 7 - Add Role-Based Logic

Now we extend system.

stored_users = {
"admin": {"password": "secure123", "role": "admin"},
"user": {"password": "userpass", "role": "user"}
}

Updated loop:

while attempts < max_attempts:
username = input("Username: ")
password = input("Password: ")

user_data = stored_users.get(username)

if user_data and user_data["password"] == password:
print("Login successful.")

if user_data["role"] == "admin":
print("Admin dashboard access granted.")
else:
print("User dashboard access granted.")

break

attempts += 1
print(f"Invalid credentials. Attempts left: {max_attempts - attempts}")

else:
print("Account locked.")

Now we have:

  • Dictionary lookup
  • Guard-style validation
  • Pattern-driven branching
  • Role-based decision tree

Step 8 - Add Lockout Persistence (Advanced)

Simulate lock storage:

locked_accounts = set()

if username in locked_accounts:
print("Account already locked.")
return

After max attempts:

locked_accounts.add(username)

Now lock persists across sessions.

Step 9 - Refactor Into Structured Architecture

Separate concerns:

def authenticate(username, password):
user_data = stored_users.get(username)
if not user_data:
return False
return user_data["password"] == password

def handle_success(user_data):
print("Login successful.")
if user_data["role"] == "admin":
print("Admin access granted.")
else:
print("User access granted.")

Main loop:

while attempts < max_attempts:
username = input("Username: ")
password = input("Password: ")

if authenticate(username, password):
handle_success(stored_users[username])
break

attempts += 1

Now logic is modular.

Step 10 - Analyze Execution Paths

Possible states:

  • Valid login
  • Invalid login
  • Locked account
  • Already locked
  • Role-based routing

Each branch must be deterministic.

No ambiguous states allowed.

Common Mistakes in Login Systems

❌ Infinite retry loops
❌ Revealing which field failed
❌ Missing lock condition
❌ Deep nesting instead of guards
❌ Mixing authentication and routing logic
❌ No fallback behavior

Complexity Reflection

This simple project demonstrates:

  • State-driven loops
  • break semantics
  • loop-else usage
  • Guard clauses
  • Pattern-driven role branching
  • Decision tree design
  • Deterministic control flow

This is not a toy script.

It is foundational backend logic.

Engineering Reflection Questions

Before finalizing, ask:

  • Can this loop run forever?
  • Are all paths covered?
  • Is default behavior defined?
  • Is state mutation clear?
  • Are credentials handled safely?
  • Is branching readable?
  • Can new roles be added easily?

If not, refactor.

Final Insight

Authentication systems are decision engines.

They are not about checking a password.

They are about:

  • Managing state
  • Controlling execution
  • Preventing abuse
  • Handling edge cases
  • Scaling behavior

This project trains you to:

Think in states. Design in branches. Terminate intentionally. Handle failure gracefully.

Control flow is system behavior.

And you just built one.

© 2026 EngineersOfAI. All rights reserved.