JavaScript SDK

The JavaScript SDK provides a customizable pre-built login form to start a login flow, along with methods that communicate directly with the Stytch API. These help you get up and running with Stytch faster by avoiding the struggles associated with creating a login UI and removing the need to create endpoints on your backend to make requests to Stytch.

Compatibility and requirements

Languages

The SDK is available in vanilla Javascript along with specialized versions for React and Next.

Browsers

  • Chrome and Safari on all platforms
  • Firefox on desktop platforms
  • TLS 1.2 must be supported by the browser

Supported authentication products

  • Email magic links
  • One-time passcodes
  • OAuth
  • WebAuthn
  • TOTPs
  • Crypto wallets
  • Session management
  • User management
  • Passwords
  • Biometrics


Installation

Install the @stytch/vanilla-js, @stytch/react packages via npm or yarn.

npm install @stytch/vanilla-js @stytch/react --save

Initialize the SDK with the StytchUIClient constructor provided in the vanilla-js package.

Example

import { StytchProvider } from '@stytch/react';
import { StytchUIClient } from '@stytch/vanilla-js';

const stytch = new StytchUIClient('PUBLIC_TOKEN');

// Wrap your App in the StytchProvider
ReactDOM.render(
  <StytchProvider stytch={stytch}>
    <App />
  </StytchProvider>,
  document.getElementById('root'),
);

Example apps

Demo app

React app that shows all the functionality available in the SDK


HTML + Express.js

Email magic links using stytch.js


React + Express.js

Email magic links using stytch-react


Next.js

Email magic links, OAuth, SMS OTP, and more using stytch-react


UI customization

The JavaScript SDK provides the option for you to use pre-built login flows.

Customize on AuthKitUI config reference
UI customization image

Guides

If you are new to Stytch, the step-by-step guides below will walk you through the process from creating a project with Stytch to going live.



One-time passcodes

One-time passcodes can be sent via email, phone number, or WhatsApp. One-time passcodes allow for a quick and seamless login experience on their own, or can layer on top of another login product like Email magic links to provide extra security as a multi-factor authentication (MFA) method.

Methods

To call these methods, One-time passcodes must be enabled in the SDK Configuration page of the Stytch dashboard.

Login or create via SMS

Wraps Stytch's login_or_create via SMS API endpoint. Call this method to send an SMS passcode to new or existing users.


Method parameters


phone_number*string

Configurationobject

Additional configuration.

expiration_minutesint

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';
export const Login = () => {
  const stytchClient = useStytch();
  const sendPasscode = useCallback(() => {
    stytchClient.otps.sms.loginOrCreate('+12025550162', {
      expiration_minutes: 5,
    });
  }, [stytchClient]);
  return <button onClick={sendPasscode}>Send passcode</button>;
};

RESPONSE

200
{
      "status_code": 200,
      "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
      "method_id": "phone-number-test-d5a3b680-e8a3-40c0-b815-ab79986666d0"
    }

Send via SMS

Wraps Stytch's send via SMS API endpoint. Call this method to send an SMS passcode to existing users.

This method is also used when you need to add a phone number to an existing Stytch User. If there is a currently valid Stytch session, and the user inputs a phone number that does not match one on their Stytch User object, upon successful authentication the new phone number will be added to the existing user. Note, this does expose a potential account enumeration vector, see our article on preventing account enumeration for more details.


Method parameters


phone_number*string

Configurationobject

Additional configuration.

expiration_minutesint

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';
export const Login = () => {
  const stytchClient = useStytch();
  const sendPasscode = useCallback(() => {
    stytchClient.otps.sms.send('+12025550162', {
      expiration_minutes: 5,
    });
  }, [stytchClient]);
  return <button onClick={sendPasscode}>Send passcode</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "method_id": "phone-number-test-d5a3b680-e8a3-40c0-b815-ab79986666d0"
  }

Login or create via email

Wraps Stytch's login_or_create via email API endpoint. Call this method to send an email passcode to new or existing users.


Method parameters


email*string

Configurationobject

Additional configuration.

expiration_minutesint
login_template_idstring
signup_template_idstring

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';
export const Login = () => {
  const stytchClient = useStytch();
  const sendPasscode = useCallback(() => {
    stytchClient.otps.email.loginOrCreate('sandbox@stytch.com', {
      expiration_minutes: 5,
    });
  }, [stytchClient]);
  return <button onClick={sendPasscode}>Send passcode</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "method_id": "email-test-81bf03a8-86e1-4d95-bd44-bb3495224953"
  }

Send via email

Wraps Stytch's send via email API endpoint. Call this method to send an email passcode to existing users.

This method is also used when you need to add a phone number to an existing Stytch User. If there is a currently valid Stytch session, and the user inputs a phone number that does not match one on their Stytch User object, upon successful authentication the new phone number will be added to the existing user. Note, this does expose a potential account enumeration vector, see our article on preventing account enumeration for more details.


Method parameters


email*string

Configurationobject

Additional configuration.

expiration_minutesint
login_template_idstring
signup_template_idstring

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';
export const Login = () => {
  const stytchClient = useStytch();
  const sendPasscode = useCallback(() => {
    stytchClient.otps.email.send('sandbox@stytch.com', {
      expiration_minutes: 5,
    });
  }, [stytchClient]);
  return <button onClick={sendPasscode}>Send passcode</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "method_id": "email-test-81bf03a8-86e1-4d95-bd44-bb3495224953"
  }

Login or create via WhatsApp

Wraps Stytch's login_or_create via WhatsApp API endpoint. Call this method to send an WhatsApp passcode to new or existing users.


Method parameters


phone_number*string

Configurationobject

Additional configuration.

expiration_minutesint

Example

React
import { useStytch } from '@stytch/react';
export const Login = () => {
  const stytchClient = useStytch();
  const sendPasscode = useCallback(() => {
    stytchClient.otps.whatsapp.loginOrCreate('+12025550162', {
      expiration_minutes: 5,
    });
  }, [stytchClient]);
  return <button onClick={sendPasscode}>Send passcode</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "method_id": "phone-number-test-d5a3b680-e8a3-40c0-b815-ab79986666d0"
  }

Send via WhatsApp

Wraps Stytch's send via WhatsApp API endpoint. Call this method to send an WhatsApp passcode to existing users.

This method is also used when you need to add a phone number to an existing Stytch User. If there is a currently valid Stytch session, and the user inputs a phone number that does not match one on their Stytch User object, upon successful authentication the new phone number will be added to the existing user. Note, this does expose a potential account enumeration vector, see our article on preventing account enumeration for more details.


Method parameters


phone_number*string

Configurationobject

Additional configuration.

expiration_minutesint

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';
export const Login = () => {
  const stytchClient = useStytch();
  const sendPasscode = useCallback(() => {
    stytchClient.otps.whatsapp.send('+12025550162', {
      expiration_minutes: 5,
    });
  }, [stytchClient]);
  return <button onClick={sendPasscode}>Send passcode</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "method_id": "phone-number-test-d5a3b680-e8a3-40c0-b815-ab79986666d0"
  }

