/
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
      Migrating from Stytch Consumer to B2B
      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
      Remembered device flow
    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 Apps
      Overview
      Getting started with the SDK
      Getting started with the API
      Client types
      OAuth scopes
    • Integration Guides

      • Integrate with an Existing Auth System
        MCP Authorization Overview
        Integrate with MCP servers deployed on Cloudflare
        Integrate with MCP servers on Vercel
        Integrate with CLI Apps
        Integrate with AI agents
    • Resources

      • Consent Management
    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
    Trusted Auth Tokens
      Overview
      Getting Started with External IDPs
      Getting Started with Custom Auth Factors
    Device History
      New Device Notifications

    RBAC

    Resources
      Overview
      Role assignment
    Integration Guides
      Start here
      Backend integration
      Headless frontend integration
      (Legacy) 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

/

Authentication

/

Connected Apps

/

Integration Guides

/

Integrate with an Existing Auth System

Add Stytch Connected Apps to an Existing Authentication System

You can use Connected Apps to make your application an OIDC/OAuth2.1 provider without migrating your entire authentication system to the Stytch platform. Any authentication system that issues a JWT access_token or id_token with an email claim can be used here with the help of Trusted Auth Tokens.

When used in this manner, Stytch will be responsible for all OAuth client management, user consent, and token issuance. Your existing authentication system will remain in control of the user's login experience and account information.

Create a Trusted Auth Token Profile

Create a Trusted Auth Token Profile to configure Stytch to accept JWTs issued by your existing Identity Provider. The Trusted Auth Token Profile tells Stytch how to validate these JWTs, and how to map claims like the user's role information to constructs in the Stytch platform.

Keep track of the profile_id created from this step.

2
Add the Stytch Javascript SDK

Install the Javascript SDK to access the Stytch UI component used to handle the OAuth consent flow. The OAuthAuthorize component shown below wraps the IdentityProvider React component. This component will take in a JWT issued by your existing authentication system matching the profile you created above.

The styling and copy of the IdentityProvider UI component can be customized to match your existing application. See available options in the IdentityProvider API reference.

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

const stytch = new StytchUIClient('PUBLIC_TOKEN');

// The Trusted Auth Token Profile ID created in Step 1
const tokenProfileID = "trusted-token-profile-...";

export const OAuthAuthorizeComponent = ({ trustedAuthToken }) => {
  const tokenParams = useMemo(() => ({ trustedAuthToken, tokenProfileID }), 
    [trustedAuthToken]);
  
  return (
    <StytchProvider stytch={stytch}>
      <IdentityProvider trustedAuthTokenParams={tokenParams} />
    </StytchProvider>
  )
}

3
Handle Unauthenticated Users

The OAuth Authorization page takes in numerous arguments from OAuth clients in the form of query parameters. If the user is not logged in, your application should redirect them to your existing login implementation. After login, your application should redirect the user back to the exact same URL - preserving the OAuth query parameters for Stytch to handle.

Your existing auth and routing libraries likely have first-class functionality to do this already - consult their documentation for details.

// If the user is unauthenticated, store the full location to return to
// query parameters and all
export const redirectToLogin = (returnState) => {
  localStorage.setItem('returnTo', returnState);
  window.location.href = '/login'
}

// After the user has authenticated, redirect them back
// into the previous OAuth flow
const onLoginComplete = () => {
  const returnTo = localStorage.getItem('returnTo')
  if (returnTo) {
    localStorage.deleteItem('returnTo');
    window.location.href = returnTo;
  } else {
    window.location.href = '/home';
  }
}

4
Implement the OAuth Authorization Page

Define a new page in your application for handling OAuth Authorization. Most commonly, this page lives at ${yourDomain}/oauth/authorize. OAuth clients will redirect the user to this page to kick off an OAuth login flow.

This page should retrieve the JWT from your existing authentication system and pass it in to the OAuthAuthorizeComponent we defined earlier.

import { useState, useEffect } from 'react';
import { createClient } from '@supabase/supabase-js';
import { OAuthAuthorizeComponent } from './components';

const supabase = createClient(
  'https://<project>.supabase.co', 
  '<sb_publishable_... or anon key>',
);

export default function OAuthAuthorizePage() {
  const [session, setSession] = useState(null)
  useEffect(() => {
    supabase.auth.getSession().
      then(({ data: { session } }) => {
        if(!session) {
          // Redirect to login page
          return redirectToLogin(window.location.href)
        }
        setSession(session);
      })
  }, []);
  
  return session ? 
    <OAuthAuthorizeComponent trustedAuthToken={session.access_token} /> :
    null;
}
import { useState, useEffect } from 'react';
import { getAuth } from "firebase/auth";
import { OAuthAuthorizeComponent } from './components';

