Before you begin, make sure you’ve completed the OAuth configuration steps.
Overview
- Headless frontend SDK
- Backend SDK
This guide walks through integrating OAuth using Stytch’s headless frontend SDKs. This approach gives you complete control over your UI while handling authentication logic on the frontend.Both and Organization-specific authentication flows are supported.
- Discovery authentication
- Organization-specific authentication
The Discovery flow is designed for situations where end users are signing up or logging in from a central landing page, and have not specified which they are trying to access.
Prerequisites
- Complete the steps in the OAuth configuration guide
- Enable the Frontend SDKs in your Stytch Dashboard
- Enable Create Organizations under “Enabled Methods”
Implementation
Start the OAuth Discovery flow
In your application’s UI, use
oauth.discovery.$provider.start() to allow users to begin the OAuth Discovery flow.Report incorrect code
Copy
Ask AI
import { useStytchB2BClient } from '@stytch/react/b2b';
export const Login = () => {
const stytchClient = useStytchB2BClient();
const startOAuth = () =>
stytchClient.oauth.google.discovery.start();
return <button onClick={startOAuth}>Log in with Google</button>;
};
Handle the OAuth callback
Stytch will send a callback to the Discovery Redirect URL you specified in the Stytch Dashboard. Exchange the token for a list of Discovered Organizations that the user can choose to log into.
Report incorrect code
Copy
Ask AI
import { useEffect } from 'react';
import { useStytchB2BClient, useStytchMemberSession } from '@stytch/react/b2b';
import { useNavigate } from 'react-router';
export const Authenticate = () => {
const stytchClient = useStytchB2BClient();
const { session } = useStytchMemberSession();
const navigate = useNavigate();
useEffect(() => {
if (session) {
navigate('/profile');
} else {
stytchClient.authenticateByUrl({
session_duration_minutes: 60,
});
}
}, [stytchClient, session, navigate]);
return <div>Loading...</div>;
};
An will be returned. The headless SDK will automatically set this in cookies and include it in follow-up calls.
Handle organization selection
When the end user selects an Organization to log into, call the exchange intermediate session method with the selected Organization ID.
Report incorrect code
Copy
Ask AI
import { useEffect } from 'react';
import { useStytchB2BClient } from '@stytch/react/b2b';
export const ExchangeIntermediateSession = () => {
const stytch = useStytchB2BClient();
useEffect(() => {
stytch.discovery.intermediateSessions.exchange({
organization_id: 'organization-test-07971b06-ac8b-4cdb-9c15-63b17e653931'
});
});
return <div>Log In</div>;
};
(Optional) Support organization creation
Allow users to create a new Organization instead of logging into an existing one.
Report incorrect code
Copy
Ask AI
import { useEffect } from 'react';
import { useStytchB2BClient } from '@stytch/react/b2b';
export const CreateOrganization = () => {
const stytch = useStytchB2BClient();
useEffect(() => {
stytch.discovery.organizations.create();
});
return <div>Create Organization</div>;
};
You can optionally prompt the user for the name and slug of their new Organization. If not provided, Stytch will auto-generate them based on the end user’s email address.
If end users login via a page that indicates which Organization they’re trying to access (e.g.,
<org-slug>.your-app.com or your-app.com/team/<org-slug>), you can offer Organization-specific authentication.Prerequisites
- Complete the steps in the OAuth configuration guide
- Enable the Frontend SDKs in your Stytch Dashboard
Implementation
Start the OAuth flow
Use the
oauth.$provider.start() method to initiate the OAuth flow for a specific Organization.Report incorrect code
Copy
Ask AI
import { useStytchB2BClient } from '@stytch/react/b2b';
export const Login = () => {
const stytchClient = useStytchB2BClient();
const startOAuth = () =>
stytchClient.oauth.google.start({
slug: 'your-org-slug'
});
return <button onClick={startOAuth}>Log in with Google</button>;
};
Handle the OAuth callback
Stytch will redirect the user to the Login or Signup Redirect URL. Extract the token from the URL and call the authentication method to finish the login process.
Report incorrect code
Copy
Ask AI
import { useEffect } from 'react';
import { useStytchB2BClient, useStytchMemberSession } from '@stytch/react/b2b';
import { useNavigate } from 'react-router';
export const Authenticate = () => {
const stytchClient = useStytchB2BClient();
const { session } = useStytchMemberSession();
const navigate = useNavigate();
useEffect(() => {
if (session) {
navigate('/profile');
} else {
stytchClient.authenticateByUrl({
session_duration_minutes: 60,
});
}
}, [stytchClient, session]);
return <div>Loading</div>;
};
This guide walks through integrating OAuth using Stytch’s backend SDKs. This approach handles all authentication logic on your backend, giving you complete control over the user experience.Both and Organization-specific authentication flows are supported.
- Discovery authentication
- Organization-specific authentication
The Discovery flow is designed for situations where end users are signing up or logging in from a central landing page, and have not specified which they are trying to access.
Prerequisites
Complete the steps in the OAuth configuration guideImplementation
Configure the callback route
Stytch will make a callback to the Discovery Redirect URL that you specified in the Stytch Dashboard. Handle the callback and authenticate the token.
Python
Report incorrect code
Copy
Ask AI
@app.route("/discovery", methods=["GET"])
def discovery() -> str:
token_type = request.args["stytch_token_type"]
token = request.args["token"]
if token_type != "discovery_oauth":
return "Unsupported auth method"
resp = stytch_client.oauth.discovery.authenticate(discovery_oauth_token=token)
if resp.status_code != 200:
return "Authentication error"
# Store IST as cookie for use in subsequent request to exchange
session['ist'] = resp.intermediate_session_token
orgs = []
for discovered in resp.discovered_organizations:
org = {
"organization_id": discovered.organization.organization_id,
"organization_name": discovered.organization.organization_name,
}
orgs.append(org)
return render_template(
'discoveredOrgs.html',
discovered_organizations=orgs,
email_address=resp.email_address
)
Create organization selection UI
On your frontend, render the list of discovered organizations and allow users to select one. Call the endpoint we’ll setup in the next step with the selected
organization_id.Handle organization selection
Create routes to handle logging into an existing Organization or creating a new Organization.
Report incorrect code
Copy
Ask AI
@app.route("/login/<string:organization_id>", methods=["GET"])
def login_to_org(organization_id):
ist = session.get('ist')
if not ist:
return "No IST found"
resp = stytch_client.discovery.intermediate_sessions.exchange(
intermediate_session_token=ist,
organization_id=organization_id
)
if resp.status_code != 200:
return "Error logging into org"
# Clear IST and set stytch session
session.pop('ist', None)
session['stytch_session'] = resp.session_token
return member.json()
@app.route("/create_org", methods=["GET"])
def create_org() -> str:
ist = session.get('ist')
if not ist:
return "No IST found"
# Created org name and slug will be based on user's email
# Can also prompt end user to provide these
resp = stytch_client.discovery.organizations.create(
intermediate_session_token=ist,
organization_slug='',
organization_name=''
)
if resp.status_code != 200:
return "Error creating org"
# Clear IST and set stytch session
session.pop('ist', None)
session['stytch_session'] = resp.session_token
return member.json()
Initiate OAuth flow
Test the OAuth flow by navigating to the following URL in your browser. Replace This will automatically redirect your browser to the OAuth provider to start the flow.
{provider} with “google” or “microsoft” and {public_token} with your Public Token from the Stytch Dashboard.Report incorrect code
Copy
Ask AI
https://test.stytch.com/v1/public/oauth/{provider}/discovery/start?public_token={public_token}
(Optional) Build login UI
On your frontend, give users the option to start an OAuth flow with a specific provider. For example, if you want to support Google and Microsoft OAuth:
- Add a “Login with Google” button that links to
${apiBase}/v1/public/oauth/google/discovery/start?public_token=${public_token} - Add a “Login with Microsoft” button that links to
${apiBase}/v1/public/oauth/microsoft/discovery/start?public_token=${public_token}
If end users login via a page that indicates which Organization they’re trying to access (e.g.,
<org-slug>.your-app.com or your-app.com/team/<org-slug>), you can offer Organization-specific authentication.Prerequisites
Complete the steps in the OAuth configuration guide, including creating an Organization.Implementation
Configure the callback route
Stytch will make a callback to the Login or Signup Redirect URL. Handle the callback and authenticate the token.
Python
Report incorrect code
Copy
Ask AI
@app.route("/authenticate", methods=["GET"])
def authenticate() -> str:
token_type = request.args["stytch_token_type"]
if token_type == "oauth":
resp = stytch_client.oauth.authenticate(oauth_token=request.args["token"])
if resp.status_code != 200:
return "something went wrong authenticating token"
else:
return "unsupported authentication method"
# Member is successfully logged in
member = resp.member
session["stytch_session"] = resp.session_jwt
return member.json()
Initiate OAuth flow
Test the OAuth flow by navigating to the following URL. Replace This will automatically redirect your browser to the specified OAuth provider to start the flow.
{provider} with “google” or “microsoft”, and use your Public Token and Organization slug.Report incorrect code
Copy
Ask AI
https://test.stytch.com/v1/public/oauth/{provider}/start?slug={organization_slug}&public_token={public_token}
(Optional) Build organization login page
Create a UI that allows end users to identify the Organization they wish to log into and surface all allowed authentication methods.On your frontend, give users the option to start an OAuth flow with a specific provider. For example, if you want to support Google and Microsoft OAuth:
Report incorrect code
Copy
Ask AI
@app.route("/org/<string:slug>", methods=["GET"])
def org_index(slug: str):
# Check for active member session, if present show logged in view
# Otherwise show login screen
resp = stytch_client.organizations.search(query=SearchQuery(operator="AND", operands=[{
"filter_name": "organization_slugs",
"filter_value": [slug]
}]))
if resp.status_code != 200 or len(resp.organizations) == 0:
return "Error fetching org"
organization = resp.organizations[0]
google_allowed = (
organization.auth_methods == "ALL_ALLOWED" or
"google_oauth" in organization.allowed_auth_methods
)
microsoft_allowed = (
organization.auth_methods == "ALL_ALLOWED" or
"microsoft_oauth" in organization.allowed_auth_methods
)
return render_template(
"organizationLogin.html",
public_token=STYTCH_PUBLIC_TOKEN,
api_base=stytch_client.api_base.base_url,
org_name=organization.organization_name,
google_allowed=google_allowed,
microsoft_allowed=microsoft_allowed
)
- Add a “Login with Google” button that links to
${apiBase}/v1/public/oauth/google/discovery/start?slug=${organization_slug}&public_token=${public_token} - Add a “Login with Microsoft” button that links to
${apiBase}/v1/public/oauth/microsoft/discovery/start?slug=${organization_slug}&public_token=${public_token}