Authenticate

The Authenticate method wraps the authenticate one-time passcode API method which validates the code passed in.

If this method succeeds, the user will be logged in, granted an active session, and the session cookies will be minted and stored in the browser.

You can listen for successful login events anywhere in the codebase with the stytch.session.onChange() method or useStytchSession hook if you are using React.


Method parameters


method_id*string

code*string

Configuration*object

Additional configuration.

session_duration_minutes*string

Example

React
import React, { useCallback, useState } from 'react';
import { useStytch } from '@stytch/react';

export const Authenticate = () => {
  const stytchClient = useStytch();
  const [code, setCode] = useState('');

  const method_id = 'phone-number-test-d5a3b680-e8a3-40c0-b815-ab79986666d0';
  // returned from calling loginOrCreate for OTPs on SMS, WhatsApp or Email

  const authenticate = useCallback(
    (e) => {
      e.preventDefault();
      stytchClient.otps.authenticate(code, method_id, {
        session_duration_minutes: 60,
      });
    },
    [stytchClient, code],
  );

  const handleChange = useCallback((e) => {
    setCode(e.target.value);
  }, []);

  return (
    <form>
      <label for="otp-input">Enter code</label>
      <input id="otp-input" autocomplete="one-time-code" inputtype="numeric" pattern="[0-9]*" onChange={handleChange} />
      <button onClick={authenticate} type="submit">
        Submit
      </button>
    </form>
  );
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    "session_token": "mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q",
    "session_jwt": "eyJ...",
    "session": {...},
    "method_id": "phone-number-test-d5a3b680-e8a3-40c0-b815-ab79986666d0",
  }

UI components

The SDK also comes with a pre-built UI component for our Email Magic Links product. It wraps our login_or_create Email Magic Link API endpoint, which finds an existing user or creates a new user and sends them a magic link via email.

To add Email Magic Links to the login UI, add SDKProductTypes.emailMagicLinks to the products array in the configuration and the appropriate emailMagicLinksOptions.

To see all authentication and customization options, see the UI config section below.

Example

React
import React from 'react';
import { Products } from '@stytch/vanilla-js';
import { StytchLogin } from '@stytch/react';

const config = {
  emailMagicLinksOptions: {
    loginExpirationMinutes: 30,
    loginRedirectURL: 'https://example.com/authenticate',
    signupExpirationMinutes: 30,
    signupRedirectURL: 'https://example.com/authenticate',
  },
  products: [Products.emailMagicLinks],
};

export const Login = () => {
  return <StytchLogin config={config} />;
};

OAuth

OAuth is a popular authentication framework that delegates authentication to an external identity provider (often shortened to IdP) like Google, Facebook, Apple, and Microsoft. A user relies on their membership from that provider to sign in instead of creating another password, and developers can enrich their users' experiences with the information shared by the providers.

The JavaScript SDK provides a pre-built UI for OAuth flows, as well as methods to start and authenticate OAuth flows that you can connect to your own UI. Use either of these approaches to quickly get up and running with OAuth.

Methods

The SDK provides methods that can be used to get the URL to start an OAuth flow and authenticate tokens in the links later.

To call these methods, OAuth must be enabled in the SDK Configuration page of the Stytch dashboard.

Start

The oauth.$provider.start() methods start OAuth flows by redirecting the browser to one of Stytch's oauth start endpoints. The method will also generate a PKCE code_verifier and store it in local storage on the device (See the PKCE OAuth guide for details). If your application is configured to use a custom subdomain with Stytch, it will be used automatically.

  • oauth.amazon.start()
  • oauth.apple.start()
  • oauth.bitbucket.start()
  • oauth.coinbase.start()
  • oauth.discord.start()
  • oauth.facebook.start()
  • oauth.github.start()
  • oauth.gitlab.start()
  • oauth.google.start()
  • oauth.linkedin.start()
  • oauth.microsoft.start()
  • oauth.salesforce.start()
  • oauth.slack.start()
  • oauth.twitch.start()

Method parameters


Configurationobject

Additional configuration.

login_redirect_urlstring
signup_redirect_urlstring
custom_scopesstring

Example

React
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const startOAuth = () =>
    stytchClient.oauth.google.start({
      login_redirect_url: 'https://example.com/authenticate',
      signup_redirect_url: 'https://example.com/authenticate',
      custom_scopes: [
        'https://www.googleapis.com/auth/documents.readonly',
        'https://www.googleapis.com/auth/drive.readonly',
      ],
    });

  return <button onClick={startOAuth}>Log in with Google</button>;
};

Authenticate

The authenticate method wraps the authenticate OAuth API endpoint which validates the OAuth token passed in.

If this method succeeds, the user will be logged in, granted an active session, and the session cookies will be minted and stored in the browser.

You can listen for successful login events anywhere in the codebase with the stytch.session.onChange() method or useStytchSession hook if you are using React.


Method parameters


token*string

Configuration*object

Additional configuration.

session_duration_minutes*string

Example

React
import React, { useEffect } from 'react';
import { useStytch, useStytchSession } from '@stytch/react';

export const Authenticate = () => {
  const stytchClient = useStytch();
  const { session } = useStytchSession();

  useEffect(() => {
    if (session) {
      window.location.href = 'https://example.com/profile';
    } else {
      const token = new URLSearchParams(window.location.search).get('token');
      stytchClient.oauth.authenticate(token, {
        session_duration_minutes: 60,
      });
    }
  }, [stytchClient, session]);

  return <div>Loading</div>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    "session_token": "mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q",
    "session_jwt": "eyJ...",
    "session": {...},
    "provider_subject": "10769150350006150715113082367",
    "provider_type": "Google"
  }

UI components

Our Javascript SDK wraps our start OAuth endpoint which kicks off the OAuth flow for your users. You'll want to set up each OAuth provider in your Dashboard before using it in the SDK. The SDK supports Google, Google One Tap, Amazon, Apple, Bitbucket, Coinbase, Discord, GitHub, GitLab, Facebook, LinkedIn, Microsoft, Salesforce, Slack, and Twitch OAuth.

To add OAuth to the login UI, add SDKProductTypes.oauth to the products array in the configuration and the appropriate oauthOptions.

To see all authentication and customization options, see the UI config section below.

Example

React
import React from 'react';
import { Stytch, SDKProductTypes, OAuthProvidersTypes, OneTapPositions } from '@stytch/stytch-react';

