Skip to content
C.W.K.
Lesson 04 of 05 · published

Dad Is a Session, Not a Header

~16 min · authentication, sessions, cookies, x-forwarded-for, fetch-metadata

Level 0Closed Lens
0 XP0/45 lessons0/13 achievements
0/100 XP to next level100 XP to go0% complete

The Header Any Program Can Send

Many of the rules so far end with "or Dad on Oriel's page": he can open the eyes there, clear a mark, start a recording, change a setting. For nine days, "Dad on the page" meant a request carrying the browser header Sec-Fetch-Site: same-origin. Browsers set that header themselves, and a web page from another site cannot forge it, so it is a reasonable signal against cross-site requests. But it is not an identity. Any program on Pippa's home Mac can send a request with whatever headers it likes, including that one. A local script could have "been Dad".

Dad's ruling on 2026-11-10 was short: "오리엘 페이지 인증 pin으로 가" (authenticate Oriel's page with the PIN). Since then the header only says "this came from the page"; who is pressing is decided by the family's PIN session.

Signing In Is the Family's, Not Oriel's

The family already has one authority for Dad's sessions: a PIN door, with passkey unlock (Face ID or Touch ID) on top, owned by the family registry app. Oriel does not build a second one. The page asks that door from the browser itself, using the family kit's PIN client, so the authority binds the session to Dad's device. The page then hands the token to Oriel (POST /api/page/session), and Oriel keeps it in an HttpOnly, SameSite=Strict cookie, and only if the authority confirms it is this device's live session.

Oriel keeps no session logic of its own: no expiry, no revocation, no attempt count. Each check asks the authority (through a scoped door in cwkPippa, with a key Oriel already holds), and the authority applies its own blacklist and lockdown and slides the session as on any request it admits. One small cache keeps it cheap: a valid answer is reused for 30 seconds, so a burst of presses costs one ask. A refusal is never cached.

Which Device Is Asking?

A session belongs to a device, so Oriel must know which device a request came from. The engine listens on loopback only; requests from other devices arrive through Tailscale Serve, the tailnet's HTTPS front, which appends the real peer address to X-Forwarded-For. That word matters. Anything earlier in the header was written by the caller and is only a claim; the last entry is what the proxy saw. So Oriel reads the last entry. A request with no forwarded address at all came from this Mac, and the authority knows this Mac by its own tailnet address.

Refusals Say What Was Missing

A page write that fails the check gets 401 or 503 with a session field naming exactly what was missing: no_session, expired_or_unknown, blocked, deep_lockdown or authority_unavailable. Never a guess. And reads were brought behind the same check later the same day ("사진 없는 읽기도 pin 뒤로 넣어": put the picture-less reads behind the PIN too): the state, the eye, sessions, the activity log. Signed out, the page reads nothing and shows only the sign-in card.

The Stops Fail Open

On that sign-in card sit the buttons that need no session: close every eye, stop play, stop recording, park the cameras (and, on the full page, Manual and forgetting the voice grant). They are pressed "blind", and Oriel's answer is shown. With a good session, a stop is recorded as Dad's; without one, as oriel. This is the asymmetry from the first track made concrete. The check that protects loosening is never allowed to stand between Dad and a stop, because the moment he most needs a stop is not a moment to discover his session expired.

Code

The device is the proxy's last entry; a valid answer is reused briefly, a refusal never (trimmed excerpt, backend/page_auth.py)·python
VALID_FOR_S = 30.0


def device(self, request) -> str | None:
    peer = _ip(request.client.host if request.client else None)
    if peer is not None and not ipaddress.ip_address(peer).is_loopback:
        return peer
    forwarded = (request.headers.get("x-forwarded-for") or "").split(",")[-1]   # the proxy's entry
    if forwarded.strip():
        return _ip(forwarded)
    return _ip(self.this_device())           # no forwarded address: this Mac


def check(self, token, device) -> Verdict:
    if not token:
        return Verdict(False, "no_session", device or "")
    if not device:
        return Verdict(False, "no_device")
    key = (token, device)
    now = self.clock()
    with self._lock:
        until = self._valid.get(key)
        if until is not None and until > now:
            return Verdict(True, "", device)
    try:
        answer = self.ask(token, device)          # the family authority decides
    except AuthorityUnavailable:
        return Verdict(False, "authority_unavailable", device)
    if answer.get("valid") is True:
        with self._lock:
            self._valid[key] = now + VALID_FOR_S
        return Verdict(True, "", device)
    with self._lock:
        self._valid.pop(key, None)
    return Verdict(False, str(answer.get("reason") or "expired_or_unknown"), device)
Why a header is not an identity: any local program can claim to be the page (try it against any local server)·bash
# A browser sets Sec-Fetch-Site itself; curl will set whatever you tell it to.
curl -s -i http://127.0.0.1:8000/some/route \
  -H 'Sec-Fetch-Site: same-origin' \
  -H 'X-Forwarded-For: 203.0.113.7, 198.51.100.9'
# The first X-Forwarded-For entry is pure claim. Only the entry a proxy you
# trust appended (the last one, when that proxy appends) says who connected.

External links

Exercise

Write a small FastAPI app with one write route and one stop route. Protect the write route with a session check that asks an "authority" function (a stub that accepts one token for one device address) and caches only valid answers for 30 seconds. Read the device from the last X-Forwarded-For entry when the peer is loopback. Leave the stop route open. Then use curl to show that a forged first X-Forwarded-For entry changes nothing.
Hint
Return the reason in the refusal (no_session, expired_or_unknown, authority_unavailable) and test each one. And make sure the stop route still answers when the authority stub raises: that is the fail-open half of the design.

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 in — Please sign in to comment.

No comments yet — be the first.