Git Product home page Git Product logo

Comments (2)

Auroratide avatar Auroratide commented on August 13, 2024

This is surprisingly nontrivial in the face of parallel requests. That is, if two requests are sent with expired access simultaneously (which does happen on some pages), then both will want to refresh the token. One will win, and the other will lose; the problem is with Gotrue, when an old refresh token is attempted, the current token becomes invalidated, ruining future refresh attempts.

Gotrue reference - A revoked token is handled differently from an incorrect one; Gotrue perceives it as an abuse attempt and therefore clears stuff.

Queueing Requests on the Client

One strat I've seen is essentially forcing parallel on the client to wait for a refresh to finish. That is, when a request fails, it issues a refresh and then retries. Importantly, that request is stored somewhere as a promise. Parallel requests fail too, but we wait for the stored refresh request to resolve before processing these requests.

A natural question to ask is how to handle multi-tab workflows. Since tabs do not share their in-memory values, if they (somehow) issue requests simultaneously, the same sort of conflict can arise.

Centralized Refresh

The most transparent way to handle refresh is to do so in SvelteKit's handle function, but unless there some shared state regarding what request is currently refreshing, the parallel problem is unresolved.

A centralized store such as Redis could be used for this, or since we're using Supabase, a simple postgres table.

A table might have an entry for a hashed refresh token with a creation date. When a request is made with an expired token, handle looks for an entry in the Table. If there is an entry, then that means a refresh has already occurred, and a 401 will be issued. The client should then utilize some retry strategy, effectively waiting for cookies to get set.

If there is not an entry, then it gets inserted into the DB, and the refresh is commenced. If the refresh fails, then the cookies are reset and the person will need to log in again.

Cron or something can be used to clean the table every once in a while to minimize collisions and free up data.

Note: this approach requires the superkey be used, as we do not want the table to be publicly accessible, nor is it possible to tie it to user permissions in any way (as, the whole point is the user doesn't have a token to begin with).

from sifetti.

Auroratide avatar Auroratide commented on August 13, 2024

Decision: A refresh token endpoint will be created for refreshing the token. This endpoint is useful in two ways:

  • Either, it can be called on a schedule by the front-end to ensure a live session
  • Or, it can be used as in the Queueing Requests on the Client method above

Although the Centralized Refresh idea probably offers the best immunity to parallelism problems, it comes with enormous complexity. The problem is not that a new table is needed, but that the table has a bunch of security implications: that refresh tokens being as powerful as passwords means they would need to be at least as securely stored, and that the supabase superkey would have to be exposed on the server (which is fine technically, but it's most secure if not used at all). On top of that, incredibly robust handling of 401 by the client must be implemented.

The endpoint creates an opportunity for transition into this architecture if, in practice, parallelism problems are common.

  1. Scheduled refresh is relatively transparent. Downsides include the potential for different tabs to refresh simultaneously, requiring JS (though the site already assumes JS), and over-generating access tokens.
  2. Refresh only when needed, aka when endpoints fail with 401, with good retry logic.
  3. Centralized refresh on the server relying on retry logic from step 2 (aka, draw the rest of the owl).

from sifetti.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.