const loginOrSignupViewConfig = {
  oauthOptions: {
    loginRedirectURL: 'https://example.com/authenticate',
    signupRedirectURL: 'https://example.com/authenticate',
    providers: [
      {
        one_tap: true,
        position: OneTapPositions.embedded,
        type: OAuthProvidersTypes.Google,
      },
      {
        type: OAuthProvidersTypes.Amazon,
      },
      {
        type: OAuthProvidersTypes.Apple,
      },
      {
        type: OAuthProvidersTypes.Bitbucket,
      },
      {
        type: OAuthProvidersTypes.Coinbase,
      },
      {
        type: OAuthProvidersTypes.Discord,
      },
      {
        type: OAuthProvidersTypes.Facebook,
        custom_scopes: ['user_photos'],
      },
      {
        type: OAuthProvidersTypes.Github,
        custom_scopes: ['gist'],
      },
      {
        type: OAuthProvidersTypes.GitLab,
      },
      {
        type: OAuthProvidersTypes.LinkedIn,
      },
      {
        type: OAuthProvidersTypes.Microsoft,
        custom_scopes: ['https://graph.microsoft.com/calendars.read'],
      },
      {
        type: OAuthProvidersTypes.Slack,
      },
      {
        type: OAuthProvidersTypes.Twitch,
      },
    ],
  },
  products: [SDKProductTypes.oauth],
};

export const Login = () => {
  const STYTCH_PUBLIC_TOKEN = 'PUBLIC_TOKEN';

  return (
    <div className="sign-in-container">
      <Stytch
        loginOrSignupView={loginOrSignupViewConfig}
        // Include publicToken if you're not using <StytchProvider>
        publicToken={STYTCH_PUBLIC_TOKEN}
      />
    </div>
  );
};

WebAuthn

The Web Authentication API (WebAuthn) is a specification that allows web applications on supported browsers to authenticate a user via authenticator types such as built-in device biometrics (e.g. facial recognition on mobile and fingerprint readers on desktop) or secure hardware keys (e.g. YubiKeys). While WebAuthn has many benefits, developers need to understand the API to implement it securely. Stytch's WebAuthn product simplifies the process by abstracting the implementation details of WebAuthn for developers to make it as quick as possible to implement securely.

Methods

The Stytch SDK can be used to create new WebAuthn registrations for users and authenticate existing WebAuthn registrations.

To call these methods, WebAuthn must be enabled in the SDK Configuration page of the Stytch dashboard.

Register

Wraps Stytch's register_start and register WebAuthn endpoints and the navigator.credentials web API. Call this method to prompt the user to enroll a new WebAuthn factor and save the factor in Stytch.

Call webauthn.register inside an event callback triggered by a user gesture.

You can listen for successful user updates anywhere in the codebase with the stytch.user.onChange() method or useStytchUser() hook if you are using React.

Note: If a user has enrolled another MFA method, this method will require MFA. See the Multi-factor authentication section for more details.


Method parameters


domainstring

authenticator_typestring

Example

React
import React, { useCallback, useEffect, useState } from 'react';
import { useStytch } from '@stytch/stytch-react';

export const Login = () => {
  const stytchClient = useStytch();

  const trigger = useCallback(() => {
    stytchClient.webauthn.register();
  }, [stytchClient]);

  return <button onClick={trigger}>Create WebAuthn Registration</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    "webauthn_registration_id": "webauthn-registration-test-5c44cc6a-8af7-48d6-8da7-ea821342f5a6"
  }

Authenticate

Wraps Stytch's register_start and register WebAuthn endpoints and the navigator.credentials web API. Call this method to prompt the user to enroll a new WebAuthn factor and save the factor in Stytch.

Call webauthn.register inside an event callback triggered by a user gesture.

You can listen for successful user updates anywhere in the codebase with the stytch.user.onChange() method or useStytchUser() hook if you are using React.

Note: If a user has enrolled another MFA method, this method will require MFA. See the Multi-factor authentication section for more details.


Method parameters


domainstring

Configuration*object

Additional configuration.

session_duration_minutes*string

Example

React
import React, { useCallback, useEffect, useState } from 'react';
import { useStytch } from '@stytch/stytch-react';

export const Login = () => {
  const stytchClient = useStytch();

  const trigger = useCallback(() => {
    stytchClient.webauthn.authenticate({
      session_duration_minutes: 60,
    });
  }, [stytchClient]);

  return <button onClick={trigger}>Authenticate WebAuthn Registration</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "session": null
    "session_jwt": "",
    "session_token": "",
    "user": {...},
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    "webauthn_registration_id": "webauthn-registration-test-5c44cc6a-8af7-48d6-8da7-ea821342f5a6",
  }

TOTPs

Time-based One-time Passcodes (TOTPs) are one-time passcodes that are generated based on a shared secret and the current time. TOTPs are also often referred to as Authenticator Apps and are a common form of secondary authentication. Creating a Stytch instance of a TOTP for a User creates a shared secret. This secret is shared by Stytch with the end user's authenticator application of choice (e.g. Google Authenticator). The authenticator app can then generate TOTPs that are valid for a specific amount of time (generally 30 seconds). The end user inputs the TOTP and the developer can use the authenticate method to verify that the TOTP is valid.

Methods

The Stytch SDK can be used to generate new TOTP secrets for users, and authenticate existing TOTP secrets.

To call these methods, TOTPs must be enabled in the SDK Configuration page

Create

Wraps Stytch's create endpoint. Call this method to create a new TOTP instance for a user. The user can use the authenticator application of their choice to scan the QR code or enter the secret.

You can listen for successful user updates anywhere in the codebase with the stytch.user.onChange() method or useStytchUser() hook if you are using React.

Note: If a user has enrolled another MFA method, this method will require MFA. See the Multi-factor authentication section for more details.


Method parameters


expiration_minutesint

Example

React
import React, { useCallback, useEffect, useState } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const trigger = useCallback(() => {
    stytchClient.totps.create({ expiration_minutes: 60 });
  }, [stytchClient]);

  return <button onClick={trigger}>Create TOTP</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "secret": "BTGNX5RKJRMQWQFRQKTG34JCF6XDRHZS",
    "totp_id": "totp-test-41920359-8bbb-4fe8-8fa3-aaa83f35f02c",
    "qr_code": "data:image/png;base64, iVBORw0KGgoAAAANSUhEUgAAAMgAAADIEAAAAADYoy0BAAAG8ElEQVR...8EAAD//7dQP/5Y00bRAAAAAElFTkSuQmCC",
    "recovery_codes": [
    "ckss-2skx-ebow",
    "spbc-424h-usy0",
    "hi08-n5tk-lns5",
    "1n6i-l5na-8axe",
    "aduj-eufq-w6yy",
    "i4l3-dxyt-urmx",
    "ayyi-utb0-gj0s",
    "lz0m-02bi-psbx",
    "l2qm-zrk1-8ujs",
    "c2qd-k7m4-ifmc"
  ]
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    "user": {...},
  }

Authenticate

Wraps Stytch's authenticate endpoint. Call this method to authenticate a TOTP code entered by a user.

If this method succeeds, the user will be logged in, granted an active session, and the session cookies will be minted and stored in the browser.

You can listen for successful login events anywhere in the codebase with the stytch.session.onChange() method or useStytchSession hook if you are using React.


Method parameters


totp_code*string

session_duration_minutes*string

Example

React
import React, { useCallback, useState } from 'react';
import { useStytch } from '@stytch/react';

