Skip to content
This repository was archived by the owner on Oct 5, 2026. It is now read-only.
This repository was archived by the owner on Oct 5, 2026. It is now read-only.

Session fixation revoke does not fire on the form_post callback path #36

Closed

Description

@ParallelEntrepreneur

Found in the Fable review of #35 (Apple sign-in), and deliberately not bodged there.

What

sessions::issue revokes the presented session before issuing a new one, as a fixation defence:

if let Some(presented) = login.presented_cookie
    && let Some(old) = store::session_by_token_hash(db, &sha256_raw(presented.as_bytes())).await?
{
    store::revoke_session(db, &old.id, &iso(clock.now())).await?;
}

That needs the raw cookie value. On a form_post callback (Apple) the session cookie is SameSite=Lax and does not arrive, so presented_cookie is always None and the revoke never runs.

#35 fixes the linking half of this by sealing the signed-in user id into the flow at /start (which is same-site, so the cookie does arrive there). It deliberately does not seal the cookie's value, because that is a bearer credential and putting it inside a second cookie widens its exposure for no clear gain.

Impact

Low. The person's previous session row stays live server-side until it expires, with no cookie pointing at it, because the browser has just overwritten it. It is untidy rather than exploitable: the cookie is __Host- and HttpOnly, so it cannot be planted cross-site, which is the attack the revoke exists for.

Options

  1. Seal the session id (not its value) into the flow alongside the user id, and give Login a presented_session_id alternative to presented_cookie. Contained, and makes the revoke fire on every path.
  2. Decide the revoke only meaningfully defends the paths where a cookie can be planted, and document that it does not apply to form_post.

Option 1 is probably right, but it changes auth-core's public API, which is why it is here rather than in #35.

Activity

  1. added a commit that references this issue on Sep 7, 2026
  2. ParallelEntrepreneur commented on Sep 7, 2026

    @ParallelEntrepreneur
    ContributorAuthor

    Documented the form_post blind spot on issue() and Login::presented_cookie in #44 (merged), so the code no longer reads as "always revokes" — that was the concrete misleading-reader risk.

    The behavioural fix (option 1) is unchanged and still worth doing when auth-core's API is next touched: seal the session id into the flow at /start (same-site, so the cookie is present there) and add a presented_session_id to Login that issue() revokes by id when presented_cookie is absent. Leaving this open to track that.

  3. added a commit that references this issue on Sep 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions