Quickstart
Select a framework to start:- Next.js - App
- Next.js - Pages
- React
- Vanilla JS
- Android
- iOS
- React Native
Before you start
- Have a
public_tokenfrom your Stytch project & environment. - Enable and configure Frontend SDKs in your Dashboard.
- Add your application’s domain to your project’s Authorized Domains.
Install the Next.js SDK and configure your API key
- In your Next.js app, run the command to install the SDK:
npm install @stytch/nextjs --save
- Then add your Stytch
public_tokento your project’s.envfile:
NEXT_PUBLIC_STYTCH_PUBLIC_TOKEN=$PUBLIC_TOKEN
Set up a Stytch context provider
- Create a custom
Stytchwrapper component that initializes the Stytch client.
'use client';
import { createStytchB2BClient, StytchB2BProvider } from '@stytch/nextjs/b2b';
const stytchClient = createStytchB2BClient(
process.env.NEXT_PUBLIC_STYTCH_PUBLIC_TOKEN
);
export default function Stytch({ children }: { children: React.ReactNode }) {
return <StytchB2BProvider stytch={stytchClient}>{children}</StytchB2BProvider>;
}
- Wrap your application with
<Stytch>to provide context to all child components:
import Stytch from './components/stytch-provider';
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html>
<body>
<Stytch>{children}</Stytch>
</body>
</html>
);
}
Add <StytchB2B> UI component
- Create a
<StytchB2B>component. - Set authentication methods and relevant options in the config object.
import { AuthFlowType, B2BProducts, StytchB2B } from '@stytch/nextjs/b2b';
const config = {
authFlowType: AuthFlowType.Discovery,
products: [B2BProducts.emailMagicLinks, B2BProducts.oauth],
emailMagicLinksOptions: {
discoveryRedirectURL: 'https://localhost:3000/authenticate',
},
oauthOptions: {
discoveryRedirectURL: 'https://localhost:3000/authenticate',
providers: ['google'],
},
sessionOptions: {
sessionDurationMinutes: 60,
},
};
export const LoginOrSignupDiscoveryForm = () => {
return <StytchB2B config={config} />;
};
Set redirect URLs, if necessary
discoveryRedirectURL to the URL in your app where users are redirected back to after clicking on their email magic link or after completing OAuth:- Using a single route: Set the redirect back to the
/loginroute if you plan on having one shared experience for both the start (login or signup) and end (MFA, organization discovery) of the authentication flow. - Using separate routes: Set the redirect to a new route (e.g.
/authenticate) if you want a different user experience between the start and the end of the authentication flow. For example, a marketing-oriented login page that redirects to a more focused authentication experience for MFA and organization selection.
Add <LoginOrSignupDiscoveryForm> to your login page(s)
- Add
<LoginOrSignupDiscoveryForm>to your/loginpage.
import { useEffect } from 'react';
import { useRouter } from 'next/navigation';
import { useStytchMemberSession } from '@stytch/nextjs/b2b';
import { LoginOrSignupDiscoveryForm } from "src/components/LoginOrSignupDiscoveryForm";
export default function Login() {
const { session, isInitialized } = useStytchMemberSession();
const router = useRouter();
// Route users to your app once they have fully authenticated (either immediately or upon completing the remainder of the auth flow, like MFA)
useEffect(() => {
if (session && isInitialized) {
router.replace("/home");
}
}, [session, isInitialized, router]);
if (!isInitialized || session) {
return <p>Loading...</p>;
}
return <LoginOrSignupDiscoveryForm/>;
}
- If you’re using separate routes, add
<LoginOrSignupDiscoveryForm>to your/authenticateredirect route as well, e.g.app/authenticate/page.tsxorpages/authenticate.tsx.
Handle session and member data
<StytchB2B> component automatically exchanges their intermediate_session_token for a fully minted session_token and session_jwt, both of which are stored in browser cookies.At this point, you can retrieve Session data and Member data via the SDK. For example, useStytchMemberSession() lets you easily check for an active session.Before you start
- Have a
public_tokenfrom your Stytch project & environment. - Enable and configure Frontend SDKs in your Dashboard.
- Add your application’s domain to your project’s Authorized Domains.
Install the Next.js SDK and configure your API key
- In your Next.js app, run the command to install the SDK:
npm install @stytch/nextjs --save
- Then add your Stytch
public_tokento your project’s.envfile:
NEXT_PUBLIC_STYTCH_PUBLIC_TOKEN=$PUBLIC_TOKEN
Wrap your application in <StytchB2BProvider>
- Initialize the Stytch client through
createStytchB2BClient(). - Pass the Stytch client to the
<StytchB2BProvider>component at the root of your application, making it accessible to all child components.
// For Page Router setups
import { createStytchB2BClient, StytchB2BProvider } from '@stytch/nextjs/b2b';
const stytch = createStytchB2BClient(process.env.NEXT_PUBLIC_STYTCH_PUBLIC_TOKEN!);
export default function MyApp({ Component, pageProps }: AppProps) {
return (
<StytchProvider stytch={stytch}>
<Component {...pageProps} />
</StytchProvider>
);
}
Add <StytchB2B> UI component
- Create a
<StytchB2B>component. - Set authentication methods and relevant options in the config object.
import { StytchB2B } from '@stytch/nextjs/b2b';
import { AuthFlowType, B2BProducts } from '@stytch/vanilla-js/b2b';
const config = {
authFlowType: AuthFlowType.Discovery,
products: [B2BProducts.emailMagicLinks, B2BProducts.oauth],
emailMagicLinksOptions: {
discoveryRedirectURL: 'https://localhost:3000/authenticate',
},
oauthOptions: {
discoveryRedirectURL: 'https://localhost:3000/authenticate',
providers: ['google'],
},
sessionOptions: {
sessionDurationMinutes: 60,
},
};
export const LoginOrSignupDiscoveryForm = () => {
return <StytchB2B config={config} />;
};
Set redirect URLs, if necessary
discoveryRedirectURL to the URL in your app where users are redirected back to after clicking on their email magic link or after completing OAuth:- Using a single route: Set the redirect back to the
/loginroute if you plan on having one shared experience for both the start (login or signup) and end (MFA, organization discovery) of the authentication flow. - Using separate routes: Set the redirect to a new route (e.g.
/authenticate) if you want a different user experience between the start and the end of the authentication flow. For example, a marketing-oriented login page that redirects to a more focused authentication experience for MFA and organization selection.
Add <LoginOrSignupDiscoveryForm> to your login page(s)
- Add
<LoginOrSignupDiscoveryForm>to your/loginpage.
import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { useStytchMemberSession } from '@stytch/nextjs/b2b';
import { LoginOrSignupDiscoveryForm } from "src/components/LoginOrSignupDiscoveryForm";
export default function Login() {
const { session, isInitialized } = useStytchMemberSession();
const router = useRouter();
// Routes users to your app once they have fully authenticated (either immediately or upon completing the remainder of the auth flow, like MFA)
useEffect(() => {
if (session && isInitialized) {
router.replace("/home");
}
}, [session, isInitialized, router]);
if (!isInitialized || session) {
return <p>Loading...</p>;
}
return <LoginOrSignupDiscoveryForm/>;
}
- If you’re using separate routes, add
<LoginOrSignupDiscoveryForm>to your/authenticateredirect route as well, e.g.app/authenticate/page.tsxorpages/authenticate.tsx.
Handle session and member data
<StytchB2B> component automatically exchanges their intermediate_session_token for a fully minted session_token and session_jwt, both of which are stored in browser cookies.At this point, you can retrieve Session data and Member data via the SDK. For example, useStytchMemberSession() lets you easily check for an active session.Before you start
- Have a
public_tokenfrom your Stytch project & environment. - Enable and configure Frontend SDKs in your Dashboard.
- Add your application’s domain to your project’s Authorized Domains.
Install the React SDK and configure your API key
npm install @stytch/react --save
Wrap your application in <StytchB2BProvider>
- Initialize the Stytch client through
createStytchB2BClient(). - Pass the Stytch client to the
<StytchB2BProvider>component at the root of your application, making it accessible to all child components.
import { createStytchB2BClient, StytchB2BProvider } from '@stytch/react/b2b';
const stytch = createStytchB2BClient($YOUR_PUBLIC_KEY);
// Add the component at the root of your application
export function App() {
return (
<StytchB2BProvider stytch={stytch}>
{/* Your app code */}
</StytchB2BProvider>
);
}
Add <StytchB2B> UI component
- Create a
<StytchB2B>component. - Set authentication methods and relevant options in the config object.
import { AuthFlowType, B2BProducts, StytchB2B } from '@stytch/react/b2b';
const config = {
authFlowType: AuthFlowType.Discovery,
products: [B2BProducts.emailMagicLinks, B2BProducts.oauth],
emailMagicLinksOptions: {
discoveryRedirectURL: 'https://localhost:3000/authenticate',
},
oauthOptions: {
discoveryRedirectURL: 'https://localhost:3000/authenticate',
providers: ['google'],
},
sessionOptions: { sessionDurationMinutes: 60 },
};
const LoginOrSignup = () => {
return <StytchB2B config={config} />;
};
Set redirect URLs, if necessary
discoveryRedirectURL to the URL in your app where users are redirected back to after clicking on their email magic link or after completing OAuth:- Using a single route: Set the redirect back to the
/loginroute if you plan on having one shared experience for both the start (login or signup) and end (MFA, organization discovery) of the authentication flow. - Using separate routes: Set the redirect to a new route (e.g.
/authenticate) if you want a different user experience between the start and the end of the authentication flow. For example, a marketing-oriented login page that redirects to a more focused authentication experience for MFA and organization selection.
Add <LoginOrSignup> to your login page(s)
- Add
<LoginOrSignup>to your/loginpage:
import { useStytchMemberSession } from "@stytch/react/b2b";
import { Navigate } from "react-router";
import { LoginOrSignup } from "./LoginOrSignup";
export const Login = () => {
const { session } = useStytchMemberSession();
// Route users to your app once they have fully authenticated (either immediately or upon completing the remainder of the auth flow, like MFA)
if (session) {
return <Navigate to="/home" />;
}
return <LoginOrSignup />;
};
- If you’re using separate routes, add
<LoginOrSignup>to your/authenticateredirect route as well, e.g.Authenticate.tsx.
Handle session and member data
<StytchB2B> component automatically exchanges their intermediate_session_token for a fully minted session_token and session_jwt, both of which are stored in browser cookies.At this point, you can retrieve Session data and Member data via the SDK. For example, useStytchMemberSession() lets you easily check for an active session.Example app
Web demo
SDK reference
Before you start
- Have a
public_tokenfrom your Stytch project & environment. - Enable and configure Frontend SDKs in your Dashboard.
- Add your application’s domain to your project’s Authorized Domains.
Install the JS SDK and configure your API key
npm install @stytch/vanilla-js --save
Initialize the Stytch client for your app
- Initialize the Stytch client through
createStytchB2BClient(). - Export the initialized client as
stytchso it can be used across your app.
import { createStytchB2BClient } from "@stytch/vanilla-js/b2b";
export const stytch = createStytchB2BClient($YOUR_PUBLIC_KEY);
Mount the Stytch UI components
- Create a
login.jsfile to initialize and mountstytch. - Set authentication methods and relevant options in the config object.
import { B2BProducts, StytchB2B } from '@stytch/vanilla-js/b2b'
import { stytch } from "./stytch-client.js";
// Stytch SDK method to get the current session synchronously
const session = stytch.session.getSync();
if (session) {
// User already has a session, redirect to your app
window.location.href = "/home";
return;
}
// Register the stytch-ui custom element
customElements.define('stytch-ui', StytchB2B);
// Pass in the Stytch client and configuration
const login = document.getElementById('stytch-ui');
login.render({
client: stytch,
config: {
authFlowType: "Discovery",
products: [B2BProducts.emailMagicLinks, B2BProducts.oauth],
sessionOptions: { sessionDurationMinutes: 60 },
emailMagicLinks: {
discoveryRedirectURL: "https://localhost:3000/authenticate",
},
oauthOptions: {
discoveryRedirectURL: "https://localhost:3000/authenticate",
providers: [{ type: "google" }],
},
},
});
Set redirect URLs, if necessary
discoveryRedirectURL to the URL in your app where users are redirected back to after clicking on their email magic link or after completing OAuth:- Using a single route: Set the redirect back to the
/loginroute if you plan on having one shared experience for both the start (login or signup) and end (MFA, organization discovery) of the authentication flow. - Using separate routes: Set the redirect to a new route (e.g.
/authenticate) if you want a different user experience between the start and the end of the authentication flow. For example, a marketing-oriented login page that redirects to a more focused authentication experience for MFA and organization selection.
Add Stytch UI on your login page(s)
- Add
<stytch-ui>on your/loginpage:
<!DOCTYPE html>
<html lang="en">
<head>...</head>
<body>
<stytch-ui id="stytch-ui" />
<script type="module" src="js/login.js"></script>
</body>
</html>
- If you’re using separate routes, add
<stytch-ui>on your/authenticateredirect route as well, e.g.authenticate.html.
Handle session and member data
intermediate_session_token for a fully minted session_token and session_jwt, both of which are stored in browser cookies.At this point, you can retrieve Session data and Member data via the SDK. For example, session.getSync() lets you retrieve the current session and can be used to determine if a user is already logged in.Before you start
- Have a
public_tokenfrom your Stytch project & environment. - Enable and configure Frontend SDKs in your Dashboard.
- Add your application’s application ID to your project’s Authorized bundle & application IDs.
- The Stytch Android SDK automatically handles deeplinks in the pre-built UI flow (used below). You must add the following URLs to your project’s Redirect URLs in the Dashboard:
[YOUR_PUBLIC_TOKEN]://b2b-ui[YOUR_PUBLIC_TOKEN]://oauth
Install the Android SDK and configure your API key
- The Stytch Android SDK is published on Maven Central at
com.stytch.sdk:sdk - The latest version can be found here
- Make sure
mavenCentral()is added to the repository configuration in yoursettings.gradle.ktsfile:
dependencyResolutionManagement {
repositories {
mavenCentral()
}
}
- Add the Stytch Android SDK to your application’s
build.gradle.ktsdependencies block:
dependencies {
implementation("com.stytch.sdk:sdk:$STYTCH_SDK_VERSION")
}
- Add your
public_tokenas a string resource. This will enable the SDK to automatically configure itself, including any necessary deeplinks.
As XML
As XML
<resources>
<string name="STYTCH_PUBLIC_TOKEN">public-token-test-...</string>
</resources>
As code
As code
android {
defaultConfig {
resValue("string", "STYTCH_PUBLIC_TOKEN", "\"${System.getenv("STYTCH_PUBLIC_TOKEN")}\"")
}
}
Initialize the Stytch B2B client for your app
StytchB2BClient.configure() method.Note: Be sure to pass an application context to this method to prevent potential memory leaks. The below examples show how to do this from either an Application or Activity class. You will only choose one approach that is appropriate for your situation.From an application class (preferred)
From an application class (preferred)
class MainApplication : Application() {
override fun onCreate() {
super.onCreate()
StytchB2BClient.configure(this)
}
}
From an activity class (alternate)
From an activity class (alternate)
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
StytchB2BClient.configure(applicationContext)
}
}
Create the StytchB2BUI client
StytchB2BUI instance using the familiar Builder pattern, configured to your needs. Below, we will be enabling Email magic links and Google OAuth:val stytchUIClient = StytchB2BUI.Builder().apply {
activity(this@MainActivity)
productConfig(
StytchB2BProductConfig(
authFlowType = AuthFlowType.DISCOVERY,
products = listOf(StytchB2BProduct.EMAIL_MAGIC_LINKS, StytchB2BProduct.OAUTH),
oauthOptions = B2BOAuthOptions(
providers = listOf(B2BOAuthProviderConfig(B2BOAuthProviders.GOOGLE))
)
),
)
onAuthenticated(::onAuthenticated)
}.build()
private fun onAuthenticated(result: AuthenticationResult) {
when (result) {
is AuthenticationResult.Authenticated -> println("Member successfully authenticated")
is AuthenticationResult.Error -> println(result.error)
}
}
Launch the authentication flow
authenticate() method from your UI. Below, we are launching the authentication flow from a button press in a compose application:Button(onClick = stytchUIClient::authenticate) {
Text("Log in")
}
Handle session and member data
intermediate_session_token for a fully minted session_token and session_jwt, all of which are stored encrypted on device.At this point, you can retrieve Session data and Member data via the SDK.We recommend listening to session/member/organization changes from the appropriate flows in your view model:class MainViewModel : ViewModel() {
val uiState =
combine(
StytchB2BClient.isInitialized,
StytchB2BClient.member.onChange,
StytchB2BClient.sessions.onChange,
) { isInitialized, memberData, sessionData ->
val memberIsAvailable = memberData is StytchObjectInfo.Available
val sessionIsAvailable = sessionData is StytchObjectInfo.Available
when {
!isInitialized -> AppUIState.Loading
isInitialized && memberIsAvailable && sessionIsAvailable -> AppUIState.LoggedIn(
memberData = memberData.value,
sessionData = sessionData.value,
)
else -> AppUIState.LoggedOut
}
}
.stateIn(
viewModelScope,
SharingStarted.WhileSubscribed(5000),
AppUIState.Loading,
)
}
Before you start
- Have a
public_tokenfrom your Stytch project & environment. - Enable and configure Frontend SDKs in your Dashboard.
- Add your application’s Bundle ID to your project’s Authorized bundle & application IDs.
- You must add the following URL to your project’s Redirect URLs in the Dashboard:
stytchui-[YOUR_PUBLIC_TOKEN]://deeplink
Install the iOS SDK and configure your API key
- Add a new package package dependency pointing at our GitHub repository
- In your project Build Settings, under
Other Linker Flags, add-ObjC
Configure your application to handle Stytch UI deeplinks
Info.plist<dict>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>stytchui-YOUR_PUBLIC_TOKEN</string>
</array>
</dict>
</array>
</dict>
Configure StytchB2BUIClient
StytchB2BUIClient with your desired options. We recommend doing so in your viewmodel.Below, we will be enabling Email magic links and Google OAuth:class ContentViewModel: ObservableObject {
@Published var stytchB2BUIConfiguration: StytchB2BUIClient.Configuration = .init(
stytchClientConfiguration: StytchClientConfiguration(publicToken: [YOUR_PUBLIC_TOKEN], defaultSessionDuration: 5),
products: [.emailMagicLinks, .oauth],
authFlowType: .discovery,
oauthProviders: [.init(provider: .google)],
)
init() {
...
StytchB2BUIClient.configure(configuration: stytchB2BUIConfiguration)
...
}
}
Launch the authentication flow
- Add the following published properties to your viewmodel:
class ContentViewModel: ObservableObject {
@Published var isAuthenticated: Bool = false
@Published var isAuthenticationPresented: Bool = false
}
- Define a deeplink helper method (also in the viewmodel):
func handleOpenURL(_ url: URL) {
isAuthenticationPresented = true
let didHandle = StytchB2BUIClient.handle(url: url)
print("StytchUIClient didHandle: \(didHandle) - url: \(url)")
}
- Pass the new
isAuthenticationPresentedproperty to theb2bAuthenticationSheet()method in your UI, and intercept links:
var body: some View {
VStack {
if viewModel.isAuthenticated {
// Your Authenticated UI
} else {
// Your Unauthenticated UI
// toggle $viewModel.isAuthenticationPresented to toggle the authentication flow
}
}
.b2bAuthenticationSheet(configuration: viewModel.stytchB2BUIConfiguration, isPresented: $viewModel.isAuthenticationPresented)
.onOpenURL { url in
viewModel.handleOpenURL(url)
}
}
Handle session and member data
intermediate_session_token for a fully minted session_token and session_jwt, all of which are stored encrypted on device.At this point, you can retrieve Session data and Member data via the SDK.We recommend listening to session/member/organization changes from the appropriate observables in your view model:class ContentViewModel: ObservableObject {
private var cancellables = Set<AnyCancellable>()
init() {
...
startObservables()
...
}
func startObservables() {
StytchB2BUIClient.dismissUI
.receive(on: DispatchQueue.main)
.sink { [weak self] in
self?.isAuthenticationPresented = false
}
.store(in: &cancellables)
StytchB2BUIClient.errorPublisher
.receive(on: DispatchQueue.main)
.sink { error in
print("Error from StytchB2BUIClient:")
print(error.errorInfo)
}
.store(in: &cancellables)
StytchB2BClient.isInitialized
.receive(on: DispatchQueue.main)
.sink { isInitialized in
print("isInitialized: \(isInitialized)")
}
.store(in: &cancellables)
StytchB2BClient.sessions.onMemberSessionChange
.receive(on: DispatchQueue.main)
.sink { [weak self] memberSessionInfo in
switch memberSessionInfo {
case let .available(memberSession, lastValidatedAtDate):
print("Session Available: \(memberSession.expiresAt) - lastValidatedAtDate: \(lastValidatedAtDate)\n")
print("member: \(String(describing: StytchB2BClient.member.getSync()))")
print("organization: \(String(describing: StytchB2BClient.organizations.getSync()))")
self?.isAuthenticated = true
case .unavailable:
print("Session Unavailable\n")
self?.isAuthenticated = false
}
}
.store(in: &cancellables)
Before you start
- Have a
public_tokenfrom your Stytch project & environment. - Enable and configure Frontend SDKs in your Dashboard.
- Add your application’s Bundle ID (iOS) and Application ID (Android) to your project’s Authorized bundle & application IDs.
- You must add the following URL to your project’s Redirect URLs in the Dashboard:
stytch-ui-[YOUR_PUBLIC_TOKEN]://deeplink
Install the React Native SDK
@stytch/react-native.npm install @stytch/react-native @stytch/react-native-inappbrowser-reborn --save
Configure your application to handle Stytch UI deeplinks
stytch-ui-[YOUR_PUBLIC_TOKEN]. How you do that will depend on your supported platforms and whether you are using bare React Native or Expo.NOTE: If you are using Expo Router, which is the default for new apps created with create-expo-app, you must add a +native-intent.tsx, file which ignores routing for the incoming Stytch UI deep links. An example of this can be found here.Configure the StytchB2BClient
StytchB2BClient with your public_token, and wrap your app in the StytchB2BProvider component:const publicToken = process.env.EXPO_PUBLIC_STYTCH_PUBLIC_TOKEN ?? '';
const stytch = new StytchB2BClient(publicToken);
export default function RootLayout() {
return (
<StytchB2BProvider stytch={stytch}>
<YourApp>
</StytchB2BProvider>
);
}
Authenticate a member
- Define your desired configuration for the authentication flow. Below, we will be enabling Email magic links and Google OAuth:
const config: StytchRNB2BUIConfig = {
productConfig: {
products: [B2BProducts.emailMagicLinks, B2BProducts.oauth],
oauthOptions: { providers: [B2BOAuthProviders.Google] },
authFlowType: AuthFlowType.Discovery,
},
};
- Display the authentication flow, and listen to the callbacks to determine when a member is fully authenticated:
export default function LoginScreen() {
const stytch = useStytchB2BClient();
const callbacks: Callbacks = {
onEvent(event) {
if (event.type == StytchEventType.AuthenticateFlowComplete) {
// navigate to a protected resource
}
},
onError(error) {
console.log('onError called: ', error.message);
},
};
<StytchB2BUI client={stytch} config={config}></StytchB2BUI>;
}
Handle session and member data
intermediate_session_token for a fully minted session_token and session_jwt, all of which are stored encrypted on device.At this point, you can retrieve Session data and Member data via the SDK. For example, useStytchMemberSession() lets you easily check for an active session.Next steps
- Authentication methods
- Session management