export const Authenticate = () => {
  const stytchClient = useStytch();
  const [totpCode, setTotpCode] = useState('');

  const authenticate = useCallback(
    (e) => {
      e.preventDefault();
      stytch.totps.authenticate({ totp_code: totpCode, session_duration_minutes: 60 });
    },
    [stytchClient, totpCode],
  );

  const handleChange = useCallback((e) => {
    setTotpCode(e.target.value);
  }, []);

  return (
    <form>
      <label for="totp-input">Enter code</label>
      <input id="totp-input" value={totpCode} onChange={handleChange} />
      <button onClick={authenticate} type="submit">
        Submit
      </button>
    </form>
  );
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "totp_id": "totp-test-41920359-8bbb-4fe8-8fa3-aaa83f35f02c",
    "session": null,
    "session_jwt": "",
    "session_token": "",
    "user": {...},
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6"
  }

Get recovery codes

Wraps Stytch's recovery_codes endpoint. Call this method to retrieve the recovery codes for a TOTP instance tied to a user.

You can listen for successful user updates anywhere in the codebase with the stytch.user.onChange() method or useStytchUser() hook if you are using React.

Note: If a user has enrolled another MFA method, this method will require MFA. See the Multi-factor authentication section for more details.

Example

React
import React, { useCallback, useEffect, useState } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const trigger = useCallback(() => {
    stytchClient.totps.recoveryCodes();
  }, [stytchClient]);

  return <button onClick={trigger}>Get Recovery Codes</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    "totps": [
      {
        "totp_id": "totp-test-41920359-8bbb-4fe8-8fa3-aaa83f35f02c",
        "verified": true,
        "recovery_codes": [
        "ckss-2skx-ebow",
        "spbc-424h-usy0",
        "hi08-n5tk-lns5",
        "1n6i-l5na-8axe",
        "aduj-eufq-w6yy",
        "i4l3-dxyt-urmx",
        "ayyi-utb0-gj0s",
        "lz0m-02bi-psbx",
        "l2qm-zrk1-8ujs",
        "c2qd-k7m4-ifmc"
      ]
      }
    ]
  }

Recover

Wraps Stytch's create endpoint. Call this method to create a new TOTP instance for a user. The user can use the authenticator application of their choice to scan the QR code or enter the secret.

You can listen for successful user updates anywhere in the codebase with the stytch.user.onChange() method or useStytchUser() hook if you are using React.

Note: If a user has enrolled another MFA method, this method will require MFA. See the Multi-factor authentication section for more details.


Method parameters


recovery_code*string

session_duration_minutes*string

Example

React
import React, { useCallback, useState } from 'react';
import { useStytch } from '@stytch/react';

export const Authenticate = () => {
  const stytchClient = useStytch();
  const [recoveryCode, setRecoveryCode] = useState('');

  const recover = useCallback(
    (e) => {
      e.preventDefault();
      stytch.totps.recover({ recovery_code: recoveryCode, session_duration_minutes: 60 });
    },
    [stytchClient, recoveryCode],
  );

  const handleChange = useCallback((e) => {
    setRecoveryCode(e.target.value);
  }, []);

  return (
    <form>
      <label for="recovery-code-input">Enter recovery code</label>
      <input id="recovery-code-input" value={recoveryCode} onChange={handleChange} />
      <button onClick={recover} type="submit">
        Submit
      </button>
    </form>
  );
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "session": null,
    "session_jwt": "",
    "session_token": "",
    "totp_id": "totp-test-41920359-8bbb-4fe8-8fa3-aaa83f35f02c"
    "user": {...},
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
  }

Crypto Wallets

Crypto wallets allow users to hold digital assets, like cryptocurrencies and NFTs, and easily cryptographically authenticate themselves on a blockchain.

Methods

The SDK provides methods that can be used to authenticate a user via their crypto wallet.

To call these methods, Crypto Wallets must be enabled in the SDK configuration page of the Stytch dashboard.

Authenticate start

Wraps Stytch's Crypto Wallet Authenticate Start endpoint. Call this method to prompt the user to sign a challenge using their crypto wallet.

Load the challenge data by calling cryptoWallets.authenticateStart().

You'll then pass this challenge to the user's wallet for signing, you can pass this challenge by using the crypto provider's built-in API and by including the crypto_wallet_address and challenge that is provided from cryptoWallets.authenticateStart(). See Ethereum's EIP-1193 for an example of Ethereum's provider API.


Method parameters


crypto_wallet_type*string

crypto_wallet_address*string

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const trigger = useCallback(async () => {
    /* Request user's address */
    const [crypto_wallet_address] = await ethereum.request({
      method: 'eth_requestAccounts',
    });

    /* Ask Stytch to generate a challenge for the user */
    const { challenge } = await stytchClient.cryptoWallets.authenticateStart({
      crypto_wallet_address,
      crypto_wallet_type: 'ethereum',
    });

    /* Ask the user to sign the challenge, this takes place on your frontend and uses the browser's built-in crypto provider API. */
    const signature = await ethereum.request({
      method: 'personal_sign',
      params: [challenge, crypto_wallet_address],
    });
  });

  /* Send the signature back to Stytch for validation */
  /* await stytchClient.cryptoWallets.authenticate({
      crypto_wallet_address,
      crypto_wallet_type: 'ethereum',
      signature,
      session_duration_minutes: 60,
    });
  }, [stytchClient]); */

  return <button onClick={trigger}>Sign in with Ethereum</button>;
};

RESPONSE

200
{
  "challenge": "Signing in with Project: 7_EPetPqfdEiDCJtgad6-xsXytN3Ee9tx6mdRTQK3fC7-J2PDxpP1GAvYB9Ic4E09h-K88STiRIzKSGP",
  "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141"
  "status_code": 200
}

Authenticate

Wraps Stytch's Crypto Wallet Authenticate Start endpoint. Call this method to prompt the user to sign a challenge using their crypto wallet.

Load the challenge data by calling cryptoWallets.authenticateStart().

You'll then pass this challenge to the user's wallet for signing, you can pass this challenge by using the crypto provider's built-in API and by including the crypto_wallet_address and challenge that is provided from cryptoWallets.authenticateStart(). See Ethereum's EIP-1193 for an example of Ethereum's provider API.


Method parameters


crypto_wallet_type*string

crypto_wallet_address*string

signature*string

session_duration_minutes*string

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const trigger = useCallback(async () => {
    /* Request user's address */
    /* const [crypto_wallet_address] = await ethereum.request({ 
      method: 'eth_requestAccounts',
    }); */

    /* Ask Stytch to generate a challenge for the user */
    /* const { challenge } = await stytchClient.cryptoWallets.authenticateStart({
      crypto_wallet_address,
      crypto_wallet_type: 'ethereum',
    }); */

    /* Ask the user to sign the challenge, this takes place on your frontend and uses the browser's built-in crypto provider API. */
    /* const signature = await ethereum.request({
      method: 'personal_sign', 
      params: [challenge, crypto_wallet_address],
    }); */

    /* Send the signature back to Stytch for validation */
    await stytchClient.cryptoWallets.authenticate({
      crypto_wallet_address,
      crypto_wallet_type: 'ethereum',
      signature,
      session_duration_minutes: 60,
    });
  }, [stytchClient]);

  return <button onClick={trigger}>Sign in with Ethereum</button>;
};

