/
Contact usSee pricingStart building
Node
​

    About Stytch

    Introduction
    Integration Approaches
      Full-stack overview
      Frontend (pre-built UI)
      Frontend (headless)
      Backend
    Migrations
      Migration overview
      Migrating users statically
      Migrating users dynamically
      Additional migration considerations
      Zero-downtime deployment
      Defining external IDs for users
      Exporting from Stytch
    Custom Domains
      Overview

    Authentication

    DFP Protected Auth
      Overview
      Setting up DFP Protected Auth
      Handling challenges
    Magic Links
    • Email Magic Links

      • Getting started with the API
        Getting started with the SDK
        Replacing your password reset flow
        Building an invite user flow
        Add magic links to an existing auth flow
        Adding PKCE to a Magic Link flow
        Magic Link redirect routing
    • Embeddable Magic Links

      • Getting started with the API
    MFA
      Overview
      Backend integration
      Frontend integration
    Mobile Biometrics
      Overview
    M2M Authentication
      Authenticate an M2M Client
      Rotate client secrets
      Import M2M Clients from Auth0
    OAuth
    • Identity providers

      • Overview
        Provider setup
      Getting started with the API (Google)
      Add Google One Tap via the SDK
      Email address behavior
      Adding PKCE to an OAuth flow
    Connected AppsBeta
      Setting up Connected Apps
      About Remote MCP Servers
    • Resources

      • Integrate with AI agents
        Integrate with MCP servers
        Integrate with CLI Apps
    Passcodes
      Getting started with the API
      Getting started with the SDK
    • Toll fraud

      • What is SMS toll fraud?
        How you can prevent toll fraud
      Unsupported countries
    Passkeys & WebAuthn
    • Passkeys

      • Passkeys overview
        Set up Passkeys with the frontend SDK
    • WebAuthn

      • Getting started with the API
        Getting started with the SDK
    Passwords
      Getting started with the API
      Getting started with the SDK
      Password strength policy
    • Email verification

      • Overview
        Email verification before password creation
        Email verification after password creation
    Sessions
      How to use sessions
      Backend integrations
      Frontend integrations
      Custom claims
      Custom claim templates
      Session tokens vs JWTs
      How to use Stytch JWTs
    TOTP
      Getting started with the API
      Getting started with the SDK
    Web3
      Getting started with the API
      Getting started with the SDK

    Authorization

    Implement RBAC with metadata

    3rd Party Integrations

    Planetscale
    Supabase
    Feathery
    Unit

    Testing

    E2E testing
    Sandbox values
Get support on SlackVisit our developer forum

Contact us

Consumer Authentication

/

Guides

/

About Stytch

/

Integration Approaches

/

Backend

Stytch and backend development

Our backend API and SDKs integrate tightly with your application's server-side logic for maximum code control and flexibility. Because of its API-first design, Stytch’s backend integration enables you to customize and control auth flows with precision. This guide covers the fundamental aspects and key considerations when implementing Stytch on your backend.

Here’s a list of libraries and options we offer for backend development:

  • Backend API
  • Backend SDKs
    • Go SDK
    • Python SDK
    • Node.js SDK
    • Ruby SDK
    • Java SDK

Refer to the backend API reference page, where you can select the language and backend SDK of your preference, for the full documentation. You can also explore the example apps to get hands-on with the code.

Overview

Backend implementation diagram

At a high-level, implementing Stytch server-side involves the following steps:

  1. Your backend collects all necessary authentication data (e.g., IDs, tokens, emails, and metadata) and calls the Stytch API to perform a specific auth-related operation (e.g., initiate an auth flow, retrieve a user record, and refresh a session).
  2. Stytch API processes the request and returns a response with pertinent data (e.g., minted session, user data, auth metadata, and statuses).
  3. Your backend handles the response and transforms the data as needed, which may involve calling the Stytch API again, passing the data to a different backend or microservice, or relaying data back to your frontend.

As the most feature-complete and flexible option, our backend API and SDKs enable you to tightly integrate Stytch's auth primitives with your application's logic. However, this level of control and customization generally requires you to write more application code.

Code examples

Here are some example code snippets that demonstrate the general idea of implementing Stytch on the backend.

Authentication flows

const stytch = require('stytch');
const stytchClient = new stytch.Client({
  project_id: "PROJECT_ID"
  secret: "SECRET",
});

