Session verification during server side rendering
important
Getting access to the session during server side rendering is only possible using cookie-based sessions. This is the default setting, but you have to keep this in mind if you want to switch to header-based sessions.
#
1) Enable sharing of cookies across sub domainsIf your API layer and website are on different sub domains (like example.com
and api.example.com
), then by default, the session tokens are attached only to api.example.com
. You want to change this so that the session tokens are attached to .example.com
so that the access token cookie is sent to your webserver on example.com
as well. This can be enabled by setting the cookieDomain
config on the backend.
#
2) Do JWT verificationFollow the JWT verification guide to verify the JWT on the server side. You can read the JWT from the sAccessToken
cookie in the request object. If the JWT is missing, or is invalid, or has expired, you should redirect the user to a /refresh-session?redirectBack=<current route>
page (you can have any path for this since it's your website).
On the /refresh-session
page, you want to call the attemptRefreshingSession
function (from the client side). This function will attempt to refresh the session. If it succeeds, it will return true
. If it fails, it will return false
. If it returns true
, you want to redirect the user back to the page they were on. If it returns false
, you want to redirect the user to the login page.
/refresh-session
page)#
3) Implementing the refresh session flow (On this path, we want to attempt refreshing the session which can yield:
- Success: The frontend will get new access and refresh tokens. Post this, we want to redirect the user to the path mentioned on the
redirectBack
query param. - Failure: This would happen if the session has expired or has been revoked from the backend. Either way, you want to redirect the user to the login page.
Below is the code snippet that you can use on the /refresh-session
path on the frontend
- ReactJS
- Angular
- Vue
import Session from 'supertokens-web-js/recipe/session';
function attemptRefresh() {
Session.attemptRefreshingSession().then(success => {
if (success) {
// we have new session tokens, so we redirect the user back
// to where they were.
const urlParams = new URLSearchParams(window.location.search);
window.location.href = urlParams.get('redirectBack')!;
} else {
// we redirect to the login page since the user
// is now logged out
window.location.href = "/login"
}
})
}
import React from "react";
import Session from "supertokens-auth-react/recipe/session"
import SuperTokens from "supertokens-auth-react";
export function AttemptRefresh(props: any) {
React.useEffect(() => {
let cancel = false;
Session.attemptRefreshingSession().then(success => {
if (cancel) {
// component has unmounted somehow..
return;
}
if (success) {
// we have new session tokens, so we redirect the user back
// to where they were.
const urlParams = new URLSearchParams(window.location.search);
window.location.href = urlParams.get('redirectBack')!;
} else {
// we redirect to the login page since the user
// is now logged out
SuperTokens.redirectToAuth();
}
})
return () => {
cancel = true;
}
}, []);
return null;
}
import Session from 'supertokens-web-js/recipe/session';
function attemptRefresh() {
Session.attemptRefreshingSession().then(success => {
if (success) {
// we have new session tokens, so we redirect the user back
// to where they were.
const urlParams = new URLSearchParams(window.location.search);
window.location.href = urlParams.get('redirectBack')!;
} else {
// we redirect to the login page since the user
// is now logged out
window.location.href = "/login"
}
})
}
#
Why do we trigger the refresh session flow instead of redirecting the user to the login page directly?There are two reasons why JWT verification can fail:
- The session tokens were not passed from the frontend: This can happen if the route is called when the user has logged out.
- The session tokens are passed from the frontend, but the JWT has expired.
If we redirect the user to the login page directly, then in the second case, the frontend will redirect the user back to the current route (since the refresh token is still valid) causing an infinite loop. To counteract this issue, we redirect the user to refresh page which will cause a new access token to be minted. In the first case, when the user is actually logged out, the refreshing will fail, and they will be redirected to the login page anyway.
verifySession
or getSession
instead of manual JWT verification?#
Can I use Yes you can, but we do not recommend it because:
- Often the webserver is on a different process than the API server. Using our backend SDK requires you to give it the credentials to the SuperTokens core, which you might not want to provide to the webserver.
- The
session
object resulting fromverifySession
andgetSession
makes it very easy to mutate the access token payload. These mutations are reflected on the frontend via network interceptors from our frontend SDK. But in SSR, the browser makes the call to your webserver direclty, so our frontend SDK interceptors don't run. This can cause inconsistency between the access token payload as seen on the frontend vs the backend.