RESPONSE

200
{
  "challenge": "Signing in with Project: 7_EPetPqfdEiDCJtgad6-xsXytN3Ee9tx6mdRTQK3fC7-J2PDxpP1GAvYB9Ic4E09h-K88STiRIzKSGP",
  "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141"
  "status_code": 200
}

UI components

The SDK also comes with a pre-built UI component for our Crypto wallets product. It wraps our authenticate_start and authenticate Crypto wallet API endpoints, which finds an existing user or creates a new user and authenticates them with their wallet.

To add Crypto wallets to the login UI, add SDKProductTypes.crypto to the products array in the configuration.

To see all authentication and customization options, see the UI config section below.

Example

React
import React from 'react';
import { Products } from '@stytch/vanilla-js';
import { StytchLogin } from '@stytch/react';

const config = {
  products: [Products.crypto],
};

export const Login = () => {
  return <StytchLogin config={config} />;
};

Passwords

Stytch supports creating, storing, and authenticating password based users, as well as support for account recovery (password reset) and account deduplication with passwordless login methods.

Methods

The SDK provides methods that can be used to create and authenticate password based users.

To call these methods, Passwords must be enabled in the SDK Configuration page of the Stytch dashboard.

Create

The send method wraps the create Password API endpoint.


Method parameters


email*string

password*string

session_duration_minutes*string

Example

React
import { useCallback } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const createPassword = useCallback(() => {
    stytchClient.passwords.create({
      email: '${exampleEmail}',
      password: '%ON@Nm*SjhElKrS5',
      session_duration_minutes: 60,
    });
  }, [stytchClient]);

  return <button onClick={createPassword}>Create Password</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    "email_id": "email-test-81bf03a8-86e1-4d95-bd44-bb3495224953"
  }

Authenticate

The authenticate method wraps the authenticate Password API endpoint.

If this method succeeds, the user will be logged in, granted an active session, and the session cookies will be minted and stored in the browser.

You can listen for successful login events anywhere in the codebase with the stytch.session.onChange() method or useStytchSession hook if you are using React.


Method parameters


email*string

password*string

session_duration_minutes*string

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const authenticatePassword = useCallback(() => {
    stytchClient.passwords.authenticate({
      email: '${exampleEmail}',
      password: '%ON@Nm*SjhElKrS5',
      session_duration_minutes: 60,
    });
  }, [stytchClient]);

  return <button onClick={authenticatePassword}>Authenticate Password</button>;
};

RESPONSE

200
{
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "session": null,
    "session_jwt": "",
    "session_token": "",
    "status_code": 200,
    "user": {...},
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
  }

Reset by email start

The resetByEmailStart method wraps the reset_by_email_start Password API endpoint.

If this method succeeds, the user will be logged in, granted an active session, and the session cookies will be minted and stored in the browser.

You can listen for successful login events anywhere in the codebase with the stytch.session.onChange() method or useStytchSession hook if you are using React.


Method parameters


email*string

Configurationobject

Additional configuration.

reset_password_redirect_urlstring
login_redirect_urlstring
reset_password_expiration_minutesint
reset_password_template_idstring

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const resetPasswordStart = useCallback(() => {
    stytchClient.passwords.resetByEmailStart({
      email: '${exampleEmail}',
    });
  }, [stytchClient]);

  return <button onClick={resetPasswordStart}>Reset Password Start</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    "email_id": "email-test-81bf03a8-86e1-4d95-bd44-bb3495224953"
  }

Reset by email

The resetByEmail method wraps the reset_by_email Password API endpoint.

If this method succeeds, the user will be logged in, granted an active session, and the session cookies will be minted and stored in the browser.

You can listen for successful login events anywhere in the codebase with the stytch.session.onChange() method or useStytchSession hook if you are using React.


Method parameters


token*string

password*string

session_duration_minutes*string

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const token = new URLSearchParams(window.location.search).get('token');

  const resetPassword = useCallback(() => {
    stytchClient.passwords.resetByEmail({
      token: token,
      password: '%ON@Nm*SjhElKrS5',
      session_duration_minutes: 60,
    });
  }, [stytchClient, token]);

  return <button onClick={resetPassword}>Reset Password</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6"
  }

Reset by existing password

The resetByExistingPassword method wraps the reset_by_existing_password Password API endpoint.

If this method succeeds, the user will be logged in, granted an active session, and the session cookies will be minted and stored in the browser.

You can listen for successful login events anywhere in the codebase with the stytch.session.onChange() method or useStytchSession hook if you are using React.


Method parameters


session_duration_minutes*string

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const resetPassword = useCallback(() => {
    stytch.passwords.resetByExistingPassword({
      existing_password: 'existing_password',
      new_password: '%ON@Nm*SjhElKrS5',
      session_duration_minutes: 60,
    });
  }, [stytchClient]);

  return <button onClick={resetPassword}>Reset Password</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6"
  }

Reset by session

The resetBySession method wraps the reset_by_session Password API endpoint.

If this method succeeds, the user will be logged in, granted an active session, and the session cookies will be minted and stored in the browser.

You can listen for successful login events anywhere in the codebase with the stytch.session.onChange() method or useStytchSession hook if you are using React.


Method parameters


password*string

session_duration_minutes*string

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const resetPassword = useCallback(() => {
    stytchClient.passwords.resetBySession({
      password: '%ON@Nm*SjhElKrS5',
      session_duration_minutes: 60,
    });
  }, [stytchClient]);

  return <button onClick={resetPassword}>Reset Password</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    "session": null
  }

Strength check

This method allows you to check whether or not the user’s provided password is valid, and to provide feedback to the user on how to increase the strength of their password. All passwords must pass the strength requirements to be accepted as valid.

The strengthCheck method wraps the strength_check Password API endpoint.


Method parameters


password*string

emailstring

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const createPassword = useCallback(() => {
    stytchClient.passwords.strengthCheck({
      email: '${exampleEmail}',
      password: '%ON@Nm*SjhElKrS5',
    });
  }, [stytchClient]);

  return <button onClick={strengthCheck}>Strength Check</button>;
};

RESPONSE

200 - LUDS invalid
{
    "breach_detection_on_create": true,
    "breached_password": false,
    "feedback": {
      "suggestions": null,
      "warning": null,
      "has_digit": true,
      "has_lower_case": false,
      "has_symbol": false,
      "has_upper_case": false,
      "missing_characters": 6,
      "missing_complexity": 1
    },
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "score": 0,
    "status_code": 200,
    "strength_policy": "luds",
    "valid_password": false
  }

UI components