// Start the authentication flow
app.post("/login-or-signup", async function (req, res) {
  try {
    const params = { email: req.body.email, create_user_as_pending: true };
    const resp = await stytchClient.magicLinks.email.loginOrCreate(params);
    res.status(200).end();
  } catch (err) {
   console.error(err);
   res.status(400).send('Authentication failed');
 }
});

// Complete the authentication flow which mints the session
app.get("/authenticate", async function (req, res) {
  try {
    const params = { token: req.body.token, session_duration_minutes: 60 };
    const resp = await stytchClient.magicLinks.authenticate(params);
    res.cookie("stytch_session_jwt", resp.session_jwt);
    res.redirect('/dashboard');
  } catch (err) {
   console.error(err);
   res.status(401).send('Authentication failed');
 }
});
...

Session management

// Authenticate the session  
async function isAuthenticated(req, res, next) {
  try {
    const sessionJWT = req.cookies.stytch_session_jwt;
    const resp = await stytchClient.sessions.authenticateJWT({session_jwt: sessionJWT});
    req.stytchUser = resp.user;
    next();
  } catch (err) {
   console.error(err);
   res.status(401).send('Authentication failed');
  } 
}

// Protect a route
app.get('/dashboard', isAuthenticated, (req, res) => {
  res.send('Welcome to your dashboard');
});

// Revoke a session
app.get('/logout', async (req, res) => {
  try {
    const sessionJWT = req.cookies.stytch_session_jwt;
    const logout = await stytchClient.sessions.revoke({session_jwt: sessionJWT});
    res.clearCookie("stytch_session_jwt");
    res.redirect('/login');
  } catch (err) {
    console.error(err);
    res.status(400).end();
  }
});
...

User management

// Update user record
app.put('/profile', isAuthenticated, async (req, res) => {
  try { 
    const params = {
      untrusted_metadata: {
         profile_pic_url: req.body["profile_pic_url"],
         display_name: req.body["display_name"]
      },
      trusted_metadata: {
	      billing_address: req.body["billing_address"]
      }
    };
    const resp = await stytchClient.users.update(req.stytchUser.user_id);
    // Update user record in your database
    res.status(200).end();
  } catch (err) {
    console.error(err);
    res.status(401).end();
  }
});

Considerations when using our backend API and SDKs

Hydrating sessions on the frontend

If you’re authenticating users and minting sessions on the backend with Stytch, you can hydrate sessions on your frontend by setting the cookie server-side with the corresponding session_jwt or session_token.

const resp = await stytchClient.magicLinks.authenticate(params);
// Set cookie with the newly minted Stytch session to pass on to your frontend
res.cookie("stytch_session_jwt", resp.session_jwt);
res.cookie("stytch_session", resp.session_token);

If you’re also using our frontend SDKs for session management, you have two options for passing the server-side session into our frontend SDK:

  1. You can set the cookies directly in a similar manner to the code above. It's important to correctly set the cookie names as stytch_session_jwt and stytch_session (or whatever you customized their names to be) and call the sessions.authenticate() method. Our frontend SDKs will then use the new values from these cookies, overwriting any session cookies it might’ve generated previously, and proceed to manage the backend-created session as expected.
  2. We recommend you use the frontend SDK sessions.updateSession method.
stytchClient.session.updateSession({
  session_token: 'a session token from your backend',
  session_jwt: 'a session JWT from your backend',
});

You can read more about session hydration here.

Keeping Stytch and your database in sync

Stytch serves as a datastore for your users' identity records and attributes (e.g. email addresses, phone numbers, metadata, and auth registrations), which you can access via our user management endpoints like the Get User endpoint and the Search Users endpoint. Moreover, Stytch allows you to moderately extend User records with metadata fields that can store custom JSON data specific to your application – which is particularly useful for session authentication and authorization decisions.

However, most applications have their own primary database to store their users' account data. We recommend storing Stytch user_ids in that database in order to associate your internal accounts with their corresponding Stytch User records. Upon receiving a success response from Stytch’s API, your backend should create a new user record or update an existing one in your database when applicable.

What's next

If you have additional questions about our different integration options, please feel free to reach out to us in our community Slack, our developer forum, or at support@stytch.com for further guidance.

Overview

Code examples

Authentication flows

Session management

User management

Considerations when using our backend API and SDKs

Hydrating sessions on the frontend

Keeping Stytch and your database in sync

What's next