Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add setSession support for a SSR context #445

Merged
merged 2 commits into from
Oct 10, 2022

Conversation

hf
Copy link
Contributor

@hf hf commented Sep 21, 2022

Adds support for calling setSession() in a server-side rendering context. When used in SSR, the access and refresh tokens are typically sent from the browser to the server. Both of them represent the user's session.

Users can thus call:

await client.setSession({ 
  access_token: req.cookies['my-access-token'], 
  refresh_token: req.cookies['my-refresh-token'] 
})

To correctly extract the session information from the two cookies. The client can then be used to call other APIs and automatic refresh token management will take place.

@hf hf requested a review from a team as a code owner September 21, 2022 11:09
src/lib/version.ts Outdated Show resolved Hide resolved
Copy link
Member

@kangmingtay kangmingtay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we're trying to do too much here and i'm not sure what this PR is trying to change - the current method just requires a refresh token, forces a refresh and then sets the current session.

Why do we also want to support setting a session via an access token? If no refresh token is being passed in, it could result in a incomplete session returned.

src/GoTrueClient.ts Show resolved Hide resolved
src/GoTrueClient.ts Outdated Show resolved Hide resolved
src/GoTrueClient.ts Outdated Show resolved Hide resolved
src/GoTrueClient.ts Outdated Show resolved Hide resolved
src/GoTrueClient.ts Outdated Show resolved Hide resolved
@hf
Copy link
Contributor Author

hf commented Sep 21, 2022

Here's a Mermaid description of the issue:

sequenceDiagram
    participant G as GoTrue
    participant S as Server
    participant B as Browser
    participant C as Cookies
    participant L as Local Storage
    
    B-->>S: GET /login
    S-->>B: 200 OK Render /login

    B-->>G: POST /sign-in { email, password }
    G-->>B: 303 See Other server/authenticate...

    B-->>S: GET /authenticate
    S-->>B: 200 OK Render /authenticate

    activate B

        B-->>B: getSessionFromURL
        B-->>L: putItem(session, ...)
        B-->>C: document.cookie = 'my-access-token...'
        B-->>C: document.cookie = 'my-refresh-token...'

    deactivate B

    note over G, L: After 1 week the user comes back to /route on server -- no issues

    activate B
        B-->>S: GET /route
        B-->>S: Cookie: my-access-token ...
        B-->>S: Cookie: my-refresh-token ...

        activate S
            S-->>S: setSession(req.cookies['my-refresh-token'])
            S-->>G: POST /verify?grant_type=refresh_token
            G-->>S: 200 OK access token, refresh token
            S-->>S: return session information to app

            S-->>B: 200 OK prerendered content
        deactivate S

        B-->>B: _refreshSession
        B-->>L: getItem(session)
        L-->>B: session { access_token, refresh_token, expires_at }
        B-->>G: POST /verify?grant_type=refresh_token
        G-->>B: 200 OK access token, refresh token 
        B-->>L: putItem(session)
    deactivate B
    

note over G, L: Immediately after login user navigates to /route -- issue after 1 hour

   activate B
        B-->>S: GET /route
        B-->>S: Cookie: my-access-token ...
        B-->>S: Cookie: my-refresh-token ...

        activate S
            S-->>S: setSession(req.cookies['my-refresh-token'])
            S-->>G: POST /token?grant_type=refresh_token
            G-->>S: 200 OK access token, refresh token
            S-->>S: return session information to app

            note over B, S: Start reuse timer!

            S-->>B: 200 OK prerendered content
        deactivate S

        B-->>B: _refreshSession
        B-->>L: getItem(session)
        L-->>B: session { access_token, refresh_token, expires_at }

        note over L, B: now is before expires_at!
        note over L, B: No need to renew refresh token

        note over G, L: 1 hour passes, app notices expires_at and tries to refresh token
        B-->>G: POST /token?grant_type=refresh_token
        G-->>B: 401 Unauthorized refresh token already used

        note over G, B: 1 hour passed after the first validation of the refresh token!

    deactivate B