The SDK also comes with a pre-built UI component for our Passwords product.

To add passwords to the login UI, add Products.passwords to the products array in the configuration and the appropriate passwordOptions.

To see all authentication and customization options, see the UI config section below.

Example

React
import React from 'react';
import { Products } from '@stytch/vanilla-js';
import { StytchLogin } from '@stytch/react';

const config = {
  passwordOptions: {
    loginExpirationMinutes: 30,
    loginRedirectURL: 'https://example.com/authenticate',
    resetPasswordExpirationMinutes: 30,
    resetPasswordRedirectURL: 'https://example.com/authenticate',
  },
  products: [Products.passwords],
};

export const Login = () => {
  return <StytchLogin config={config} />;
};

There is a separate component for the password reset flow.

The component takes in a passwordResetToken as a prop along with all props the StytchLogin component supports.

To see all authentication and customization options, see the UI config section below.

Example

React
import React from 'react';
import { Products } from '@stytch/vanilla-js';
import { StytchPasswordReset } from '@stytch/react';

const config = {
  passwordOptions: {
    loginExpirationMinutes: 30,
    loginRedirectURL: 'https://example.com/authenticate',
    resetPasswordExpirationMinutes: 30,
    resetPasswordRedirectURL: 'https://example.com/authenticate',
  },
  products: [Products.passwords],
};

export const ResetPassword = () => {
  const passwordResetToken = new URLSearchParams(window.location.search).get('token');
  return <StytchPasswordReset config={config} passwordResetToken={passwordResetToken} />;
};

Users

Once a user has successfully logged in, the SDK can be used to view and manage that user's information, add additional authentication factors, or delete factors that are no longer used.

Methods

To call these methods, Manage user data must be enabled in the SDK Configuration page of the Stytch dashboard.

Get user

The SDK provides two methods for getting a user. The recommended approach is to use the synchronous method, user.getSync, and listen to changes with the user.onChange method.

If logged in, the user.getSync method returns the cached user object. Otherwise it returns null. This method does not refresh the user's data. The stytch-react library provides the useStytchUser hook that implements these methods for you to easily access the user and listen for changes.

The user.onChange method takes in a callback that gets called whenever the user object changes. It returns an unsubscribe method for you to call when you no longer want to listen for such changes.

The asynchronous method, user.get, wraps the get user endpoint. It fetches the user's data and refreshes the cached object if changes are detected. The Stytch SDK will invoke this method automatically in the background, so you probably won't need to call this method directly.

Example

React
import React from 'react';
import { useStytchUser } from '@stytch/react';

export const Home = () => {
  const { user } = useStytchUser();

  return user ? <p>Welcome, {user.name.first_name}</p> : <p>Log in to continue!</p>;
};

Update user

Wraps Stytch's update user endpoint. Use this method to change the user's name, untrusted metadata, and attributes.

You can listen for successful user updates anywhere in the codebase with the stytch.user.onChange() method or useStytchUser() hook if you are using React.

Note: If a user has enrolled another MFA method, this method will require MFA. See the Multi-factor authentication section for more details.


Method parameters


nameobject

untrusted_metadataobject

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const updateName = useCallback(() => {
    stytchClient.user.update({
      name: {
        first_name: 'Jane',
        last_name: 'Doe',
      },
      untrusted_metadata: {
        display_theme: 'DARK_MODE',
      },
    });
  }, [stytchClient]);

  return (
    <>
      <button onClick={updateName}>Update name</button>
    </>
  );
};

RESPONSE

200
{
  "emails": [
    {
      "email_id": "email-test-81bf03a8-86e1-4d95-bd44-bb3495224953",
      "email": "sandbox@stytch.com",
      "verified": false
    }
  ],
  "phone_numbers": [
    {
      "phone_id": "phone-number-test-d5a3b680-e8a3-40c0-b815-ab79986666d0",
      "phone_number": "+12025550162",
      "verified": false
    }
  ],
  "crypto_wallets": [
    {
      "crypto_wallet_id": "crypto-wallet-test-dbbd372e-79f8-48ea-907c-5f0755e7d328",
      "crypto_wallet_address": "0x6df2dB4Fb3DA35d241901Bd53367770BF03123f1",
      "crypto_wallet_type": "ethereum",
      "verified": true
    }
  ],
  "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
  "status_code": 200,
  "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
  "user": {...}
}

Delete authentication factors

Wraps Stytch's delete authentication factors family of endpoints and can be used to remove factors from a user.

These methods cannot be used to remove all factors from a user. A user must have at least one email, phone number, or OAuth provider associated with their account at all times, otherwise they will not be able to log in again.

You can listen for successful user updates anywhere in the codebase with the stytch.user.onChange() method or useStytchUser() hook if you are using React.

Note: If a user has enrolled another MFA method, this method will require MFA. See the Multi-factor authentication section for more details.


Method parameters


method_id*string

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';

export const Login = () => {
  const stytchClient = useStytch();

  const deleteEmail = useCallback(() => {
    stytchClient.user.deleteEmail('email-test-81bf03a8-86e1-4d95-bd44-bb3495224953');
  }, [stytchClient]);

  const deletePhoneNumber = useCallback(() => {
    stytchClient.user.deletePhoneNumber('phone-number-test-d5a3b680-e8a3-40c0-b815-ab79986666d0');
  }, [stytchClient]);

  const deleteWebauthnRegistration = useCallback(() => {
    stytchClient.user.deleteWebauthnRegistration('webauthn-registration-test-5c44cc6a-8af7-48d6-8da7-ea821342f5a6');
  }, [stytchClient]);

  const deleteOAuthRegistration = useCallback(() => {
    stytchClient.user.deleteOAuthRegistration('oauth-user-test-de86770c-911d-463f-80e7-f1b089cead14');
  }, [stytchClient]);

  return (
    <>
      <button onClick={deleteEmail}>Delete email</button>
      <button onClick={deletePhoneNumber}>Delete phone number</button>
      <button onClick={deleteWebauthnRegistration}>Delete WebAuthn registration</button>
      <button onClick={deleteOAuthRegistration}>Delete OAuth registration</button>
    </>
  );
};

RESPONSE

200
{
"status_code": 200,
"request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
"user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
"user": {...}
}

Session management

The SDK may be used to check whether a user has a cached session, view the current session, refresh the session, and revoke the session. To authenticate a session on your backend, you must use either the Stytch API or a Stytch Backend SDK.

Methods

Get session

The SDK provides the session.getSync method to retrieve the current session. The session.onChange method can be used to listen to session changes.

If logged in, the session.getSync method returns the cached session object. Otherwise it returns null. The stytch-react library provides the useStytchSession hook that implements these methods for you to easily access the session and listen for changes.

The session.onChange method takes in a callback that gets called whenever the user object changes. It returns an unsubscribe method for you to call when you no longer want to listen for such changes.

Example

React
import React, { useEffect } from 'react';
import { useStytchSession } from '@stytch/react';

