Switch between cookie and header-based sessions
Switch between cookie and header-based sessions for secure token management in SuperTokens.
Overview
SuperTokens supports 2 methods of authorizing requests. The following guide shows you how to switch between them.
Cookie based
- The default in the web SDKs
- Uses
HttpOnlycookies by default to prevent token theft via XSS
Header based
- The default in the mobile SDKs
- Uses the
Authorizationheader with aBearerauth-scheme - This can make it easier to work with API gateways and third-party services
- Preferable in mobile environments, since they can have buggy and/or unreliable cookie implementations
When creating or authorising sessions, the SDK has to choose to send the tokens to the frontend by cookies or custom headers. The backend controls this choice, but it follows a preference set in the frontend configuration.
Before you start
Steps
1. Update the frontend configuration
You can provide a tokenTransferMethod property in the configuration of the Session recipe to set the preferred token transfer method. The backend receives this method with every request in the st-auth-mode header.
By default, the backend follows this preference.
You need to make changes to the auth route configuration, as well as to the supertokens-web-js SDK configuration at the root of your application:
This change is in your auth route configuration.
import SuperTokens from "supertokens-auth-react";
import Session from "supertokens-auth-react/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
Session.init({
tokenTransferMethod: "header", // or "cookie"
}),
],
});// this goes in the auth route config of your frontend app (once the pre-built UI script has been loaded)
supertokensUIInit({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
supertokensUISession.init({
tokenTransferMethod: "header", // or "cookie"
}),
],
});This change goes in the supertokens-web-js SDK configuration at the root of your application:
import SuperTokens from "supertokens-web-js";
import Session from "supertokens-web-js/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
},
recipeList: [
Session.init({
tokenTransferMethod: "header", // or "cookie"
}),
],
});You can use the tokenTransferMethod builder method to set what mode the SDK should use for sessions.
import SuperTokens from "supertokens-web-js";
import Session from "supertokens-web-js/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
},
recipeList: [
Session.init({
tokenTransferMethod: "header", // or "cookie"
}),
],
});supertokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
},
recipeList: [
supertokensSession.init({
tokenTransferMethod: "header", // or "cookie",
}),
],
});import SuperTokens from "supertokens-react-native";
SuperTokens.init({
apiDomain: "...",
tokenTransferMethod: "header", // or "cookie". "header" by default
});import android.app.Application
import com.supertokens.session.SuperTokens
class MainApplication: Application() {
override fun onCreate() {
super.onCreate()
SuperTokens.Builder(this, "...")
.tokenTransferMethod("header") // or "cookie". "header" by default
.build()
}
}import UIKit
import SuperTokensIOS
fileprivate class ApplicationDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
do {
try SuperTokens.initialize(
apiDomain: "...",
tokenTransferMethod: .header // or .cookie . header by default
)
} catch SuperTokensError.initError(let message) {
// TODO: Handle initialization error
} catch {
// Some other error
}
return true
}
}import 'package:supertokens_flutter/supertokens.dart';
void main() {
SuperTokens.init(
apiDomain: "...",
tokenTransferMethod: SuperTokensTokenTransferMethod.COOKIE,
);
}Using cookies
When using cookies for session management you need to enable cookies before making requests.
With HttpURLConnection
import android.app.Application
import com.supertokens.session.SuperTokens
import com.supertokens.session.SuperTokensHttpURLConnection
import com.supertokens.session.SuperTokensPersistentCookieStore
import java.net.CookieManager
class MainApplication: Application() {
override fun onCreate() {
super.onCreate()
CookieManager.setDefault(CookieManager(SuperTokensPersistentCookieStore(this), null))
// TODO: Make sure to call SuperTokens.init
}
}SuperTokensPersistentCookieStore is a cookie store that SuperTokens provides which uses SharedPreferences to persist sessions across app launches
With OkHttp / Retrofit
import android.content.Context
import com.franmontiel.persistentcookiejar.PersistentCookieJar
import com.franmontiel.persistentcookiejar.cache.SetCookieCache
import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor
import com.supertokens.session.SuperTokens
import com.supertokens.session.SuperTokensInterceptor
import okhttp3.OkHttpClient
import retrofit2.Retrofit
class NetworkManager {
fun getClient(context: Context): OkHttpClient {
val clientBuilder = OkHttpClient.Builder()
clientBuilder.addInterceptor(SuperTokensInterceptor())
// TODO: Make sure to call SuperTokens.init
// Sets persistent cookies
clientBuilder.cookieJar(PersistentCookieJar(SetCookieCache(), SharedPrefsCookiePersistor(context)))
val client = clientBuilder.build()
// REQUIRED FOR RETROFIT ONLY
val instance = Retrofit.Builder()
.baseUrl("<YOUR_BASE_URL>")
.client(client)
.build()
return client
}
}In the above example, PersistentCookieJar from 'com.github.franmontiel:PersistentCookieJar:v1.0.1' enables persistently storing cookies using SharedPreferences to maintain sessions across app launches.
2. Update the backend configuration (optional)
This step is optional. You can force the backend to use a specific token transfer method regardless of the frontend configuration.
import SuperTokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";
SuperTokens.init({
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [
Session.init({
getTokenTransferMethod: () => "header",
}),
],
});import (
"net/http"
"github.com/supertokens/supertokens-golang/recipe/session"
"github.com/supertokens/supertokens-golang/recipe/session/sessmodels"
"github.com/supertokens/supertokens-golang/supertokens"
)
func main() {
supertokens.Init(supertokens.TypeInput{
RecipeList: []supertokens.Recipe{
session.Init(&sessmodels.TypeInput{
GetTokenTransferMethod: func(req *http.Request, forCreateNewSession bool, userContext supertokens.UserContext) sessmodels.TokenTransferMethod {
return sessmodels.HeaderTransferMethod
},
}),
},
})
}from supertokens_python import init, InputAppInfo
from supertokens_python.recipe import session
from supertokens_python.framework import BaseRequest
from typing import Dict, Any
def get_token_transfer_method(req: BaseRequest, for_create_new_session: bool, user_context: Dict[str, Any]):
# OR use session.init(get_token_transfer_method=lambda *_: "header")
return "header"
init(
app_info=InputAppInfo(api_domain="...", app_name="...", website_domain="..."),
framework='...',
recipe_list=[
session.init(
get_token_transfer_method=get_token_transfer_method
)
]
)