> ## Documentation Index
> Fetch the complete documentation index at: https://stytch.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Cookies & Session Management

> Guide to cookies and session management with the React SDK

export const vertical_0 = "Consumer"

{vertical_0 === "B2B" ? (
<Note>
  For additional information about how to manage sessions when using our frontend JavaScript SDK, check out the <a href="/multi-tenant-auth/manage-sessions/session-layer/overview">Session guide</a>.
</Note>
) : (
<Note>
  For additional information about how to manage sessions when using our frontend JavaScript SDK, check out the <a href="/consumer-auth/manage-sessions/overview">Session guide</a>.
</Note>
)}

<p>Stytch will automatically save the {vertical_0 === "B2B" ? "Member's" : "User's"} Session in two cookies:</p>

* `stytch_session` that will contain the opaque session token returned from the API
* `stytch_session_jwt` that will contain the session JWT returned from the API

For example, if you load the SDK on [https://app.mycoolsite.com](https://app.mycoolsite.com) it will set

* `document.cookie` = `stytch_session=secret-session; domain=app.mycoolsite.com; path=/; SameSite=Lax; Secure; max-age=whenever-it-expires`
* `document.cookie` = `stytch_session_jwt=eyJhxxx.xxx.xxx; domain=app.mycoolsite.com; path=/; SameSite=Lax; Secure; max-age=whenever-it-expires`

<Warning>
  If you load the SDK on `localhost`, we will not mark the cookies as secure.
</Warning>

## Cookie Configuration Options

The Stytch Client allows you to configure the following directives and values related to cookie management.

<Warning>
  If you're using **HttpOnly cookies**, none of the below options are available.  Cookies are written by the backend, not the JavaScript SDK.
</Warning>

```js theme={null}
{
  "cookieOptions": {
    /**
     * The name of the cookie containing the opaque Stytch session token.
     * Defaults to `stytch_session`.
     */
    "opaqueTokenCookieName": "string",

    /**
     * The name of the cookie containing the opaque Stytch session token.
     * Defaults to `stytch_session_jwt`.
     */
    "jwtCookieName": "string",

    /**
     * What HTTP paths the cookies should be available on.
     * Equal to configuring the `;path=${}` param in the set-cookie directive.
     * Defaults to unset.
     */
    "path": "string",

    /**
     * What domain the cookies should be available on.
     * Equal to configuring the `;domain=${}` param in the set-cookie directive.
     * Requires setting availableToSubdomains to have any effect.
     * Defaults to unset.
     */
    "domain": "string",

    /**
     * Whether to make the cookies available to subdomains.
     * When true, equivalent to configuring the `;domain=${window.location.host}` directive.
     * When false, equivalent to leaving the directive unset.
     * Defaults to false.
     */
    "availableToSubdomains": "boolean"
  }
}
```

To override the defaults, set the desired values in the `cookieOptions` and pass it as part of the optional second parameter object when initializing the Stytch Client.

{vertical_0 === "B2B" ? (
<CodeBlock language="javascript">
{`
import { StytchB2BClient } from "@stytch/vanilla-js/b2b"

const STYTCH_PUBLIC_TOKEN = 'YOUR_PUBLIC_TOKEN';

const stytchOptions = {
  cookieOptions: {
    opaqueTokenCookieName: "my_stytch_session",
    jwtCookieName: "my_stytch_session_jwt",
    path: "/",
    availableToSubdomains: true,
    domain: "app.example.com",
  }
}

const stytchClient = new StytchB2BClient(STYTCH_PUBLIC_TOKEN, stytchOptions)
`}
</CodeBlock>
) : (
<CodeBlock language="javascript">
{`
import { StytchClient } from "@stytch/vanilla-js"

const STYTCH_PUBLIC_TOKEN = 'YOUR_PUBLIC_TOKEN';

const stytchOptions = {
  cookieOptions: {
    opaqueTokenCookieName: "my_stytch_session",
    jwtCookieName: "my_stytch_session_jwt",
    path: "/",
    availableToSubdomains: true,
    domain: "app.example.com",
  }
}

const stytchClient = new StytchClient(STYTCH_PUBLIC_TOKEN, stytchOptions)
`}
</CodeBlock>
)}

## HttpOnly cookies

By default, cookies are managed by the SDK running in the client and are not marked as HttpOnly. For enhanced security, you can enable the use of [HttpOnly cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#httponly) for your project. This moves cookie management from the client to Stytch's backend, which makes it possible to mark cookies as HttpOnly.

When HttpOnly cookies are used, Stytch's backend will set the [Domain of the cookies](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#domaindomain-value) to the parent of your [custom domain](/resources/branding/custom-domains). Note that cookies are accessible to the Domain specified and its subdomains. For example:

* If your custom domain is `login.example.com`, the Domain would be set to `example.com`. The cookies would be accessible to `example.com` and its subdomains.
* If your custom domain is `login.app.example.com`, the Domain would be set to `app.example.com`. The cookies would be accessible to `app.example.com` and its subdomains, but not to `example.com`.

Before enabling HttpOnly cookies, there are some important considerations:

* Using HttpOnly cookies requires a custom domain. This allows Stytch's backend to set cookies in a first-party context for your domain.
* Using HttpOnly cookies will make session tokens inaccessible to client-side JavaScript. This includes opaque session tokens (`stytch_session`), JWT tokens (`stytch_session_jwt`), and intermediate session tokens (`stytch_intermediate_session_token`). These values will also be omitted from response bodies returned to the client from methods like [stytch.session.authenticate()](../methods/sessions/authenticate-session).
* [stytch.session.getTokens()](../methods/sessions/get-tokens) will no longer return session tokens when an active session exists. If you have any frontend code that depends on these values, you will need to change it.
* [stytch.session.updateSession()](../methods/sessions/update-session) will only work if there is not an existing session token set using a cookie marked HttpOnly. If you use `updateSession`, make sure your `cookieOptions` are configured to match the domain and cookie names used by Stytch's backend.
* When the HttpOnly cookies setting is "Enforced", Stytch will only accept browser requests for your project that use your custom domain. Requests that try to access Stytch using other domains, including `api.stytch.com`, will be rejected.
* `cookieOptions` does not apply to HttpOnly cookies.
* HttpOnly cookies are only supported in your **live environment**.

### Enabling HttpOnly cookies

1. Configure a [custom domain](https://stytch.com/dashboard/custom-domains) for your application (see our [guide](/resources/branding/custom-domains)).
2. In the Stytch Dashboard, under [Frontend SDK](https://stytch.com/dashboard/sdk-configuration), go to "Optional configuration" and change the HttpOnly cookies setting to "Enabled". This allows Stytch to start setting HttpOnly cookies when accessed through your custom domain, but still allows requests that do not use your custom domain.
3. In your application, set the `customBaseUrl` option in your Stytch client configuration to your custom domain. This field tell the SDK to use your custom domain for requests. We recommend initially changing this setting in a staging environment or for a limited set of test users.
4. Verify that your application behaves as expected. The `stytch_session` and `stytch_session_jwt` cookies should now be marked as HttpOnly.
5. When you have finished testing and have ensured that all users of your application are using your custom domain, change the HttpOnly cookies setting on the **Frontend SDK** page to "Enforced". **This will block all browser SDK requests that do not use your custom domain**, which will prevent client-side JavaScript from accessing session tokens.

### Disabling HttpOnly cookies

You can stop using HttpOnly cookies by removing the `customBaseUrl` setting from your Stytch client configuration. Be aware that this will not remove existing HttpOnly cookies, which the SDK will be unable to access. To avoid disrupting existing user sessions, have your backend replace HttpOnly cookies with non-HttpOnly cookies.

## Authenticating sessions on your backend

Since the session is stored in the site's cookies, the browser will include these cookies in the request headers to your backend if they share a domain. For any protected requests, your backend should validate either the `stytch_session` or `stytch_session_jwt` before processing with the request. The session may be validated using any [Backend SDK](../../../api/sdks).

### Validating the opaque session in Node.js / Express.

{vertical_0 === "B2B" ? (
<CodeBlock language="javascript">
{`
const express = require('express');
const cookieParser = require('cookie-parser');

const app = express();
app.use(cookieParser());
app.use(authenticateStytchSession);

const client = new stytch.B2BClient({
  project_id: process.env.STYTCH_PROJECT_ID,
  secret: process.env.STYTCH_SECRET,
});

const authenticateStytchSession = (req, res, next) => {
  return client.sessions.authenticate({
    session_token: req.cookies['stytch_session'],
  })
    .then(session => {
      req.stytchSession = session;
      return next();
    })
    .catch(next)
};
`}
</CodeBlock>
) : (
<CodeBlock language="javascript">
{`
const express = require('express');
const cookieParser = require('cookie-parser');

const app = express();
app.use(cookieParser());
app.use(authenticateStytchSession);

const client = new stytch.Client({
  project_id: process.env.STYTCH_PROJECT_ID,
  secret: process.env.STYTCH_SECRET,
});

const authenticateStytchSession = (req, res, next) => {
  return client.sessions.authenticate({
    session_token: req.cookies['stytch_session'],
  })
    .then(session => {
      req.stytchSession = session;
      return next();
    })
    .catch(next)
};
`}
</CodeBlock>
)}

### Validating the JWT in Node.js / Express.

{vertical_0 === "B2B" ? (
<CodeBlock language="javascript">
{`
const express = require('express');
const cookieParser = require('cookie-parser');

const app = express();
app.use(cookieParser());
app.use(authenticateStytchSession);

const client = new stytch.B2BClient({
  project_id: process.env.STYTCH_PROJECT_ID,
  secret: process.env.STYTCH_SECRET,
});

const authenticateStytchSession = (req, res, next) => {
  return client.sessions.authenticateJwt({ session_jwt: req.cookies['stytch_session_jwt'] })
    .then(session => {
      req.stytchSession = session;
      return next();
    })
    .catch(next)
};
`}
</CodeBlock>
) : (
<CodeBlock language="javascript">
{`
const express = require('express');
const cookieParser = require('cookie-parser');

const app = express();
app.use(cookieParser());
app.use(authenticateStytchSession);

const client = new stytch.Client({
  project_id: process.env.STYTCH_PROJECT_ID,
  secret: process.env.STYTCH_SECRET,
});

const authenticateStytchSession = (req, res, next) => {
  return client.sessions.authenticateJwt({ session_jwt: req.cookies['stytch_session_jwt'] })
    .then(session => {
      req.stytchSession = session;
      return next();
    })
    .catch(next)
};
`}
</CodeBlock>
)}
