Facilitate greater security, easier account management, and accelerated application onboarding and adoption.
The standalone API (covered in this document), is a standalone API for integrating into an existing auth stack.
User Management is a complete authentication platform which includes SSO out of the box.
Single Sign-On is the most frequently asked for requirement by organizations looking to adopt new SaaS applications. SSO enables authentication via an organization’s identity provider (IdP).
This service is compatible with any IdP that supports either the SAML or OIDC protocols. It’s modeled to meet the OAuth 2.0 framework specification, abstracting away the underlying authentication handshakes between different IdPs.
WorkOS SSO API acts as authentication middleware and intentionally does not handle user database management for your application.
In this guide, we’ll take you from learning about Single Sign-On and POC-ing all the way through to authenticating your first user via the WorkOS SSO API.
To get the most out of this guide, you’ll need:
Reference these example apps as you follow this guide.
WorkOS offers native SDKs in several popular programming languages. Choose a language below to see instructions in your application’s language.
Don't see an SDK you need? Contact us to request an SDK!
To make calls to WorkOS, provide the API key and, in some cases, the client ID. Store these values as managed secrets, such as WORKOS_API_KEY
and WORKOS_CLIENT_ID
, and pass them to the SDKs either as environment variables or directly in your app’s configuration based on your preferences.
WORKOS_API_KEY='sk_example_123456789' WORKOS_CLIENT_ID='client_123456789'
The code examples use your staging API keys when signed in
The endpoint to initiate SSO via the WorkOS API is responsible for handing off the rest of the authentication workflow to WorkOS. There are a couple configuration options shown below.
You can use the optional state
parameter to encode arbitrary information to help restore application state between redirects.
Use the organization parameter when authenticating a user by their specific organization. This is the preferred parameter for SAML and OIDC connections.
The example below uses the Test Organization that is available in your staging environment and uses a mock identity provider. It’s created to help you test your SSO integration without having to go through the process of setting up an account with a real identity provider.
import type { NextApiRequest, NextApiResponse } from 'next'; import { WorkOS } from '@workos-inc/node'; const workos = new WorkOS(process.env.WORKOS_API_KEY); const clientId = process.env.WORKOS_CLIENT_ID; export default (_req: NextApiRequest, res: NextApiResponse) => { // Use the Test Organization ID to get started. Replace it with // the user’s real organization ID when you finish the integration. const organization = 'org_test_idp'; // The callback URI WorkOS should redirect to after the authentication const redirectUri = 'https://dashboard.my-app.com'; const authorizationUrl = workos.sso.getAuthorizationUrl({ organization, redirectUri, clientId, }); res.redirect(authorizationUrl); };
const express = require('express'); const { WorkOS } = require('@workos-inc/node'); const app = express(); const workos = new WorkOS(process.env.WORKOS_API_KEY); const clientId = process.env.WORKOS_CLIENT_ID; app.get('/auth', (_req, res) => { // Use the Test Organization ID to get started. Replace it with // the user’s real organization ID when you finish the integration. const organization = 'org_test_idp'; // The callback URI WorkOS should redirect to after the authentication const redirectUri = 'https://dashboard.my-app.com'; const authorizationUrl = workos.sso.getAuthorizationUrl({ organization, redirectUri, clientId, }); res.redirect(authorizationUrl); });
You can also use the connection parameter for SAML or OIDC connections when authenticating a user by their connection ID.
import type { NextApiRequest, NextApiResponse } from 'next'; import { WorkOS } from '@workos-inc/node'; const workos = new WorkOS(process.env.WORKOS_API_KEY); const clientId = process.env.WORKOS_CLIENT_ID; export default (_req: NextApiRequest, res: NextApiResponse) => { // A WorkOS Connection ID const connection = 'connection_123'; // The callback URI WorkOS should redirect to after the authentication const redirectUri = 'https://dashboard.my-app.com'; const authorizationUrl = workos.sso.getAuthorizationUrl({ connection, clientId, redirectUri, }); res.redirect(authorizationUrl); };
const express = require('express'); const { WorkOS } = require('@workos-inc/node'); const app = express(); const workos = new WorkOS(process.env.WORKOS_API_KEY); const clientId = process.env.WORKOS_CLIENT_ID; app.get('/auth', (_req, res) => { // A WorkOS Connection ID const connection = 'connection_123'; // The callback URI WorkOS should redirect to after the authentication const redirectUri = 'https://dashboard.my-app.com'; const authorizationUrl = workos.sso.getAuthorizationUrl({ connection, clientId, redirectUri, }); res.redirect(authorizationUrl); });
The provider parameter is used for OAuth connections which are configured at the environment level.
The supported provider
values are GoogleOAuth
, MicrosoftOAuth
, GitHubOAuth
, and AppleOAuth
.
import type { NextApiRequest, NextApiResponse } from 'next'; import { WorkOS } from '@workos-inc/node'; const workos = new WorkOS(process.env.WORKOS_API_KEY); const clientId = process.env.WORKOS_CLIENT_ID; export default (_req: NextApiRequest, res: NextApiResponse) => { // The provider to authenticate with const provider = 'GoogleOAuth'; // The callback URI WorkOS should redirect to after the authentication const redirectUri = 'https://dashboard.my-app.com'; const authorizationUrl = workos.sso.getAuthorizationUrl({ provider, redirectUri, clientId, }); res.redirect(authorizationUrl); };
const express = require('express'); const { WorkOS } = require('@workos-inc/node'); const app = express(); const workos = new WorkOS(process.env.WORKOS_API_KEY); const clientId = process.env.WORKOS_CLIENT_ID; app.get('/auth', (_req, res) => { // The provider to authenticate with const provider = 'GoogleOAuth'; // The callback URI WorkOS should redirect to after the authentication const redirectUri = 'https://dashboard.my-app.com'; const authorizationUrl = workos.sso.getAuthorizationUrl({ provider, redirectUri, clientId, }); res.redirect(authorizationUrl); });
If there is an issue generating an authorization URL, WorkOS will return the redirect URI as is. Read the API Reference for more details.
Next, let’s add the redirect endpoint which will handle the callback from WorkOS after a user has authenticated with their identity provider. This endpoint should exchange the authorization code returned by WorkOS with the authenticated user’s profile. The authorization code is valid for 10 minutes.
The redirect URI must use HTTPS. If you need a custom URI scheme, e.g. for mobile app deep linking, please contact support.
import type { NextApiRequest, NextApiResponse } from 'next'; import { WorkOS } from '@workos-inc/node'; const workos = new WorkOS(process.env.WORKOS_API_KEY); const clientId = process.env.WORKOS_CLIENT_ID; export default async (req: NextApiRequest, res: NextApiResponse) => { const { code } = req.query; const { profile } = await workos.sso.getProfileAndToken({ code, clientId, }); // Use the Test Organization ID to get started. Replace it with // the user’s real organization ID when you finish the integration. const organization = 'org_test_idp'; // Validate that this profile belongs to the organization used for authentication if (profile.organizationId !== organization) { return res.status(401).send({ message: 'Unauthorized', }); } // Use the information in `profile` for further business logic. res.redirect('/'); };
const express = require('express'); const { WorkOS } = require('@workos-inc/node'); const app = express(); const workos = new WorkOS(process.env.WORKOS_API_KEY); const clientId = process.env.WORKOS_CLIENT_ID; app.get('/callback', async (req, res) => { const { code } = req.query; const { profile } = await workos.sso.getProfileAndToken({ code, clientId, }); // Use the Test Organization ID to get started. Replace it with // the user’s real organization ID when you finish the integration. const organization = 'org_test_idp'; // Validate that this profile belongs to the organization used for authentication if (profile.organizationId !== organization) { return res.status(401).send({ message: 'Unauthorized', }); } // Use the information in `profile` for further business logic. res.redirect('/'); });
When adding your callback endpoint, it is important to always validate the returned profile’s organization ID. It’s unsafe to validate using email domains as organizations might allow email addresses from outside their corporate domain (e.g. for guest users).
Go to the Redirects page in the dashboard to configure allowed redirect URIs. This is your callback endpoint you used in the previous section.
Multi-tenant apps will typically have a single redirect URI specified. You can set multiple redirect URIs for single-tenant apps. You’ll need to be sure to specify which redirect URI to use in the WorkOS client call to fetch the authorization URL.
WorkOS staging environments allow wildcard characters in redirect URIs. More information about wildcard characters support can be found in the Redirect URIs guide. Query parameters are not allowed in any environment.
Normally, the default redirect URI you configure in the WorkOS dashboard is going to be used for all identity provider-initiated SSO sessions. This is because the WorkOS client is not used to initiate the authentication flow.
However, your customer can specify a separate redirect URI to be used for all their IdP-initiated sessions as a RelayState
parameter in the SAML settings on their side.
Learn more about configuring IdP-initiated SSO in the Login Flows guide.
If you followed this guide, you used the Test Organization available in your staging environment to initiate SSO. With that, you can already test your integration end-to-end.
Head to the Test SSO page in the WorkOS Dashboard to get started with testing common login flows, or read on about that in detail in the next guide.