C.W.K.
Stream
Lesson 03 of 06 · published

Bcrypt, Local IP Bypass, Session Cookies

~15 min · bcrypt, session-cookies, ip-binding

Level 0Greenhorn
0 XP0/53 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

Three primitives the middleware leans on. Each is small; combined they're the entire AuthN story.

Bcrypt — storing the PIN without being able to recover it

Local IP bypass — convenience with an audit trail

The bypass is a deliberate trade: you accept that anyone on these IPs is "you", in exchange for not entering the PIN every time you reload from your dev machine. Two rules make it survivable.

  1. Be explicit about which IPs. Hardcode the set; don't accept "any RFC1918 address" by default.
  2. Log when it triggers. Future-you debugging "did the PIN work?" needs to see "bypassed because IP was in trusted list".

Session cookies — the token in the browser

Code

Bcrypt hashing helpers·python
import bcrypt

def hash_pin(pin: str) -> bytes:
    # cost 12 = ~150ms per hash on modern hardware
    # tune: low enough to not annoy you, high enough to slow attackers
    return bcrypt.hashpw(pin.encode(), bcrypt.gensalt(rounds=12))

def verify_pin(input_pin: str, stored_hash: bytes) -> bool:
    try:
        return bcrypt.checkpw(input_pin.encode(), stored_hash)
    except ValueError:
        return False  # malformed hash
Explicit local IP bypass set·python
LOCAL_BYPASS = {
    "127.0.0.1",       # loopback IPv4
    "::1",             # loopback IPv6
    "192.168.1.42",    # the Mac on the desk — explicit
    # NOT "192.168.1.0/24" — too broad
}
Issuing a session and validating it·python
import secrets, time

SESSION_SECONDS = 30 * 24 * 3600   # 30 days

def create_session(ip: str) -> str:
    token = secrets.token_urlsafe(32)        # 256 bits of entropy
    now   = int(time.time())
    db.execute(
        "INSERT INTO security_sessions(token, ip, created_at, expires_at) "
        "VALUES (?, ?, ?, ?)",
        (token, ip, now, now + SESSION_SECONDS)
    )
    db.commit()
    return token

def session_valid(token: str, ip: str) -> bool:
    row = db.execute(
        "SELECT ip, expires_at FROM security_sessions WHERE token = ?",
        (token,)
    ).fetchone()
    if not row:
        return False
    stored_ip, expires_at = row
    if expires_at < int(time.time()):
        return False
    if stored_ip != ip:
        return False              # token bound to issuing IP
    return True
Setting the session cookie·python
response.set_cookie(
    key="session",
    value=token,
    max_age=SESSION_SECONDS,
    httponly=True,          # JS can't read it
    secure=True,            # HTTPS only (turn off only for local dev)
    samesite="strict",      # no cross-site sends
    path="/"
)

External links

Exercise

Implement the three helpers (hash_pin, verify_pin, create_session, session_valid) on top of the middleware from the previous lesson. Insert a row into security_config with pin_hash = hash_pin('4729'). Verify in a Python REPL that verify_pin('4729', stored) returns True and verify_pin('4730', stored) returns False.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.