---
title: Switch between cookie and header-based sessions
description: Switch between cookie and header-based sessions for secure token management in SuperTokens.
sidebar:
  order: 50
---

## 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 [`HttpOnly` cookies](https://owasp.org/www-community/HttpOnly) by default to prevent token theft via XSS

### Header based
  - The default in the mobile SDKs
  - Uses the [`Authorization` header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Authorization) with a [`Bearer` auth-scheme](https://developer.mozilla.org/en-US/docs/Web/HTTP/Authentication#authentication_schemes)
  - 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

:::warning[We recommend cookie-based sessions in browsers because header-based sessions require saving the access and refresh tokens in storage vulnerable to XSS attacks.]
:::

## 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.

<UITypeSwitch />

<VariantContent storageKey="ui-type" value="prebuilt">

<DependentContent passive group="frontend-prebuilt-ui">
<ContentOption title="Angular" value="angular">
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.
</ContentOption>
</DependentContent>

<CodeGroup group="frontend-prebuilt-ui">
<Tab title="Reactjs" value="reactjs">
```tsx
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"
    }),
  ],
});
```
</Tab>
<Tab title="Angular" value="angular">
```tsx check=false reason="Requires SDK globals from surrounding application"
// 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"
    }),
  ],
});
```
</Tab>
</CodeGroup>

<DependentContent passive group="frontend-prebuilt-ui">
<ContentOption title="Angular" value="angular">
This change goes in the `supertokens-web-js` SDK configuration at the root of your application:
</ContentOption>
</DependentContent>

<CodeGroup passive group="frontend-prebuilt-ui">
<Tab title="Angular" value="angular">
```tsx
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"
    }),
  ],
});
```
</Tab>
</CodeGroup>

</VariantContent>

<VariantContent storageKey="ui-type" value="custom">



<DependentContent passive group="frontend-custom-ui">
<ContentOption title="Mobile" value="mobile">
<DependentContent passive group="mobile-frameworks">
<ContentOption title="Android" value="android">
You can use the `tokenTransferMethod` builder method to set what mode the SDK should use for sessions.
</ContentOption>
</DependentContent>
</ContentOption>
</DependentContent>

<CodeGroup group="frontend-custom-ui">
<Tab title="Web" value="web">
<DependentContent group="install-method" label="Installation method">
<ContentOption title="npm" value="npm">
```tsx
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"
    }),
  ],
});
```
</ContentOption>
<ContentOption title="Script tag" value="script-tag">
```tsx check=false reason="Requires SDK globals from surrounding application"
supertokens.init({
  appInfo: {
    apiDomain: "...",
    appName: "...",
  },
  recipeList: [
    supertokensSession.init({
      tokenTransferMethod: "header", // or "cookie",
    }),
  ],
});
```
</ContentOption>
</DependentContent>
</Tab>
<Tab title="Mobile" value="mobile">
<DependentContent group="mobile-frameworks" label="Mobile framework">
<ContentOption title="ReactNative" value="reactnative">
```tsx
import SuperTokens from "supertokens-react-native";

SuperTokens.init({
  apiDomain: "...",
  tokenTransferMethod: "header", // or "cookie". "header" by default
});
```
</ContentOption>
<ContentOption title="Android" value="android">
```kotlin
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()
    }
}
```
</ContentOption>
<ContentOption title="iOS" value="ios">
```swift
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
    }

}
```
</ContentOption>
<ContentOption title="Flutter" value="flutter">
```dart
import 'package:supertokens_flutter/supertokens.dart';

void main() {
    SuperTokens.init(
        apiDomain: "...",
        tokenTransferMethod: SuperTokensTokenTransferMethod.COOKIE,
    );
}
```
</ContentOption>
</DependentContent>
</Tab>
</CodeGroup>

<DependentContent passive group="frontend-custom-ui">
<ContentOption title="Mobile" value="mobile">
<DependentContent passive group="mobile-frameworks">
<ContentOption title="Android" value="android">
### Using cookies

When using cookies for session management you need to enable cookies before making requests.

#### With `HttpURLConnection`
</ContentOption>
</DependentContent>
</ContentOption>
</DependentContent>

<CodeGroup passive group="frontend-custom-ui">
<Tab title="Mobile" value="mobile">
<DependentContent group="mobile-frameworks" label="Mobile framework">
<ContentOption title="Android" value="android">
```kotlin
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
    }
}
```
</ContentOption>
</DependentContent>
</Tab>
</CodeGroup>

<DependentContent passive group="frontend-custom-ui">
<ContentOption title="Mobile" value="mobile">
<DependentContent passive group="mobile-frameworks">
<ContentOption title="Android" value="android">
`SuperTokensPersistentCookieStore` is a cookie store that SuperTokens provides which uses SharedPreferences to persist sessions across app launches

#### With `OkHttp` / `Retrofit`
</ContentOption>
</DependentContent>
</ContentOption>
</DependentContent>

<CodeGroup passive group="frontend-custom-ui">
<Tab title="Mobile" value="mobile">
<DependentContent group="mobile-frameworks" label="Mobile framework">
<ContentOption title="Android" value="android">
```kotlin
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
    }
}
```
</ContentOption>
</DependentContent>
</Tab>
</CodeGroup>

<DependentContent passive group="frontend-custom-ui">
<ContentOption title="Mobile" value="mobile">
<DependentContent passive group="mobile-frameworks">
<ContentOption title="Android" value="android">
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.
</ContentOption>
</DependentContent>
</ContentOption>
</DependentContent>



</VariantContent>

### 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.

:::warning[**You should not set this on the backend if you have more than one client using different modes** (for example if you have a website that uses cookie based, and a mobile app that uses header based sessions).]
:::


<CodeGroup group="backend-language">
<Tab title="Node.js" value="nodejs">
```tsx
import SuperTokens from "supertokens-node";
import Session from "supertokens-node/recipe/session";

SuperTokens.init({
  appInfo: {
    apiDomain: "...",
    appName: "...",
    websiteDomain: "...",
  },
  recipeList: [
    Session.init({
      getTokenTransferMethod: () => "header",
    }),
  ],
});
```
</Tab>
<Tab title="Go" value="go">
```go
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
				},
			}),
		},
	})
}
```
</Tab>
<Tab title="Python" value="python">
```python check=false reason="Partial configuration example"
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
        )
    ]
)
```
</Tab>
</CodeGroup>

:::note[By default, session verification allows both cookie and authorization bearer tokens. When creating a new session, it follows the preference of the frontend indicated by the `st-auth-mode` request header (set by the frontend SDK).]
:::
