Skip to content

Alternative short-lived refresh design #238

@martinthomson

Description

@martinthomson

@arnar and I talked about the general problem statement at TPAC, but never really concluded that discussion to either of our satisfaction.

As noted in the TAG review, the primary concern is the unitary nature of the design. The TAG likes the overall problem statement and is supportive of the general approach, but would prefer to see a modular design. There are elements in this document that cover most of that, but the question of how the short-lived cookie is refreshed remains a sticking point.

I think that the problem statement basically equates to this:

  1. Refreshing the short-lived cookie that is issued in response to receiving a signature from the TPM becomes far more important in this new model. The goal is to ensure that refreshes are frequent, so you have continual assurance of the liveness of the signing key, but not so frequent that the TPM is overloaded.
  2. Sites that rely on periodic refreshes, such as fetching new email or getting document updates, are most exposed to the short-lived cookie expiring.
  3. Those sites are generally poorly set up to manage expiration. They have processes for dealing with a need to reauthenticate, but those are typically much more disruptive because they are built for longer-lived cookies expiring. Typically, that means triggering a user-level authentication flow, including passkeys, 2FA, and the works. You don't want to risk firing that every few minutes.

Overall, there is a strong desire to have the browser recognize that the cookie is expired and have it automatically refreshed before any request that might need to fail.

The present design is all based on the JSON controller document that acts as something of a controller for multiple cookies and resources. There is also a formal notion of a session, which encompasses the use of keys, scopes, refresh sources, and more. For refreshing cookies, that design has the site publish the set of places that cookies need to be provided, plus how those cookies are refreshed. That's quite a bit of complexity to manage.

Continuing from the more modular alternative design proposed, just looking at the refresh component, here's a potential approach1.

Set-Cookie: shortlived=123; Secure; HttpOnly; Max-Age=600; Path=/OtherPath;
  Refresh=/RefreshEndpoint; Refresh-Time=86400

This says that the cookie is good for 10 minutes, but the server asks that the browser attempt to automatically refresh the cookie for up to a day before using it if it expires.

The way the cookie is refreshed is to fetch the identified URL. The browser would be told to make that request before proceeding with a fetch, without a cache (cache-mode = "no-store" or maybe "reload"), just like in the present design. The difference being that you don't have a need for the notion of a session to drive this design.

The only tiny catch is that this is not valid if Path is unspecified or a prefix of Refresh. Otherwise, you create a circular dependency.

The Refresh-Time thing might be optional if we can agree on a default, or even a fixed value. It seems like this could be almost arbitrarily long, up to however long the browser is willing to hold a cookie for.

This doesn't look significantly different, except that the cookie itself encodes its own refresh criteria. There are other things you might consider adding (I'm unconvinced of the utility of caching a challenge or including a session ID, for instance; both are something the site could put in the URL instead, not requiring the browser to do anything special).

As indicated in the linked analysis, whether this refresh endpoint2 is the one that asks for a signed cookies is up to the server, but I would generally recommend that the server use a redirect on that fetch so that it can provide a fresh random challenge and demonstrate true live access to the secret key.

Overall, this could be more modular than what is presently proposed. It offers a new tool for servers that want to manage cookie issuance centrally, for more than just this one case. I won't pretend like this addresses all of the details that have been integrated into the present design (what if the TPM is overloaded? how does this interact with navigation?) but hopefully it shows an alternative path for the requirements, as stated.

Footnotes

  1. With thanks to GitHub's "http" syntax highlighter, which has helpfully highlighted the parts I'm proposing to add.

  2. As an HTTP person, we don't refer to these things as endpoints. The term we prefer is "resource".

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