export const withMfaRequired = (Component) => (props) => {
  const { session } = useStytchSession();

  useEffect(() => {
    if (!session || session.authentication_factors.length < 2) {
      window.location.replace('/home');
    }
  }, [session]);

  if (!session || session.authentication_factors.length) {
    return null;
  }

  return <Component {...props} />;
};

Refresh session

Wraps Stytch's authenticate Session endpoint and validates that the session issued to the user is still valid. The SDK will invoke this method automatically in the background. You probably won't need to call this method directly. It's recommended to use session.getSync and session.onChange instead.


Method parameters


Configuration*object

Additional configuration.

session_duration_minutes*string

Example

React
import React, { useEffect } from 'react';
import { useStytch } from '@stytch/react';

export const RefreshSession = () => {
  const stytchClient = useStytch();

  useEffect(() => {
    const refresh = () => {
      if (stytchClient.session.getSync()) {
        stytchClient.session.authenticate({
          session_duration_minutes: 60,
        });
      }
    };
    // Refresh session every 50 minutes
    let interval = setInterval(refresh, 3000000);
    return () => clearInterval(interval);
  }, [stytchClient]);

  return <></>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "session": {
      "attributes": {
        "ip_address": "203.0.113.1",
        "user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"
      },
      "authentication_factors": [
        {
          "delivery_method": "email",
          "email_factor": {
            "email_address": "sandbox@stytch.com",
            "email_id": "email-test-81bf03a8-86e1-4d95-bd44-bb3495224953"
          },
          "last_authenticated_at": "2021-08-09T07:41:52Z",
          "type": "magic_link"
        }
      ],
      "custom_claims": {
        "claim1": "value1",
        "claim2": "value2",
      },
      "expires_at": "2021-08-10T07:41:52Z",
      "last_accessed_at": "2021-08-09T07:41:52Z",
      "session_id": "session-test-fe6c042b-6286-479f-8a4f-b046a6c46509",
      "started_at": "2021-08-09T07:41:52Z",
      "user_id": "user-test-16d9ba61-97a1-4ba4-9720-b03761dc50c6",
    },
    "session_jwt": "example_jwt"
    "session_token": "mZAYn5aLEqKUlZ_Ad9U_fWr38GaAQ1oFAhT8ds245v7Q"
    "user": {...},
  }

Revoke session

Wraps Stytch's revoke Session endpoint and revokes the user's current session. This method should be used to log out a user.

Example

React
import React, { useCallback } from 'react';
import { useStytch } from '@stytch/react';

export const LogOutButton = () => {
  const stytchClient = useStytch();

  const logout = useCallback(() => {
    stytchClient.session.revoke();
  }, [stytchClient]);

  return <button onClick={logout}>Log out</button>;
};

RESPONSE

200
{
    "status_code": 200,
    "request_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141"
  }

Update session

Update a user's session tokens to hydrate a front-end session from the backend. For example, if you log your users in with one of our backend SDKs, you can pass the resulting session_token and session_jwt to this method to prime the frontend SDK with a valid set of tokens. You must then make an authenticate call to authenticate the session tokens and retrieve the user's current session.

Example

React
import React, { useCallback, useEffect } from 'react';
import { useStytch, useStytchUser } from '@stytch/react';

export const App = () => {
  const stytchClient = useStytch();
  const user = useStytchUser();

  useEffect(() => {
    if (user) {
      // redirect to logged in experience
    }
  }, [user]);

  const authenticate = useCallback(() => {
    stytchClient.session.updateSession({
      session_token: 'a session token from your backend',
      session_jwt: 'a session JWT from your backend',
    });

    stytchClient.session.authenticate({ session_duration_minutes: 60 });
  }, [stytchClient]);

  return <button onClick={authenticate}>Hydrate session</button>;
};

UI config


config*object

The config object for login or signup functionality.

products*array
emailMagicLinksOptions*object
oauthOptions*object
otpOptionsobject
sessionOptionsobject
passwordOptions*object

stylesobject

The style object allows you to customize the look of the SDK. You can specify some of them or none at all. We'll use our defaults for the ones you don't specify. Check out the UI customization options in the SDK here.

fontFamilystring
hideHeaderTextboolean
containerobject
colorsobject
buttonsobject
logoobject

callbacksobject

Optional callbacks that are triggered by various events in the SDK. See more details about the callbacks here.

onEvent(data) => void
onError(data) => void

Example

React
import React from "react";
import { StytchLogin } from "@stytch/react";

const Login = () => {
  const style = {
    fontFamily: 'Arial',
  };
  
  const callbacks = {
    onEvent: ({ type, data }) => {
      if (type === 'MAGIC_LINK_LOGIN_OR_CREATE') {
        console.log("Email magic Link sent", data);
      }
    },
    onError: (data) => {
      console.log(data);
    }
  }

  const config = {
    products: ['emailMagicLinks', 'oauth'],
    emailMagicLinksOptions: {
      loginRedirectURL: "https://example.com/authenticate",
      loginExpirationMinutes: 30,
      signupRedirectURL: "https://example.com/authenticate",
      signupExpirationMinutes: 30,
    },
    oauthOptions: {
      providers: [{type: 'google', 'one_tap': true, position: 'floating'}, {type: 'microsoft'}]
    },
  };

  return (
    <div className="sign-in-container">
      <StytchLogin
        config={config}
        styles={style}
        callbacks={callbacks}
      />
    </div>
  );
};

export default Login;

CAPTCHA

CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) is a security measure that attempts to verify that a user is human and not a malicious bot. This helps protect your application against spammy sign ups and other automated bot attacks. Set up CAPTCHA in your Dashboard via our step by step guide and the SDK will protect every login according to your configured threshold. Only Google Enterprise is currently supported, but please contact us if there is a CAPTCHA provider you would like to see supported in the future!

Hiding the reCAPTCHA Badge

When Google Enterprise reCAPTHCA is configured, Google automatically displays a badge in the lower corner of the screen. This badge may be hidden with CSS as long as you include the reCAPTCHA branding visibly in the user flow. See Google's documentation for more details.

.grecaptcha-badge { visibility: hidden; }

If you are using the React SDK with Next.js, the following utility component can be used to programmatically hide the badge on a page by page basis.

import React from 'react';

export const HideRecaptchaBadge = () => (
  <style global jsx>{`
    .grecaptcha-badge {
      visibility: hidden;
    }
  `}</style>
);

Resources

Callbacks

Callbacks are optional functions for the JavaScript SDK that allow you to do things like take actions in your app or send logs to your backend based on where your user is in the flow.

onEvent

A function that is called when the stytch client makes a request. The function expects an argument of an event object, the event object has type and data objects.