const auth = getAuth();

export default function OAuthAuthorizePage() {
  const [token, setToken] = useState(null)
  useEffect(() => {
    if (!auth.currentUser) {
      // Redirect to login page
      return redirectToLogin(window.location.href)
    }
    auth.currentUser.getIdToken().
      then((token) => setToken(session))
  }, []);
  
  return session ? 
    <OAuthAuthorizeComponent trustedAuthToken={token} /> :
    null;
}
import { useState, useEffect } from 'react';
import { fetchAuthSession } from 'aws-amplify/auth';
import { OAuthAuthorizeComponent } from './components';

export default function OAuthAuthorizePage() {
  const [token, setToken] = useState(null)
  useEffect(() => {
    fetchAuthSession()
      .then((session) => setToken(session.tokens.idToken))
      // Redirect to your login page if the user is not logged in
      .catch(err => redirectToLogin(window.location.href))
    
  }, []);
  
  return session ? 
    <OAuthAuthorizeComponent trustedAuthToken={token} /> :
    null;
}
import { useState, useEffect } from 'react';
import { Auth0Client } from '@auth0/auth0-spa-js';
import { OAuthAuthorizeComponent } from './components';

const auth0 = new Auth0Client({
  domain: '{yourDomain}',
  clientId: '{yourClientId}'
});

export default function OAuthAuthorizePage() {
  const [token, setToken] = useState(null)
  useEffect(() => {
    auth0.getIdTokenClaims()
      then((claims) => setToken(claims.__raw))
    // Redirect to your login page if the user is not logged in
    .catch(err => redirectToLogin(window.location.href))
  }, []);
  
  return session ? 
    <OAuthAuthorizeComponent trustedAuthToken={token} /> :
    null;
}

5
Configure the Authorization URL in Stytch

In the Connected Apps section of the Stytch Dashboard, set the Authorization URL to the URL of the page where OAuthAuthorizeComponent is mounted. This will allow Stytch to broadcast the URL to clients using your project's OpenID Connect Endpoint.

Entering the Authorization URL

6
Validate Stytch-issued OAuth Access Tokens

After completion of an OAuth flow, the OAuth client will be granted a Stytch-issued Access Token, and optionally an ID Token. The OAuth client can now use this access token to invoke API endpoints hosted by your application. Use the Stytch Backend SDKs - or any JWT-compatible library - to validate the access token within your existing codebase. Refer to the Authenticate Access Token API docs for a complete reference.

from stytch import Client

client = Client(
    project_id="PROJECT_ID",
    secret="SECRET",
    custom_base_url="${projectDomain}",
)

resp = client.idp.introspect_access_token_local(
    access_token="eyJ...",
)
import * as stytch from 'stytch';

const client = new stytch.Client({
  project_id: 'PROJECT_ID',
  secret: 'SECRET',
  custom_base_url: '${projectDomain}',
});

client.idp.introspectTokenLocal({ token: 'eyJ...' })
  .then((resp) => {
    console.log(resp);
  })
  .catch((err) => {
    console.log(err);
  });
require 'stytch'

client = Stytch::Client.new(
  project_id: 'PROJECT_ID',
  secret: 'SECRET'
  custom_base_url: '${projectDomain}',
)

resp = client.idp.introspect_token_local(
    token="eyJ...",
)

print(resp)
package main

import (
	"context"
	"log"

	"github.com/stytchauth/stytch-go/v16/stytch/consumer/stytchapi"
	"github.com/stytchauth/stytch-go/v16/stytch/consumer/idp"
)

func main() {
	client, err := stytchapi.NewClient(
		"PROJECT_ID",
		"SECRET",
		stytchapi.WithBaseURI("${projectDomain}"),
	)
	if err != nil {
		log.Fatalf("error instantiating client: %v", err)
	}

	resp, err := client.IDP.IntrospectTokenLocal(
	  context.Background(), 
	  &idp.IntrospectTokenLocalParams{
		  Token: token,
	  })
	if err != nil {
		log.Fatalf("error in method call: %v", err)
	}

	log.Println(resp)
}

What's Next

Your application is now an OAuth 2.1 / OIDC Compliant identity provider!

  • Read about OAuth for MCP
  • Learn more about OAuth Scopes in the Stytch platform

Create a Trusted Auth Token Profile

2.

Add the Stytch Javascript SDK

3.

Handle Unauthenticated Users

4.

Implement the OAuth Authorization Page

5.

Configure the Authorization URL in Stytch

6.

Validate Stytch-issued OAuth Access Tokens

What's Next