Working with multiple API endpoints
To enable use of sessions for multiple API endpoints, you need to use the sessionTokenBackendDomain config on the frontend and cookieDomain on the backend Session.init function call.
important
- All your API endpoints must have the same top level domain. For example, they can be
{"api.example.com", "api2.example.com"}, but they cannot be{"api.example.com", "api.otherdomain.com"}. - The backend config (step 1 and 2) need to only be done if you are using cookie based auth (which is the default for web apps). If using header based auth, please skip to step 3.
Step 1) Set Cookie Domain in the Backend Config (only applicable for cookie based auth)#
You need to set the cookieDomain value to be the common top level domain. For example, if your API endpoints are {"api.example.com", "api2.example.com", "api3.example.com"}, the common portion of these endpoints is ".example.com" (The dot is important). So you would need to set the following:
- NodeJS
- GoLang
- Python
- Other Frameworks
Important
import SuperTokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
supertokens: {
connectionURI: "...",
},
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Session.init({
cookieDomain: ".example.com",
})
]
});
import (
"github.com/supertokens/supertokens-golang/recipe/session"
"github.com/supertokens/supertokens-golang/recipe/session/sessmodels"
"github.com/supertokens/supertokens-golang/supertokens"
)
func main() {
cookieDomain := ".example.com"
supertokens.Init(supertokens.TypeInput{
RecipeList: []supertokens.Recipe{
session.Init(&sessmodels.TypeInput{
CookieDomain: &cookieDomain,
}),
},
})
}
from supertokens_python import init, InputAppInfo
from supertokens_python.recipe import session
init(
app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
framework='...',
recipe_list=[
session.init(
cookie_domain='.example.com'
)
]
)
The above will set the session cookies' domain to example.com, allowing them to be sent to *.example.com.
note
Whilst the cookieDomain can start with a leading ., the value of the apiDomain in appInfo must point to an exact API domain only. This should be the API in which you want to expose all the auth related endpoints (for example /auth/signin).
For local development, you should not set the cookieDomain to an IP address based domain, or .localhost - browsers will reject these cookies. Instead, you should alias localhost to a named domain and use that.
Step 2) Set Older Cookie Domain in the Backend Config (only applicable for cookie based auth)#
To avoid locking out users with existing sessions (they will get a 500 error when try to refresh their session), set olderCookieDomain to match your previous cookieDomain. If your cookieDomain was not set, you can use an empty string. However, if you don't have any existing sessions, you can skip this step entirely.
- NodeJS
- GoLang
- Python
- Other Frameworks
Important
import SuperTokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
supertokens: {
connectionURI: "...",
},
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Session.init({
cookieDomain: ".example.com",
olderCookieDomain: "" // Set to an empty string if your previous cookieDomain was unset. Otherwise, use your old cookieDomain value.
})
]
});
import (
"github.com/supertokens/supertokens-golang/recipe/session"
"github.com/supertokens/supertokens-golang/recipe/session/sessmodels"
"github.com/supertokens/supertokens-golang/supertokens"
)
func main() {
cookieDomain := ".example.com"
olderCookieDomain := "" // Set to an empty string if your previous cookieDomain was unset. Otherwise, use your old cookieDomain value.
supertokens.Init(supertokens.TypeInput{
RecipeList: []supertokens.Recipe{
session.Init(&sessmodels.TypeInput{
CookieDomain: &cookieDomain,
OlderCookieDomain: &olderCookieDomain,
}),
},
})
}
from supertokens_python import init, InputAppInfo
from supertokens_python.recipe import session
init(
app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
framework='...',
recipe_list=[
session.init(
cookie_domain='.example.com',
older_cookie_domain='' # Set to an empty string if your previous cookie_domain was unset. Otherwise, use your old cookie_domain value.
)
]
)
caution
If
olderCookieDomainisn't set, users with older sessions will get a 500 error from the session refresh endpoint, effectively locking them out. This will continue untilolderCookieDomainis set correctly or they clear their cookies.The value set for
olderCookieDomainmust be kept for 1 year because the cookie lifetime of the access token on the frontend is 1 year (even though the JWT expiry is a few hours).If you have changed the
cookieDomainmore than once within one year, to prevent a stuck state, switch to header based auth for all your clients. The important thing here is that you have to set the backend config to header even though that doc says it's optional. This is so that all clients are forced to use header based auth.Changing the
cookieDomaincan cause a temporary spike in requests, even if theolderCookieDomainis set correctly. This happens because older sessions, with older cookie domain, require additional refresh calls to clear their old cookies and set new ones. This spike is a one-time event and should not recur after the update.
info
The olderCookieDomain value should be set to prevent clients from having multiple session cookies from different domains. This can happen when cookies from a previous domain are still valid and sent with requests. For instance, if your previous cookieDomain was api.example.com and the new one is .example.com, both sets of cookies would be sent to the apiDomain api.example.com, leading to an inconsistent state. This can cause issues until the older cookies are cleared. Setting olderCookieDomain in the configuration ensures that the SuperTokens SDK can automatically remove these older cookies.
Step 3) Frontend config (for cookie or header based auth)#
You need to set the same value for sessionTokenBackendDomain on the frontend. This will allow the frontend SDK to apply interception and automatic refreshing across all your API calls:
- ReactJS
- Angular
- Vue
Important
supertokens-auth-react SDK and will inject the React components to show the UI. Therefore, the code snippet below refers to the supertokens-auth-react SDK.import SuperTokens from "supertokens-auth-react";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Session.init({
sessionTokenBackendDomain: ".example.com"
})
]
});
Important
supertokens-auth-react SDK and will inject the React components to show the UI. Therefore, the code snippet below refers to the supertokens-auth-react SDK.import SuperTokens from "supertokens-auth-react";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Session.init({
sessionTokenBackendDomain: ".example.com"
})
]
});
import SuperTokens from "supertokens-auth-react";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Session.init({
sessionTokenBackendDomain: ".example.com"
})
]
});