{
  "type": "MAGIC_LINK_LOGIN_OR_CREATE",
  "data": {
    "user_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "status_code": 200
  }
},
{
  "type": "OTP_LOGIN_OR_CREATE",
  "data": {
    "user_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "status_code": 200
  }
},
{
  "type": "OTP_AUTHENTICATE",
  "data": {
    "user_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "status_code": 200
  }
},
{
  "type": "CRYPTO_WALLET_AUTHENTICATE_START",
  "data": {
    "user_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "status_code": 200
  }
},
{
  "type": "CRYPTO_WALLET_AUTHENTICATE",
  "data": {
    "user_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "status_code": 200
  }
},
{
  "type": "PASSWORD_CREATE",
  "data": {
    "user_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "status_code": 200
  }
},
{
  "type": "PASSWORD_AUTHENTICATE",
  "data": {
    "user_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "status_code": 200
  }
},
{
  "type": "PASSWORD_RESET_BY_EMAIL_START",
  "data": {
    "user_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "status_code": 200
  }
},
{
  "type": "PASSWORD_RESET_BY_EMAIL",
  "data": {
    "user_id": "request-id-test-b05c992f-ebdc-489d-a754-c7e70ba13141",
    "status_code": 200
  }
}`

onError

A function that is called when an error occurs. The function expects an argument of an StytchError object, the StytchError object has a message property.

  // Example of an API related error.
  "message": "StytchSDKAPIError: [401] unauthorized_credentials Unauthorized credentials. See https://stytch.com/docs/api/errors/401 for more information. request_id: request-id-test-8e2a9758-713e-49a2-8b62-f9169bbabded",
  
  // Example of a network related error.
  "message": "SDKAPIUnreachableError: Failed to send magic link Unable to contact the Stytch servers. Are you online?"

  // Example of a schema related error.
  "message": "StytchSDKSchemaError: [400] Request does not match expected schema. email: should be string"
  
  // Example of an error with using our SDK.
  "message": "StytchSDKUsageError: Invalid call to <METHOD_NAME>"

Cookies & session management

Stytch will automatically save the user's Session in two cookies:

  • 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 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"

Note: If you load the SDK on localhost, we will not mark the cookie as secure.

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.

Validating the opaque session in Node.js / Express.

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,
  env: stytch.envs.test,
});

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

Validating the JWT in Node.js / Express.

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,
  env: stytch.envs.test,
});

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

Overwriting the SDK managed session

In certain cases you may need to manually override the Stytch Session managed by the frontend SDK with a Session available on your backend. A common reason would be when adding custom claims to a Session which is an action that can only be done server-side.

In order to override the SDK managed Session you will need to overwrite the the stytch_session and stytch_session_jwt browser cookies. This can be done by setting the cookies in the response headers from your backend, or by setting the values directly on document.cookie. Be sure to use the same cookie names and properties which are normally set by the SDK.

In most cases, the SDK will automatically detect the new values, and proceed as normal. However, if the SDK is not properly reacting to the updated Session you can force the SDK to refresh the session.

// Call session authentication without any parameters to refresh the session in the SDK
stytchClient.session.authenticate();

Stytch Client Options

The Stytch Client can be configured by passing in an optional object as the second parameter. This currently lets developers configure options related to the cookies set by Stytch's SDK.

Stytch automatically saves the user's session in two cookies: stytch_session that will contain the opaque session token returned from the API and stytch_session_jwtthat will contain the session JWT returned from the API.

import { StytchHeadlessClient } 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: false,
  }
}

const stytchClient = new StytchHeadlessClient(STYTCH_PUBLIC_TOKEN, stytchOptions)

Options

{
 "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",

    /**
     * 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 true.
     */
    "availableToSubdomains": "boolean",
  }
}

Migration Guide

If you are currently using the @stytch/stytch-js or @stytch/stytch-react SDKs, please upgrade to our newest SDK using the guides below.


Migrating to v0.5

Version 0.5.0 introduces an updated styles object used to customize the appearance of the SDK UI. This change introduces many new styling options, and restructures how existing styles are defined.

  • width is now container.width
  • primaryColor is now buttons.primary.backgroundColor
  • primaryTextColor is now colors.primary
  • secondaryTextColor is now colors.secondary
  • Note: that we have also added new buttons.secondary properties which you can check out here.

Values lightGrey and darkGrey do not have direct replacements. Check out all of the new properties we've added here.

Review this pull request to see what migrating our example app from 0.4 to 0.5 looked like.

Migrating to v0.10

Version 0.10.0 of @stytch/vanilla-js introduces our JavaScript SDKs for B2B. Check out in-depth docs for them here

In this version, the default value of availableToSubdomains in StytchClientOptions is now false

SWR & caching

On first load, many websites must make a network request to determine whether a user is logged in before the site can start rendering the user interface. This slows down users' ability to interact with the application and ultimately leaves them with a sluggish experience.

Stytch JavaScript SDK embraces stale-while-revalidate (SWR) - a caching and data fetching strategy that promises faster time-to-interactivity and snappier UX. While SWR is most closely associated with React, the principles can apply to any web application.

Here's how it works:

  • The page first loads. Stytch's SDK checks cached data to determine if a user has logged in previously on the same device, and returns that data to your app immediately.
  • Stytch's SDK refreshes the user's data in the background while your app starts.
  • Your app makes requests to your backend to pull in application-specific data. Your backend validates the session stored in the request's cookies, and then completes the request.
  • In the rare case that the user's session has been terminated from another device, your backend will fail the request and return a 401 error. The Stytch SDK will also notify your app that the session is no longer valid through the useStytchUser and useStytchSession hooks or HOCs.

If a SWR approach isn't right for you, you can explicitly call stytch.user.get() to refresh the user object with a network call, and/or stytch.session.authenticate() to make sure the user is still logged in.

User privacy measures

To guard against potential misuse of the client-side library by bad actors, the SDK has a few restrictions:

  • No user data is shared with the browser until the user has logged in
  • The client may only access data for one user at a time - endpoints like search users are not available
  • Certain endpoints, such as update user, require step-up or multi-factor authentication in order to be used
  • To prevent account enumeration, login or create endpoints for one-time passcodes and magic links do not return the user_id as they would when using the direct API

The JavaScript SDK is not a complete replacement for the Stytch API - they are designed to be used together in order to create secure and low-friction login experiences. Some processes must necessarily happen on your server rather than client (for example, validating a session_token).

Multi-factor authentication

The Stytch SDK allows users to edit the verification mechanisms associated with their account (adding an email, deleting a phone number, adding a second factor method, etc.).

In order to access these routes, we require the that the user be authenticated with a secure combination of factors.

Stytch factors are split into three general groups based on what they prove:

  • Access to another online account or email address (OAuth, email magic links, email passcodes, and embeddable magic links)
  • Access to a phone number (SMS and WhatsApp passcodes)
  • Access to a dedicated 2nd factor (WebAuthn and TOTP)

In order for a session to be considered secure, it must include factors from at least two categories. For example, if a user completes a successful Email magic link flow and a successful SMS passcode flow, they will be considered securely authenticated. A user that completes an Email magic link flow + an OAuth flow with their Google account will not. In addition, at least one factor in the session must be less than an hour old.

Important: If a user does not have enough registered factors, they will always be allowed to add one.