note over G, L: With setSession({ access_token, refresh_token }) fix -- no-issue

   activate B
        B-->>S: GET /route
        B-->>S: Cookie: my-access-token ...
        B-->>S: Cookie: my-refresh-token ...

        activate S
            S-->>S: setSession({ refresh_token: req.cookies['my-refresh-token']), access_token: ... })
            S-->>S: access token is not expired no post to GoTrue

            S-->>S: return session information to app

            note over B, S: Start reuse timer!

            S-->>B: 200 OK prerendered content
        deactivate S

        B-->>B: _refreshSession
        B-->>L: getItem(session)
        L-->>B: session { access_token, refresh_token, expires_at }

        note over L, B: now is before expires_at!
        note over L, B: No need to renew refresh token

        note over G, L: 1 hour passes, app notices expires_at and tries to refresh token
        B-->>G: POST /token?grant_type=refresh_token
        G-->>B: 200 OK access_token, refresh_token

        note over G, B: 1 hour passed after the first validation of the refresh token!

        B-->>L: putItem(session, ...)
        B-->>C: document.cookie = 'my-access-token...'
        B-->>C: document.cookie = 'my-refresh-token...'

        note over L, G: Ok but what if the user closes the tab until 1 hour passes and then navigates to /route

        B-->>S: GET /route
        B-->>S: Cookie: my-access-token ...
        B-->>S: Cookie: my-refresh-token ...

        activate S
            S-->>S: setSession({ refresh_token: req.cookies['my-refresh-token']), access_token: ... })
            S-->>S: access token IS expired, refreshing in GoTrue
            S-->>G: POST /token?grant_type=refresh_token
            G-->>S: 200 OK access token, refresh token
            S-->>S: return session information to app

            note over B, S: Start reuse timer!

            S-->>B: 200 OK prerendered content
        deactivate S

        B-->>B: _refreshSession
        B-->>L: getItem(session)
        L-->>B: session { access_token, refresh_token, expires_at }
        B-->>B: now is after expires_at!
        B-->>G: POST /token?grant_type=refresh_token
        note over B, G: this occurs milliseconds after the refresh from the server
        note over B, G: thus the refresh_token although used is within a reuse period
        G-->>B: 200 OK access_token, refresh_token

        B-->>L: putItem(session, ...)
        B-->>C: document.cookie = 'my-access-token...'
        B-->>C: document.cookie = 'my-refresh-token...'

        note over G, L: All is good in the world!

    deactivate B

Loading

src/GoTrueClient.ts Outdated Show resolved Hide resolved
src/GoTrueClient.ts Outdated Show resolved Hide resolved
src/GoTrueClient.ts Outdated Show resolved Hide resolved
@hf hf force-pushed the hf/add-set-session-ssr-support-v1 branch from 9bc250c to 1813591 Compare October 4, 2022 08:38
kangmingtay
kangmingtay previously approved these changes Oct 4, 2022
@hf hf force-pushed the hf/add-set-session-ssr-support-v1 branch 2 times, most recently from a610ec3 to 0d33675 Compare October 4, 2022 10:19
@hf hf dismissed kangmingtay’s stale review October 4, 2022 10:22

I need to improve the types still, I don't want someone merging this accidentally. :D

@hf hf force-pushed the hf/add-set-session-ssr-support-v1 branch from 0d33675 to e8a5355 Compare October 4, 2022 11:11
@hf hf force-pushed the hf/add-set-session-ssr-support-v1 branch from e8a5355 to be413ca Compare October 4, 2022 11:18
src/GoTrueClient.ts Outdated Show resolved Hide resolved
@kangmingtay kangmingtay merged commit 4e7165e into master Oct 10, 2022
@kangmingtay kangmingtay deleted the hf/add-set-session-ssr-support-v1 branch October 10, 2022 02:55
@github-actions
Copy link
Contributor

🎉 This PR is included in version 1.24.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@github-actions
Copy link
Contributor

🎉 This PR is included in version 2.0.0-rc.11 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants