Session security
Overview
The following page takes you through some common security considerations that the SuperTokens Session
recipe handles.
Anti-csrf
CSRF attacks can happen if a logged in user visits a malicious website which makes an API call to your website's API to maliciously change that user's data.
To protect against this attack, the cookie sameSite
attribute works along with some anti-csrf measures.
This attribute declares if your cookies should restrict to a first-party or same-site context.
Configuring sameSite
can prevent CSRF attacks.
For example, if sameSite
is lax
, the browser only sends cookies for requests that originate from the same top level domain as the API's domain.
If a user visits a malicious site, requests from those sites do not have the session cookies.
Configure anti-csrf
- SuperTokens automatically defends against CSRF attacks.
- Please only change this setting if you know what you are doing. If you are unsure, please feel free to ask questions.
- This setting does not apply while using header-based authentication, since they get the same protection as
antiCsrf
set toVIA_CUSTOM_HEADER
.
You can change the antiCsrf
configuration option to take control of the kind of protection you get.
You can use on of the following values:
"NONE"
would disable any anti-csrf protection from our end. You can use this if you have an implementation of CSRF protection."VIA_CUSTOM_HEADER"
uses this method to prevent CSRF protection. This sets automatically ifsameSite
isnone
or if yourapiDomain
andwebsiteDomain
do not share the same top level domain name."VIA_TOKEN"
uses an explicit anti-csrf token. Use this method if you want to allow any origin to query your APIs. This method may cause issues in browsers like Safari, especially if your site embeds as aniframe
.
import SuperTokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
supertokens: {
connectionURI: "...",
},
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Session.init({
antiCsrf: "VIA_CUSTOM_HEADER", // Should be one of "NONE" or "VIA_CUSTOM_HEADER" or "VIA_TOKEN"
})
]
});
Cookie consent
Per GDPR, users do not need to give consent for your application to use session cookies. This is because they fall under essential cookies and not tracking cookies:
"While it is not required to obtain consent for these cookies, explain to the user what they do and why they are necessary."
Same site cookies
To ensure session cookies have protection from CSRF attacks, the sameSite
cookie attribute ensures this protection.
The sameSite
cookie attribute declares if your cookies should restrict to a first-party or same-site context.
The sameSite
attribute can have three possible values:
none
- Cookies attach in all contexts, that is, cookies attach to both first-party and cross-origin requests.
- On Safari however, if third-party cookies do not work (which is the default behavior), and the website and
API
domains do not share the same top-level domain, then cookies do not go. Please check the session management page to see how you can switch to using headers.
lax
- Cookies are only sent in a first-party context and along with
GET
requests initiated by third party websites (that result in browser navigation - user clicking on a link).
- Cookies are only sent in a first-party context and along with
strict
- Cookies are only sent in a first-party context and not sent along with requests initiated by third party websites.
Configuration
- SuperTokens automatically sets the value of the
sameSite
cookie attribute based on your website andAPI
domain configuration. - Please only change this setting if you are a web security expert. If you are unsure, please feel free to ask questions.
import SuperTokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
supertokens: {
connectionURI: "...",
},
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Session.init({
cookieSameSite: "strict", // Should be one of "strict" or "lax" or "none"
}),
],
});
Cookies and HTTPS
SuperTokens ensures that cookies have security by enabling the secure
flag when generating session cookies.
When set, the secure
attribute limits the scope of the cookie to attach only to secure domains.
This results in the cookie only attaching to requests transmitted over https
.
This, in turn, prevents cookie theft via man in the middle attacks.
You can explicitly set the security level of cookies using the next snippet:
If not explicitly set, SuperTokens automatically determines the value for the secure
attribute based on your API domain having http
or https
.
import SuperTokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
supertokens: {
connectionURI: "...",
},
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Session.init({
cookieSecure: true,
})
]
});
Access Token signing key rotation
Access Token signing key rotation implies that the secret key for signing the access tokens changes at a fixed time interval. This reduces the risk of key theft.
- Existing logged in users are not logged out on key change.
- This feature enables by default.
Change the key rotation interval
docker run \
-p 3567:3567 \
// highlight-start
-e ACCESS_TOKEN_DYNAMIC_SIGNING_KEY_UPDATE_INTERVAL=168 \
// highlight-end
-d registry.supertokens.io/supertokens/supertokens-<db name>
access_token_dynamic_signing_key_update_interval
- Time in hours for how frequently the signing key changes.
- It must have a
number
value with, the default value set to168
For managed service, update this value by visiting the dashboard.
Use static keys
If you do not want to use dynamic keys for session creation, then you can tell SuperTokens to use the static key instead. This is useful in cases where you want to hard-code the public key for JWT verification in some process.
import SuperTokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
supertokens: {
connectionURI: "...",
},
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "..."
},
recipeList: [
Session.init({
useDynamicAccessTokenSigningKey: false,
})
]
});
Updating this value causes a spike in the session refresh API, as and when users visit your application.