# Admin Portal

The Admin Portal is a standalone application where your users can configure and manage WorkOS resources such as [Connections](/reference/sso/connection) and [Directories](/reference/directory-sync/directory) that are scoped to their [Organization](/reference/organization).

### provider-icons

## Provider Icons

Icons for third-party providers are available through the WorkOS CDN. These icons cover identity providers, Directory Sync, and domain verification services used within the Admin Portal.

### List Provider Icons

Get a list of all of existing provider icons.





### Get a Provider Icon

To use an icon in your project, you can reference the CDN link directly. You can alternate between light and dark mode icons by changing the path in the URL or using CSS media queries.

```html title="Example icon"

  
  

```

You can change the icons to grayscale by adding the `filter` CSS property.

```css title="Grayscale style"
img {
  filter: grayscale(100%);
}
```

### portal-link

## Portal Link

A Portal Link is a temporary endpoint to initiate an Admin Portal session. It expires five minutes after issuance.

```url title="Example Portal Link URL"
https://setup.workos.com?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

### generate

## Generate a Portal Link

Generate a Portal Link scoped to an Organization.


## RBAC {#rbac}

### Quick Start

Set up roles & permissions to model your authorization requirements. Then use the SDK to make access checks from your application.

## Before getting started

To get the most out of this guide, you should have:

- A [WorkOS account](https://dashboard.workos.com/)
- Your WorkOS [API Key](/glossary/api-key)

## What you'll build

In this guide, we’ll implement role-based access control for a simple B2B video sharing SaaS application, where users can view and create videos, and elevated roles can manage other users’ roles and application settings.

We will:

1. Map your application’s access management model to a set of roles
2. Define permissions to control granular access to your application’s resources
3. Associate permissions with roles, and configure default roles and priority order
4. If using AuthKit, assign roles to organization memberships and determine access via the [session JWT](/reference/authkit/session-tokens)
5. If using standalone SSO, access user roles through the [SSO Profile object](/reference/sso/profile)
6. If using standalone Directory Sync, access user roles through the [Directory User object](/reference/directory-sync/directory-user)

## API resource definitions

[Role](/reference/roles)
: Represents a logical grouping of access management rules.

---

## (1) Create roles

The first step to RBAC is to determine the application's access management hierarchy.

---

## (2) Create permissions

The first step to RBAC is to define

Get provider-specific instructions by selecting the directory provider you want to test:

---

## Summary

That's it! We've now setup a powerful RBAC system for our application.

### Organization Roles

Create and manage custom organization-scoped roles

## Overview

Organization roles are custom roles scoped to a particular organization. They are managed via the _Roles_ tab under an organization in the [WorkOS Dashboard](https://dashboard.workos.com/). You can utilize organization roles regardless of whether you’re integrating with AuthKit, SSO, or Directory Sync.

![Roles tab for organization](https://images.workoscdn.com/images/5c09cd78-041f-4bb9-9e76-f7267106b22c.png?auto=format&fit=clip&q=50)

### Why might I use organization roles?

In some cases, an application’s fixed set of roles may not meet the needs of certain organizations. For example, an organization may require a lesser privileged set of permissions for their members. Organization roles allow you to create custom roles, with the organization’s desired set of permissions, without affecting access control for other organizations.

### Creating organization roles

By default, organizations have no custom organization roles and simply inherit the environment-level roles. You can create an organization role by clicking the "Create role" button on the organization’s _Roles_ tab. All organization role slugs are automatically prefixed with `org`.

![Create an organization role](https://images.workoscdn.com/images/90f3f3c0-3c66-48b2-b962-04b34f30599e.png?auto=format&fit=clip&q=50)

### Organization role configuration

Once you create the first role for an organization, that organization will have its own [default role](/authkit/roles-and-permissions/configure-roles-and-permissions/default-role) and [priority order](/authkit/roles-and-permissions/configure-roles-and-permissions/priority-order), independent from the environment.

New roles added to the environment will be available to the organization and placed at the bottom of the organization’s role priority order.

### Using organization roles

Like environment-level roles, organization roles can be used in [role assignment](/authkit/roles-and-permissions/role-assignment), [sessions](/authkit/roles-and-permissions/role-aware-sessions), and the [organization membership API](/reference/authkit/organization-membership). No additional action is required to enable this behavior after creating organization roles.

### Deleting an environment role

When attempting to delete an environment role that’s the default role for one or more organizations, you’ll be prompted to select a new default role for all affected organizations. Organization members previously assigned the deleted role will be assigned the new organization default role.

![Select a replacement role](https://images.workoscdn.com/images/5e6f3e51-5de5-4bb1-a850-52b2196282b9.png?auto=format&fit=clip&q=50)

### Integrating Role-Based Access Control

Utilize Role-Based Access Control across WorkOS products

## Configure roles and permissions

Before integrating with WorkOS Role-Based Access Control (RBAC), you’ll need to [configure roles and permissions](/rbac/configuration) for your application in the [WorkOS Dashboard](https://dashboard.workos.com/).

---

## Integrating with AuthKit

WorkOS RBAC seamlessly integrates with AuthKit to provide a complete user management solution. Using AuthKit, you can assign roles directly to organization memberships, source roles from your customer’s identity provider (IdP), and read roles and permissions directly from session JWTs.

### Assigning roles

In AuthKit, users are associated with [organizations](/reference/organization) via [organization memberships](/reference/authkit/organization-membership). Each organization membership has role(s), which represents a user’s access level for that particular organization. Every organization membership is automatically assigned the [default role](/rbac/configuration/configure-roles/default-role) when added to an organization.

You can modify an organization membership’s role(s) via the [organization memberships API](/reference/authkit/organization-membership/create), [WorkOS Dashboard](https://dashboard.workos.com/), or via [IdP role assignment](/rbac/assignments/idp-role-assignment).

[IdP role assignment](/rbac/idp-role-assignment) will always take precedence over roles assigned via API or the WorkOS Dashboard. For [SSO group role assignment](/sso/identity-provider-role-assignment/sso-group-role-assignment), the organization membership role updates each time the user authenticates. For [directory group role assignment](/directory-sync/identity-provider-role-assignment/directory-group-role-assignment) via [directory provisioning](/authkit/directory-provisioning), the organization membership’s role updates each time we receive a directory event for the user.

### Single vs. multiple roles

AuthKit, Directory Sync, and Single Sign-On all support both single and [multiple role](/authkit/roles-and-permissions/multiple-roles) paradigms. There are two ways to assign multiple roles:

- **Group-based assignment**: if a user is a member of multiple groups with role mappings, they will receive all the roles. This applies to directory users, SSO profiles, and organization memberships when using [directory](/authkit/directory-provisioning) or [SSO JIT provisioning](/authkit/jit-provisioning/sso-jit-provisioning) in AuthKit.
- **Manual assignment**: multiple roles can be assigned to [organization memberships](/reference/authkit/organization-membership) directly via the WorkOS Dashboard or [API](/reference/authkit/organization-membership/create).

Multiple roles helps to avoid needing to create roles for every possible combination of permissions e.g., designer-engineer. This model fits teams where users span functions or need additive, temporary access.

For most apps, start with **single-role** assignments for simplicity and predictability, and adopt multiple roles only when overlapping permission sets become common.

### Using roles and permissions in your app

Read a user’s role(s) from their [organization membership](/reference/authkit/organization-membership) or from an [AuthKit session access token](/authkit/sessions/integrating-sessions/access-token).

---

## Integrating with Directory Sync

For [standalone Directory Sync](/directory-sync), organization administrators manage roles through [directory group role assignment](/directory-sync/identity-provider-role-assignment). Their assigned role defines the user’s access level for the particular [organization](/reference/organization) and is based on their directory group memberships.

All [directory users](/reference/directory-sync/directory-user) have assigned roles. If no role is explicitly assigned through directory group role assignment, the user receives the [default role](/rbac/configuration/configure-roles/default-role). Roles are granted to directory users in real-time, when we receive updates to their group memberships.

Role slugs are returned on [Directory User](/reference/directory-sync/directory-user) objects from the API. These can be used to assign a role to your internal user object.

---

## Integrating with Single Sign-On (SSO)

For [standalone SSO](/sso), organization administrators manage roles via [SSO group role assignment](/sso/identity-provider-role-assignment). Their assigned role defines the user’s access level for the particular [organization](/reference/organization).

All [SSO profiles](/reference/sso/profile) have assigned roles. If no role is explicitly assigned through SSO group role assignment, the user receives the [default role](/rbac/configuration/configure-roles/default-role). Roles are granted to SSO profiles when the user authenticates.

Role slugs are returned on [SSO Profile](/reference/sso/profile) objects from the API. These can be used to assign a role to your internal user object based on group memberships.

### Role-Based Access Control (RBAC)

Assign roles and manage access for users and organizations

## Introduction

WorkOS Role-Based Access Control (RBAC) is an authorization system designed for managing access to applications using a flexible roles and permissions model. With WorkOS RBAC, teams can also define custom roles at the organization or tenant level, assign permissions to those roles, and enforce access policies at scale. RBAC also supports role assignment from identity provider (IdP) groups, making it easy to integrate with Single Sign-On (SSO) and Directory Sync workflows for seamless, enterprise-ready access control.

## Key features

- Fully managed authorization service for defining and enforcing access controls across your application
- Configure roles, permissions, and organization-level roles directly in the [WorkOS Dashboard](https://dashboard.workos.com)
- Seamless integration with [AuthKit user management](/authkit) by assigning roles via API and enforcing access through session JWTs
- Support for enterprise features like organization-scoped roles and IdP role assignment via SSO and Directory Sync allowing your customers to automatically map roles from their identity provider to streamline enterprise onboarding
- Fully integrated with [WorkOS Widgets](/widgets), including role management through the User Management Widget

## Additional resources

- [The developer's guide to RBAC](https://workos.com/guide/the-developers-guide-to-rbac)
- [8 Role-Based Access Control (RBAC) examples in action](https://workos.com/blog/role-based-access-control-example)
- [How to build RBAC with WorkOS and Node](https://workos.com/blog/rbac-with-workos-and-node)

### IdP Role Assignment

Map identity provider groups to roles to automatically assign roles to users

## Overview

Identity Provider (IdP) role assignment is the process of mapping identity provider groups to roles to automatically assign roles to users.

Users are assigned to groups via the identity provider. Groups usually correspond to roles in your app. Therefore, IT admins will often map a group one-to-one to a role. This can be defined within the WorkOS dashboard or Admin Portal for your application to receive automatic role updates.

## Role assignment sources

### Directory Sync

Roles can be assigned from the identity provider via Directory Sync through [directory group role assignment](/directory-sync/identity-provider-role-assignment/directory-group-role-assignment). Admins can map groups to roles in the Admin Portal during SCIM and Google Workspace directory setup.
You can also manage these assignments in the [WorkOS Dashboard](https://dashboard.workos.com/).

Enterprise organizations typically use SSO to manage user authentication and SCIM (Directory Sync) for user lifecycle management.
While access management can be automated through either SSO or SCIM, SCIM is generally the preferred option due to its real-time synchronization capabilities.

### SSO

Roles can be assigned from the identity provider via SSO through [SSO group role assignment](/sso/identity-provider-role-assignment/sso-group-role-assignment). Admins can map groups to roles in the Admin Portal during SSO connection setup.
You can also manage these assignments in the [WorkOS Dashboard](https://dashboard.workos.com/). SSO group role assignment is supported in both SAML and OIDC-based connection types, except for Google OIDC due to [a limitation](https://issuetracker.google.com/issues/133774835?pli=1) with the groups claim.

A key limitation of SSO-based role assignment is that changes made in the identity provider (IdP) only take effect after the user re-authenticates. In contrast, SCIM propagates changes immediately without requiring user interaction, enabling applications to revoke sessions and enforce access updates in real time.

> If your organization has a directory connection configured, it is recommended to use the [directory for role assignment](/directory-sync/identity-provider-role-assignment/directory-group-role-assignment).

## AuthKit integration

If you are [integrating with AuthKit](/authkit/roles-and-permissions/role-assignment), our full user management solution, roles are automatically assigned to the appropriate [organization membership](/reference/authkit/organization-membership). These roles are also reflected in the [user’s session token](/authkit/sessions/integrating-sessions/access-token), ensuring consistent access control across your application.

When using SSO group role assignment, roles are populated on the organization membership through SSO groups, allowing role assignment based on your customer’s identity provider configuration each time a user authenticates.

When using Directory Sync group role assignment, roles are populated on the organization membership through [directory provisioning](/authkit/directory-provisioning), allowing for seamless, real-time role assignment based on your customer’s identity provider configuration.

## Priority order

If a user is provisioned from multiple groups with conflicting roles, the role with the highest priority will be assigned. If using multiple roles, priority order should be ignored.

![Edit role priority dialog](https://images.workoscdn.com/images/3c6946c2-4ff1-41e4-b10f-568339dc3a2b.png?auto=format&fit=clip&q=50)

## Multiple roles

When [multiple roles is enabled](/rbac/configuration/configure-roles/multiple-roles), users can receive multiple roles through identity provider group memberships. This applies to both [SSO group role assignment](/sso/identity-provider-role-assignment) and [Directory Sync group role assignment](/directory-sync/identity-provider-role-assignment).

### How multiple roles work with IdP assignment

- **All applicable roles assigned**: Users receive all roles from groups they belong to that have explicit role mappings
- **Union of permissions**: Users get the combined permissions from all assigned roles
- **Priority order ignored**: When multiple roles are enabled, priority order is not used since users receive all applicable roles
- **Minimum one role**: Every user must have at least one role - if no groups have explicit mappings, the user receives the [default role](/rbac/configuration)

### Example scenario

If a user is a member of both "Engineering" and "Design" groups in their identity provider:

- **Single role mode**: User receives the highest priority role (e.g., "Engineering")
- **Multiple roles mode**: User receives both "Engineering" and "Designer" roles

This prevents "role explosion" where you would otherwise need to create hybrid roles like "designer-engineer" for every possible combination.

## Explicit vs. default role assignments

Explicit role assignments are created by manually mapping an IdP group to a role in the WorkOS Admin Portal or Dashboard.

Default role assignments are created for any IdP group that does not have an explicit role mapping. Default group role assignments are always mapped to the configured [default role](/rbac/configuration/configure-roles/default-role).

## Role assignment in Admin Portal

You can choose to show or hide the role assignment step in Admin Portal, and whether to show the steps for Directory Sync or SSO at an environment level on the _Roles & Permissions_ page in the [WorkOS Dashboard](https://dashboard.workos.com/).

![Role assignment in Admin Portal dialog](https://images.workoscdn.com/images/fe19e3ac-6370-404e-9590-cdb06b3de127.png?auto=format&fit=clip&q=50)

For your customers that may have a different setup, you can override the role assignment in Admin Portal setting per-organization, on the _Roles_ tab of the organization page in the [WorkOS Dashboard](https://dashboard.workos.com/). For example, if most customers use Directory Sync but a few only use SSO, select "Directory groups" role assignment at the environment level, and select "Single Sign-On groups" at the organization level for the exceptions.

### Configuration

Configure roles and permissions

## Overview

A role represents a logical grouping of permissions, defining access control levels for users within your application. Roles are identified by unique, immutable slugs and are assigned to users via [organization memberships](/authkit/users-organizations/organizations). Role assignments can be sourced manually or from Identity Provider (IdP) group mappings (SSO or Directory Sync).

Permissions grant users privileged access to resources and actions in your application and are referenced in your code by unique, immutable slugs. A permission can be assigned to any number of roles.

> Role and permission configuration applies to [all integrations](/rbac/integration).

---

## Configure roles

Roles alone can be sufficient when your application only requires very coarse-grained access control. This is suitable if users only need to be separated into broad categories and there is minimal overlap between roles. Simple roles can be easier to manage, but are less flexible for complex access control scenarios.

![Roles section WorkOS Dashboard](https://images.workoscdn.com/images/09c8fb23-5748-4236-914e-79849ac03a9a.png?auto=format&fit=clip&q=50)

You can manage roles in the _Roles & Permissions_ section of the [WorkOS Dashboard](https://dashboard.workos.com/environment/roles-and-permissions/).

Role slugs are immutable and cannot be changed after creation. Environment role slugs are unique within an environment. [Organization role](/rbac/organization-roles) slugs are unique within an organization.

### Default role

Role configuration occurs at the environment level. Each environment is seeded with a default `member` role, which is automatically assigned to every organization member. This default role cannot be deleted, but any role can be set as the default.

If you need to set default roles or other role configurations at the organization level, refer to the [Organization roles](/authkit/roles-and-permissions/organization-roles) section.

### Multiple roles

All [integrations](/rbac/integration) support multiple roles across directory users, SSO profiles, and organization memberships. For any user, if role(s) are not explicit set, they will receive the default role.

Multiple roles is disabled by default. To manage this setting, open the [Roles & Permissions](https://dashboard.workos.com/environment/roles-and-permissions/configuration) configuration page and scroll to the _Multiple Roles_ section.

> Multiple roles is an **environment-level** setting and applies to all organizations in that environment.

### Priority order

Role priority order is used for [IdP role assignment](/rbac/idp-role-assignment) to resolve conflicts when a user belongs to multiple mapped groups. The highest-priority role wins. Priority order also determines which role will be assigned to users when migrating from a multiple roles to single role configuration in the environment.

### Delete roles

When roles are deleted:

- **Single-role (default):** All affected organization memberships, SSO profiles, and directory users are reassigned to the **default role**.
- **Multiple-roles:** The deleted role is **removed** from each organization membership that has it, any other roles on the membership remain intact.

Deletion is asynchronous, so updates may take a moment to propagate.

> **Tip:** To migrate from one default role to another, set the new default, then delete the old one—users will be reassigned automatically.

---

## Configure permissions

Permissions allow for more detailed and flexible management of access. They are particularly useful when:

- You anticipate the need to frequently modify access rights or introduce new roles.
- There is significant overlap in access rights between different roles, but with some variations.
- You want to minimize code changes when modifying access rights. By abstracting access control checks to permissions, you can add or modify roles and their access rights without changing the application code.

### Create permissions

You can manage permissions in the _Roles & Permissions_ section of the [WorkOS Dashboard](https://dashboard.workos.com/environment/roles-and-permissions/permissions).

When configuring permissions, we recommend:

- Defining a common naming scheme to use across all permissions for your application. Consider separating the resource and action with a delimiter, such as `users:view`. The following delimiters are permitted: `-.:_*`.
- Keep permission slugs clear and concise. When assigned to roles, these slugs will included as part of session cookies in the [session JWT claims](/authkit/sessions/integrating-sessions/access-token), which is limited to a maximum size of 4KB in many modern web browsers.

### Assign permissions to roles

Permissions can be assigned when creating a new role or when editing an existing role.

![Assign permissions to a role](https://images.workoscdn.com/images/f6fd6d9a-a7b0-4df7-908b-b657e669a3dc.png?auto=format&fit=clip&q=50)


## Pipes {#pipes}

### Pipes

Enable your customers to connect their third-party accounts to your application.

## Introduction

Pipes allows your users to securely connect their third-party accounts to your
application. With Pipes, you can easily integrate with popular services like
GitHub, Slack, Google, Salesforce, and many more without managing OAuth flows,
token refresh logic, or credential storage.

> Reach out to support via [email](mailto:support@workos.com) or Slack if you are interested in early access.

## Configuring providers

To make an provider available to your users, you will need to configure it in
the WorkOS Dashboard.

Visit the _Pipes_ section of the WorkOS Dashboard to get started. Click _Connect
provider_ then choose the provider from the list. If you don’t see the provider
you need, please reach out to [our team](mailto:support@workos.com).

![A screenshot of a GitHub provider being configured via the Pipes page in the WorkOS Dashboard](https://images.workoscdn.com/images/88a1f135-53ba-4d26-92ef-6c61e924e178.png?auto=format&fit=clip&q=50)

### Shared Credentials

For the fastest setup, you can use WorkOS-managed shared credentials in sandbox
environments. This allows users to connect immediately without requiring you to
create OAuth applications with each provider.

1. Specify the required **scopes** for your application.
2. Provide an optional **description**. This will be used in the widget to inform users
   on how your application will use their data from the provider.

### Custom Credentials

For production applications, configure the provider with your own OAuth credentials:

1. **Create an OAuth application** within the provider's dashboard.
   1. You can find instructions on setting up the provider in the documentation section of the setup modal.
1. Use the provided **redirect URI** when configuring the provider.
1. Set the **client ID and secret** from the provider.
1. Specify the required **scopes** for your application.
   1. You may need to set these scopes in the provider configuration as well.
1. Provide an optional **description**. This will be used in the widget to inform users
   on how your application will use their data from the provider.

Commonly used scopes are provided in-line, but you should consult each provider's documentation for the full list of available scopes.

## Provider management in your application

The [Pipes Widget](/widgets/pipes) provides a pre-built UI for users to connect
and manage their connected accounts. The widget shows the user which
providers are available, and lets them easily initiate the authorization
flow. It communicates with the WorkOS API and stores the connection information
for the user. If there's ever a problem with the user’s access token, the widget
will let them know they need to reauthorize.

![Pipes widget screenshot](https://images.workoscdn.com/images/e84a33bb-0510-4d85-9041-33b1a0ce938c.png?auto=format&fit=clip&q=50)

> The description in the widget is set in the provider's configuration in the WorkOS Dashboard.

## Fetching access tokens

Once a user has connected a provider, you can [fetch access tokens](/reference/pipes) from your
backend to make API calls to the connected service on their behalf. Pipes takes
care of refreshing the token if needed, so you’ll always have a fresh token. If
there’s a problem with the token, the endpoint will return information about the issue so you can
direct the user to the correct it. This may require sending the user to re-authorize directly
or via the page with the Pipes widget.


## Migrations {#migrate}

### Migrate from Stytch

Learn how to migrate users and organizations from Stytch.

## Introduction

The WorkOS API allows you to migrate your existing user data from a variety of existing sources. In this guide, we will walk through the steps to export and import your B2B users, organizations, and enterprise configurations from Stytch.

---

## (1) Export data from Stytch

Stytch allows customers to export organization and member data using their API endpoints. You can [export most data programmatically](https://stytch.com/docs/b2b/guides/migrations/exporting-from-stytch), though password hashes and complete SSO/SCIM connection configurations require contacting Stytch support.

### Exporting organizations and members

Use the [Stytch Search Organizations API](https://stytch.com/docs/b2b/api/search-organizations) to retrieve all organizations in your Stytch project, then use the [Stytch Search Members API](https://stytch.com/docs/b2b/api/search-members) to export members for each organization. Both endpoints support pagination for projects with more than 1000 records and have a rate limit of 100 requests per minute.

> The following exports B2B Users. To export Consumer Users, consult [this utility from Stytch](https://github.com/stytchauth/stytch-node-export-users).

```typescript title="Export organizations and members from Stytch"
;
;

const client = new B2BClient({
  project_id: process.env.STYTCH_PROJECT_ID,
  secret: process.env.STYTCH_SECRET,
});

async function exportOrganizations() {
  const allOrganizations: any[] = [];
  let cursor = '';

  do {
    const response = await client.organizations.search({
      cursor,
      limit: 1000,
    });

    allOrganizations.push(...response.organizations);
    cursor = response.results_metadata.next_cursor;
  } while (cursor);

  return allOrganizations;
}

async function exportMembers(organizationIds: string[]) {
  const allMembers: any[] = [];
  let cursor = '';

  do {
    const response = await client.organizations.members.search({
      organization_ids: organizationIds,
      cursor,
      limit: 1000,
    });

    allMembers.push(...response.members);
    cursor = response.results_metadata.next_cursor;
  } while (cursor);

  return allMembers;
}

(async () => {
  const organizations = await exportOrganizations();
  const organizationIds = organizations.map((org) => org.organization_id);
  console.log(`Found ${organizations.length} organizations`);
  const members = await exportMembers(organizationIds);
  console.log(`Found ${members.length} members`);

  // Export all data to a JSON file
  await writeFile(
    'stytch-b2b-export.json',
    JSON.stringify({ organizations, members }, null, 2),
  );
})();
```

The Organization object includes `organization_id`, `organization_name`, `email_allowed_domains`, `sso_active_connections`, and `scim_active_connection` fields. The Member object includes `member_id`, `email_address`, `name`, `status`, `oauth_registrations`, `sso_registrations`, and `roles` fields.

### Exporting passwords

If your Stytch members sign in using password-based authentication, you will need to [contact Stytch support](mailto:support@stytch.com) to export password hashes. After opening a request, they will provide an export of your hashed password data. The timeline for this process can vary.

Stytch uses the `scrypt` password hashing algorithm for password storage. When you export passwords through Stytch support, verify the hash format they provide, as WorkOS supports multiple algorithms including `scrypt`, `bcrypt`, and `argon2`.

---

## (2) Import data into WorkOS

Once you've obtained the necessary export data from Stytch, you can import it into WorkOS via the API. We recommend importing organizations first, then users with their organization memberships.

### Creating organizations

Use the [Create Organization API](/reference/organization/create) to import each Stytch organization. Map `organization_name` to `name` and `email_allowed_domains` to `domainData` (with appropriate `state` values).

```typescript title="Import organizations into WorkOS"
;

const workos = new WorkOS(process.env.WORKOS_API_KEY);

async function importOrganization(stytchOrg: any) {
  const domainData =
    stytchOrg.email_allowed_domains?.map((domain: string) => ({
      domain,
      state: 'pending', // or 'verified' if domains are pre-verified
    })) || [];

  const org = await workos.organizations.createOrganization({
    name: stytchOrg.organization_name,
    domainData,
  });

  return org;
}

// Import all organizations
const orgIdMapping = new Map();
for (const stytchOrg of stytchOrganizations) {
  try {
    const workosOrg = await importOrganization(stytchOrg);
    orgIdMapping.set(stytchOrg.organization_id, workosOrg.id);
  } catch (error: any) {
    console.error(`[FAILED] ${stytchOrg.organization_name}`, error.message);
  }
}
```

### Creating users and memberships

Use the [Create User API](/reference/authkit/user/create) to import each Stytch member, then use the [Organization Membership API](/reference/authkit/organization-membership/create) to link users to their organizations. You should filter members by status—typically only importing `active` members and potentially re-inviting `invited` or `pending` members.

```typescript title="Import users and create memberships"
async function importUser(stytchMember: any) {
  // Parse name into first and last name
  const nameParts = stytchMember.name?.split(' ') || [];
  const firstName = nameParts[0] || '';
  const lastName = nameParts.slice(1).join(' ') || '';

  const user = await workos.userManagement.createUser({
    email: stytchMember.email_address,
    emailVerified: stytchMember.email_address_verified,
    firstName,
    lastName,
  });

  return user;
}

async function createMembership(
  workosUserId: string,
  workosOrgId: string,
  roleSlug: string = 'member',
) {
  return await workos.userManagement.createOrganizationMembership({
    userId: workosUserId,
    organizationId: workosOrgId,
    roleSlug,
  });
}

const userIdMapping = new Map();
for (const stytchMember of stytchMembers) {
  try {
    const workosUser = await importUser(stytchMember);
    userIdMapping.set(stytchMember.member_id, workosUser.id);

    const workosOrgId = orgIdMapping.get(stytchMember.organization_id);
    if (workosOrgId) {
      await createMembership(workosUser.id, workosOrgId);
    } else {
      console.warn(`No WorkOS org found for ${stytchMember.email_address}`);
    }
  } catch (error: any) {
    console.error(`[FAILED] ${stytchMember.email_address}`, error.message);
  }
}
```

> User creation is rate-limited. See the [rate limits documentation](/reference/rate-limits) for details. Consider implementing retry logic and batching for large imports, or reach out to [support@workos.com](mailto:support@workos.com) to process large datasets in the background.

### Importing passwords

If you exported password hashes from Stytch, you can import them during user creation or later using the [Update User API](/reference/authkit/user/update). Pass the `passwordHashType` parameter (e.g., `'scrypt'`, `'bcrypt'`) and the `passwordHash` value from your Stytch export. Once imported, users can sign in with their existing passwords without performing a password reset.

```typescript title="Import user with password hash"
const user = await workos.userManagement.createUser({
  email: stytchMember.email_address,
  emailVerified: stytchMember.email_address_verified,
  firstName,
  lastName,
  passwordHash: stytchPasswordHash, // From Stytch support export
  passwordHashType: 'scrypt', // Verify the actual format with Stytch support
});
```

---

## (3) SSO connections

Enterprise SSO connections cannot be exported from Stytch, but you can manually reconfigure connections. You have two options: configure each connection through the dashboard, or use the [Admin Portal](/admin-portal) to let customers self-service their SSO setup. The Admin Portal approach is recommended for larger migrations, as it reduces manual work and provides a familiar self-service experience for IT administrators.

To manually configure a SAML connection, create the organization (if not already created), then set up a new SAML connection in the dashboard.

```typescript title="Create SSO connection programmatically"
;

const workos = new WorkOS(process.env.WORKOS_API_KEY);

// Generate Admin Portal link for customer to self-configure SSO
const { link } = await workos.portal.generateLink({
  organization: 'org_12345',
  intent: 'sso',
  returnUrl: 'https://yourapp.com/admin',
});

// Send this link to the customer's IT administrator
console.log('Admin Portal link:', link);
```

The OIDC process is similar: create the organization, configure a new OIDC connection, obtain the callback URL, and work with the customer's IT team to update their OIDC application configuration. See the [OIDC integration guide](/integrations/oidc) for detailed instructions. For provider-specific guidance, consult the integration guides for [Okta SAML](/integrations/okta-saml), [Microsoft Entra ID SAML](/integrations/entra-id-saml), [Google Workspace SAML](/integrations/google-saml), or [Generic SAML](/integrations/saml).

---

## (4) Directory Sync

Like SSO connections, SCIM directory sync connections must be reconfigured. [Directory Sync](/directory-sync) provides real-time user and group provisioning, automatic deprovisioning, custom attribute mapping, and support for 20+ identity providers including [Okta SCIM](/integrations/okta-scim), [Microsoft Entra ID SCIM](/integrations/entra-id-scim), [Google Workspace Directory](/integrations/google-saml), and [Custom SCIM v2.0](/integrations/scim) providers.

For each Stytch SCIM connection, create a corresponding Directory Sync connection in the dashboard or using the [Admin Portal](/admin-portal) for self-service setup.

```typescript title="Generate Admin Portal link for Directory Sync"
const { link } = await workos.portal.generateLink({
  organization: 'org_12345',
  intent: 'dsync',
  returnUrl: 'https://yourapp.com/admin',
});
```

WorkOS sends webhooks for directory sync events like `dsync.user.created`, `dsync.user.updated`, `dsync.user.deleted`, and `dsync.group.updated`. Configure webhooks in the dashboard to receive these events and keep your application in sync with directory changes.

```typescript title="Handle directory sync events"
app.post('/webhooks/workos', async (req, res) => {
  const event = req.body;

  switch (event.event) {
    case 'dsync.user.created':
      await createUserFromDirectory(event.data);
      break;
    case 'dsync.user.deleted':
      await deactivateUser(event.data.id);
      break;
    case 'dsync.group.updated':
      await syncGroupMemberships(event.data);
      break;
  }

  res.status(200).send();
});
```

See the [Directory Sync guide](/directory-sync) for complete implementation details.

---

## (5) Authentication and access control

Stytch B2B supports several authentication methods and access control features that have equivalent capabilities in AuthKit, though some migration adjustments are necessary.

### Authentication methods

Both Stytch and WorkOS support traditional email and password authentication. After importing your users with their password hashes, users can sign in immediately with their existing credentials. Enable password authentication in the dashboard under the _Authentication_ tab and configure password strength requirements as needed.

Stytch's magic link authentication can be replaced with [Magic Auth](/authkit/magic-auth). While Stytch sends clickable magic links via email, Magic Auth sends a six-digit one-time code that users enter manually. Magic Auth codes expire after 10 minutes and are automatically validated by AuthKit. Stytch's email OTP authentication is functionally identical to Magic Auth, so no application logic changes are needed.

If your Stytch users sign in through OAuth providers like Google, Microsoft, or GitHub, they can continue using the same providers. After configuring OAuth providers in the dashboard, users can sign in with their social credentials and will be automatically linked to their user account based on email address matching.

In the dashboard:

1. Navigate to Authentication > OAuth providers
2. Select the provider (Google, Microsoft, GitHub, etc.)
3. Add OAuth client credentials (Client ID and Secret)
4. Copy the redirect URI and add to your OAuth app configuration

Users authenticate through AuthKit, which handles the OAuth flow.

```typescript title="Configure OAuth providers"
const { user } = await workos.userManagement.authenticateWithCode({
  code: authorizationCode,
  clientId: process.env.WORKOS_CLIENT_ID,
});
```

Check the [integrations page](/integrations) for the complete list of supported OAuth providers, including [Google OAuth](/integrations/google-oauth), [Microsoft OAuth](/integrations/microsoft-oauth), and [GitHub OAuth](/integrations/github-oauth).

### Multi-factor authentication

Both Stytch and WorkOS support TOTP authenticators like Google Authenticator, Authy, and 1Password. WorkOS supports importing existing TOTP secrets during migration through the [developer-provided TOTP secrets](https://workos.com/changelog/developer-provided-totp-secrets) feature, which allows users to keep their existing authenticator app configurations without re-enrollment.

However, [Stytch cannot export TOTP secrets](https://stytch.com/docs/guides/migrations/migrating-user-data-statically#adding-totp-or-biometrics-for-mfa). Users who have TOTP MFA enrolled in Stytch will need to re-enroll their authenticator apps with WorkOS during their next sign-in. Enable MFA in the dashboard under the _Authentication_ tab and configure whether MFA is optional or required. Communicate this change to your users before migration so they're prepared to scan a new QR code or enter a new secret key.

While Stytch supports SMS-based MFA, WorkOS does not due to known security vulnerabilities with SMS (SIM swapping, interception, etc.). Users who currently have SMS-based MFA will need to switch to TOTP authenticators, email-based Magic Auth, or modern biometric [Passkeys](/authkit/passkeys). See the [MFA guide](/authkit/mfa) for enrollment flows and implementation details.

### Roles and sessions

Stytch B2B provides RBAC with custom resources, roles, and actions. WorkOS offers similar capabilities through [roles and permissions](/authkit/roles-and-permissions). When migrating, identify your roles defined in Stytch, create equivalent roles in the dashboard, and assign roles during migration by specifying the `roleSlug` parameter when creating organization memberships. If your Stytch implementation uses complex RBAC policies with custom resources and actions, you may need to simplify to standard roles or implement custom authorization in your application logic.

```typescript title="Assign roles during migration"
const roleMapping = {
  stytch_admin: 'admin',
  stytch_member: 'member',
  custom_role_123: 'manager',
};

await workos.userManagement.createOrganizationMembership({
  userId: workosUserId,
  organizationId: workosOrgId,
  roleSlug: roleMapping[stytchMember.roles[0].role_id] || 'member',
});
```

JWT-based session tokens are used for authentication state. Your application will need to handle these session tokens. Use [an SDK](/sdks) to verify, extract user context (user ID, organization ID, role), and implement token refresh logic if using long-lived sessions.

```typescript title="Handle WorkOS sessions"
;

const workos = new WorkOS(process.env.WORKOS_API_KEY);

const { user, organizationId, role } =
  await workos.userManagement.authenticateWithCode({
    code: authorizationCode,
    clientId: process.env.WORKOS_CLIENT_ID,
  });

// Store session in your application
req.session.userId = user.id;
req.session.organizationId = organizationId;
req.session.role = role;
```

See the [AuthKit guide](/authkit) for complete session management implementation.

---

## Next steps

Be sure to understand how to [handle interim new users](/migrate/other-services/3-handling-interim-new-users) for managing users who sign up during your migration process.

After completing your migration to WorkOS, you can take advantage of additional features:

- **[Audit Logs](/audit-logs)**: Track security-relevant events across your application
- **[Radar](/authkit/radar)**: Protect against bots, fraud, and abuse
- **[Vault](/vault)**: Encrypt, store, and control access to sensitive data

If you haven't already, check out the [AuthKit Quick Start guide](/authkit) to learn how to integrate WorkOS into your application.

For questions or assistance with your migration, contact [support@workos.com](mailto:support@workos.com).

### Migrate from the standalone SSO API

Learn how to migrate your code from an existing WorkOS SSO integration.

## Introduction

The WorkOS AuthKit API supports all of the same social and enterprise identity providers, while providing higher level authentication features that most applications need. In this guide, we'll outline the steps to migrate an existing WorkOS SSO integration to the AuthKit API.

> The existing standalone [WorkOS SSO API](/reference/sso) will continue to be supported. This is a viable option for you if you prefer to handle more of the authentication flow yourself.

## The new User resource

The primary difference between existing integrations with [SSO](/sso) or [Directory Sync](/directory-sync) is the addition of a new resource: [Users](/reference/authkit/user).

The WorkOS [User object](/reference/authkit/user) represents a single user in your application, and binds together information from all of the Directory and Identity providers that WorkOS supports into a single resource. As you migrate your existing integration, you can expect to replace references to WorkOS Profiles and Directory Users with instead references to Users.

## Switch to AuthKit API calls

If you have built an integration with our standalone SSO API using [Get Authorization URL](/reference/sso/get-authorization-url), you will need to switch these calls with analogous calls to the AuthKit API.

### (1) Switch SSO initiation call

When initiating SSO for one of your users, instead of calling the SSO [Get Authorization URL](/reference/sso/get-authorization-url) API, call the AuthKit [Get Authorization URL](/reference/authkit/authentication/get-authorization-url) API instead:



The AuthKit Get Authorization API supports all of the same initiation parameters as the SSO API. In addition, it also supports an additional provider type, `authkit`, which will be covered later in this guide.

### (2) Switch API in Application Callback

Similar to an SSO integration, your application will still have a callback identified by the Redirect URI passed during the previous initiation call. The contract with your callback is the same, where you should expect to be given a `code`, along with any `state` that was originally provided.

However, instead of calling the SSO [Get a Profile and Token](/reference/sso/profile/get-profile-and-token) API, call the AuthKit [Authenticate](/reference/authkit/authentication) API instead, with the `grant_type` set to `authorization_code`:



> **Important:** Instead of receiving a [Profile](/reference/sso/profile), your application now receives a full [User object](/reference/authkit/user). While many of the fields are similar, such as the user’s email or name, the **User ID’s will be different** than the Profile ID’s you may have previously persisted in your application.

If email is a unique identifier in your application, you can use the WorkOS User’s email to identify the application-local user. WorkOS ensures that user email is verified before successfully completing an authentication request. When the API issues an email verification challenge, an [email verification response](/reference/authkit/authentication-errors/email-verification-required-error) is returned.

### Handling new authentication flows

The AuthKit API offers a higher-level abstraction than the SSO API, offering more advanced [security features](/authkit/overview/security) like email verification and account Linking.

This means that when your application attempts to exchange a code for a user object, it may return one of several new expected errors. These map to cases that were previously mentioned, like requiring that the user first verify their email, or enroll in MFA.

If your application doesn’t require these extra settings, they can be disabled in the _Authentication_ section of the [WorkOS Dashboard](https://dashboard.workos.com/).

> If you are using AuthKit, you won’t need to handle error cases like required email verification, as AuthKit will automatically request this before a user is directed to their callback endpoint.

## AuthKit

If you prefer to have full control over the authentication UI, you can choose to integrate with the AuthKit API directly. However, the easiest way to get started is to use AuthKit Hosted UI, a pre-built hosted authentication UI that guides users through all of the advanced flows, like email verification and MFA enrollment.

You can enable AuthKit from the WorkOS dashboard, where you can also configure AuthKit branding and custom domains.

Getting started with AuthKit is as simple as passing `authkit` as the `provider`:



AuthKit can handle many of the concerns your application likely needed to previously, such as identifying which users sign in using enterprise SSO, and correctly routing them to their organization’s identity provider.

## Directory Sync

Directory provisioning is also supported in AuthKit. See the [Directory Provisioning documentation](/authkit/directory-provisioning) to learn more.

## Next Steps

Check out the [full guide](/authkit), along with the [API reference](/reference/authkit) to get an idea of all the ways your application’s user management needs can be solved by WorkOS.

If you need help migrating your existing WorkOS integration, or have any other questions, please reach out to [WorkOS support](mailto:support@workos.com?subject=WorkOS%20Support).

### Migrate from other services

Learn how to export and import users from your own data store.

## Introduction

The WorkOS AuthKit API allows you to migrate your existing user data from a variety of sources. In this guide, we'll walk through the steps to export, and then import users from your own data store.

## (1) Exporting data

While moving authentication related metadata to WorkOS, most applications will continue to store certain user information in their data store. This common subset of data will usually be the following:

| Field               | Description                                                                                                                    | Status   |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------ | -------- |
| Email               | The user’s email address. Used for various authentication and verification purposes.                                           | Required |
| First Name          | The user’s first, or given name.                                                                                               | Optional |
| Last Name           | The user’s last, or family name.                                                                                               | Optional |
| Verification Status | The user’s email verification status if they have gone through a verification flow. Assumed as “not verified” unless supplied. | Optional |
| Password            | The user’s password hash, if they use password-based authentication.                                                           | Optional |

While preparing the migration, you’ll want to ensure this information is programmatically available for use in the import step, this can mean:

- Exporting the relevant data to a file such as JSON or CSV.
- Allowing the data to be queried from the data store directly.

After the data is accessible, we can configure the import.

---

## (2) Importing Users into WorkOS

Now that the User data is available, we can import it into WorkOS.

### Creating users

For each of your users, you can call the WorkOS [Create User API](/reference/authkit/user/create). This will create a matching [User object](/reference/authkit/user) within WorkOS.

A successful response will include a new WorkOS user ID, most apps will want to persist this WorkOS user ID alongside the application-local user object.

```json
{
  "object": "user",
  /* highlight-start */
  "id": "user_01E4ZCR3C56J083X43JQXF3JK5",
  /* highlight-end */
  "email": "marcelina.davis@gmail.com",
  "firstName": "Marcelina",
  "lastName": "Davis",
  "emailVerified": true,
  "createdAt": "2021-06-25T19:07:33.155Z",
  "updatedAt": "2021-06-25T19:07:33.155Z"
}
```

> **Email addresses are unique** to each WorkOS environment. If you have a subset of users already in WorkOS, you may need to handle constraint violation errors.

There are now several options on how to proceed, depending on your application’s needs:

### Importing passwords

If your users currently use password-based authentication, you can import existing password hashes during the [users creation](/reference/authkit/user/create) process, or later using the WorkOS [Update User API](/reference/authkit/user/update).

WorkOS currently supports the following password hashing algorithms:

- `bcrypt`
- `scrypt`
- `firebase-scrypt`
- `ssha`
- `pbkdf2`
- `argon2`

For `scrypt` and `pbkdf2` passwords, use the PHC string format.
The hash and salt should be B64 encoded: trim the `=` characters that represent Base64 padding. Using a PHC-formatting library, like
Node's [`@phc/format`](https://www.npmjs.com/package/@phc/format), should handle this for you.

The following table shows how to map the `scrypt` and `pbkdf2` parameters to the PHC parameters.

#### scrypt

| `Scrypt` value    |     | PHC hash parameter |
| ----------------- | --- | ------------------ |
| `key length`      | →   | `kl`               |
| `cost`            | →   | `n`                |
| `rounds`          | →   | `r`                |
| `parallelization` | →   | `p`                |

A valid `scrypt` PHC formatted string looks like this:

```txt
$scrypt$v=1$n=16384,r=8,p=1,kl=64$Swhqd4iUYTtWfbCYIPeuMw$q7pfdBQMJujd5FX/qX+ozM2O6aNqP+mo1ZnHGH15XM2vlhroQfPA037UpbdfpH4H66OrSPjsUhfkAMuNoBiQvw
```

#### pbkdf2

| `pbkdf2` value |     | PHC hash parameter |
| -------------- | --- | ------------------ |
| `digest`       | →   | `d`                |
| `iterations`   | →   | `i`                |

For `pbkdf2` allowed values for digest are `sha256` or `sha512`. The value for iterations is dependent on digest. For `sha256` there is a minimum of 600,000 iterations and a max of 1,000,000. For `sha512` there is a minimum of 210,000 and a max of 1,000,000.

A valid `pbkdf2` PHC formatted string looks like this:

```txt
$pbkdf2$i=600000,d=sha256$T2ptRFh6MXhDQVh2SWZuUGdpQXBUTg$xXiyTisD7390NijyCv5ICMhFW4eDuMlzypRoLGLyIvA
```

#### argon2

| `argon2` value |     | PHC hash parameter |
| -------------- | --- | ------------------ |
| `variant`      | →   | algorithm id       |
| `version`      | →   | `v`                |
| `memory`       | →   | `m`                |
| `time`         | →   | `t`                |
| `parallelism`  | →   | `p`                |

The variant should be `argon2id`, but older supported variants include `argon2d` and `argon2i`. The version must be `19`. The following memory, time (iterations), and parallelism settings are based on [OWASP recommendations](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id). Memory is specified in KiB with a minimum of 4,096 KiB (4 MiB) and maximum of 262,144 KiB (256 MiB). For time, there is a minimum of 1 iteration and a maximum of 5 iterations, except for `argon2i` which has a minimum of 3 iterations. Parallelism ranges from 1 to 8 threads. If your requirements fall outside of these guidelines, please [contact support](mailto:support@workos.com).

A valid `argon2` PHC formatted string looks like this:

```txt
$argon2id$v=19$m=65536,t=3,p=4$c29tZXNhbHQ$RdescudvJCsgt3ub+b+dWRWJTmaaJObG
```

For `firebase-scrypt` passwords, refer to the [Firebase Migration guide](/migrate/firebase) for an example of how to format the `password_hash`.

For `ssha` passwords, use the following algorithm:

1. Generate a `salt`: random bytes
2. Hash the user’s password and the `salt` using the SHA1 algorithm
3. Base64 encode the hash followed by the salt
4. Prepend the string with `{SSHA}`

A high-level representation is: `{SSHA}base64(sha1(password + salt) + salt)`.

Once imported, users can continue to sign-in with their existing password, **without** having to go through a password reset flow.

### Triggering password resets

If you are unable to export passwords from your existing data store, whether for security reasons or other limitations, you can programmatically trigger a password reset flow using the WorkOS [Password Reset API](/reference/authkit/password-reset).

This process can be initiated at any time, and doesn’t need to happen during the user import process.

Some applications may want to remove password-based authentication when switching to WorkOS, in favor of another method like Magic Auth. If this is the case for your application, you can skip dealing with passwords entirely.

### Migrating social auth users

If you have users who previously signed in using social auth providers, such as [Google](/integrations/google-oauth) or [Microsoft](/integrations/google-oauth), those users can continue to sign in with those providers after you’ve migrated to WorkOS.

Check out our [integrations](/integrations) page for guidance on configuring the relevant provider’s client credentials in WorkOS.

After your provider is configured in WorkOS, users can sign in with their provider credentials and will be automatically linked to a WorkOS user. WorkOS uses the **email address** from the social auth provider to determine this match.

> Some users may need to verify their email address through WorkOS if email verification is enabled in your WorkOS environment’s authentication settings.

Email verification behavior varies depending on whether the provider is known to verify email addresses. For example, users signing in using Google OAuth and a `gmail.com` email domain will not need to perform the extra verification step.

---

## (3) Handling interim new users

Many applications allow users to sign up at any time. If your app offers this feature, then you should consider the timing of your migration. If any users sign up after you’ve completed importing users into WorkOS, but before you’ve switched to WorkOS for authentication, then those users will have been omitted from the migration process.

There are two main strategies to handle this:

### (A) Disable signups during migration

The simplest solution is to schedule an appropriate time for the migration and disable signup while in progress. This may be done using temporary code added to your application and controlled by a feature flagging system.

After the migration is complete, your application should be updated to perform authentication using WorkOS, and the signup flag block disabled. This helps to ensure the export/import process captures all active users.

### (B) Use a dual-write strategy

For applications that want to avoid disabling signups, a “dual-write” strategy can be used.

![Diagram demonstrating the dual-write process.](https://images.workoscdn.com/images/656fbbac-adb1-4f99-b416-056d80e408ac.png?auto=format&fit=clip&q=80)[border=false]

When a new user signs-up, in addition to creating a user record in the existing user store, the application should also create a matching record in WorkOS using the [Create User API](/reference/authkit/user/create). As time passes, WorkOS will stay consistent with future new users, but a migration will still need to be performed for the historical set of users.

You will need to perform the same export and import process into WorkOS, but keeping in mind that some users will already exist in WorkOS as a result from the “dual-write”.

While this minimizes forms of downtime for your application, there are other complications. For example, if a user updates their email or authentication method, you will need to perform the same update in WorkOS, at least until the migration process is complete.

### Which to choose?

Your timeline for completing the migration, along with your user’s tolerances for disruption, will affect which strategy makes more sense for your application.

Disabling signups, or even sign-in entirely, and doing a “big-bang” migration by moving all users at the same time, could be reasonable for a smaller application. However, larger applications that are on the critical path for their customers may need a more careful path in order to provide consistent access.

## Wrapping-up

User management migration complexity can vary, so it is important to consider how existing application constraints will transfer to WorkOS. If you have any questions, reach out to [support@workos.com](mailto:support@workos.com) or via your team’s WorkOS Slack channel for more help planning your migration.

### Migrate from Firebase

Learn how to migrate users to WorkOS from Firebase.

## Introduction

The WorkOS AuthKit API allows you to migrate your existing user data from a variety of existing sources. In this guide, we'll walk through the steps to export your users from Firebase, and then import them into WorkOS.

## (1) Exporting Firebase user data

Firebase customers can export their user data using either the [Firebase CLI](https://firebase.google.com/docs/cli/auth#auth-export) or the [Firebase API](https://firebase.google.com/docs/reference). In this guide we’ll be using the Firebase CLI, use the following command to retrieve a dump of all users in JSON or CSV format.

```bash title="Exporting users with the Firebase CLI"
firebase auth:export --project= --format=json users.json
```

## (2) Importing users into WorkOS

After obtaining your user data from Firebase, it’s time to import it into WorkOS, mapping attributes from the [Firebase User format](https://firebase.google.com/docs/cli/auth#JSON) to WorkOS API parameters.

Using the WorkOS [Create User API](/reference/authkit/user/create), you can create a corresponding record in WorkOS for each exported user. Use the following mapping from the Firebase format to parameters in your WorkOS Create User API calls:

| Firebase        |     | WorkOS API       |
| --------------- | --- | ---------------- |
| `email`         | →   | `email`          |
| `emailVerified` | →   | `email_verified` |
| `displayName`   | →   | `first_name`     |
| `displayName`   | →   | `last_name`      |

### Importing passwords

If your users sign in to your Firebase application using passwords, you can choose to also import those password hashes. Firebase uses a [forked version of `scrypt`](https://firebaseopensource.com/projects/firebase/scrypt/) which can be directly imported during the [user creation](/reference/authkit/user/create) process into WorkOS, or later using the [Update User API](/reference/authkit/user/update).

First, retrieve your Firebase project's password hash parameters from the Firebase console following the [export documentation](https://firebase.google.com/docs/cli/auth#password_hash_parameters). These parameters are the `base64_signer_key`, `base64_salt_separator`, `rounds`, and `mem_cost`.

Next, retrieve the password salts and hashes for each of your individual Firebase users by running the [Firebase CLI `auth:export` command](https://firebase.google.com/docs/cli/auth#auth-export). Your Firebase users that have a password set will have a `passwordHash` and `salt` field present which will be imported into WorkOS.

Finally, you will need to format these parameters into a [PHC-compatible](https://github.com/P-H-C/phc-string-format/blob/5f1e4ec633845d43776849f503f8ce8314b5290c/phc-sf-spec.md) password hash following this Firebase to PHC hash parameter mapping:

| Firebase value          |     | PHC hash parameter |
| ----------------------- | --- | ------------------ |
| `base64_signer_key`     | →   | `sk`               |
| `base64_salt_separator` | →   | `ss`               |
| `rounds`                | →   | `r`                |
| `mem_cost`              | →   | `m`                |

The hash, salt, along with `sk` and `ss` parameters, should be [B64 encoded](https://github.com/P-H-C/phc-string-format/blob/5f1e4ec633845d43776849f503f8ce8314b5290c/phc-sf-spec.md#b64), which means trimming the `=` characters that represent base64 padding. Using a PHC-formatting library, like [`@phc/format`](https://www.npmjs.com/package/@phc/format) for Node, should handle this for you.



## Other authentication methods

Firebase authentication methods vary depending on your specific usage, and corresponding connections can be easily configured in WorkOS. This allows users to continue signing in with the same authentication methods, matching the previous sign in experience.

### Social Auth Providers

If your users “Sign in with Google” or similar, you can configure WorkOS to continue using those sign in methods. Migrating these connections involves providing the same client credentials (i.e. Client ID and Client Secret) to WorkOS as configured in Firebase.

For more details on supported connections, see the provider-specific integration guides, such as for [Microsoft](/integrations/microsoft-oauth) and [Google](/integrations/google-oauth).

Reach out to [support@workos.com](mailto:support@workos.com) if there are additional Social Auth providers you would like to see supported.

### Email Link

If your users sign in using [Email Link](https://firebase.google.com/docs/auth/web/email-link-auth), sometimes called “passwordless”, you can achieve the same experience by adding WorkOS [Magic Auth](/reference/authkit/magic-auth) to your application.

### OIDC and SAML

Enterprise authentication often uses standard protocols such as [OpenID Connect (OIDC)](https://firebase.google.com/docs/auth/web/openid-connect) or [SAML](https://firebase.google.com/docs/auth/web/saml) between your service and identity provider.

The same identity providers can be configured in WorkOS, preserving the sign in process familiar to your users. For specific instructions, see the guides on setting up [OIDC](/integrations/oidc) and [SAML](/integrations/saml) connections with WorkOS.

### Migrate from Descope

Learn how to migrate users and organizations from Descope.

## Introduction

The AuthKit API allows you to migrate your existing user data from a variety of existing sources. In this guide, we will walk through the steps to export, and then import your users from Descope.

---

## (1) Export Descope data

Descope allows you to export user data through their [Management API](https://docs.descope.com/api/management/users) or directly from the Descope console.

You can export user data programmatically using the [Search Users endpoint](https://docs.descope.com/management/user-management/user-exporting). The `searchAll()` function in the Descope Backend SDKs retrieves a comprehensive list of users. Submitting an empty request payload will return all users:

```bash
curl -X POST https://api.descope.com/v1/mgmt/user/search \
  -H 'Authorization: Bearer :' \
  -H 'Content-Type: application/json' \
  -d '{}'
```

Alternatively, you can export users directly from the [Descope console](https://docs.descope.com/management/user-management/user-exporting) by selecting users on the users page and clicking the "Export CSV" button.

### Exporting passwords

If your Descope users currently sign in using password-based authentication, and you'd like to import those passwords, you'll need to [contact Descope support](https://docs.descope.com/management/user-management/user-exporting).

Descope does not make hashed passwords available through their Backend APIs. After opening a support ticket, Descope can generate a CSV file containing your users' data including password hashes and facilitate a secure data transfer.

Descope supports multiple password hashing algorithms including bcrypt, argon2, pbkdf2, and others. When you receive the password export from Descope support, make note of which hashing algorithm was used, as you'll need this information when importing.

---

## (2) Import users into WorkOS

Once you've obtained the necessary export data from Descope, you can import your users into WorkOS using the WorkOS APIs.

### Using WorkOS APIs

With the data from Descope's user export, you can use the [Create User API](/reference/authkit/user/create) to import each user. The API is rate-limited, so for large migrations, you may want to implement batching with appropriate delays. You can view the [rate limits](/reference/rate-limits) documentation for more information.

Using the fields from the Descope export, use the following mapping from Descope to parameters in your Create User API calls:

| Descope         |     | WorkOS API       |
| --------------- | --- | ---------------- |
| `email`         | →   | `email`          |
| `givenName`     | →   | `first_name`     |
| `familyName`    | →   | `last_name`      |
| `verifiedEmail` | →   | `email_verified` |

Here's an example migration script:

### Import passwords

If you also exported passwords from Descope support, you can import them during the [user creation](/reference/authkit/user/create) process, or later using the [Update User API](/reference/authkit/user/update).

WorkOS supports the following password hashing algorithms that Descope uses:

- `bcrypt`
- `argon2`
- `pbkdf2`

When importing passwords, pass the following parameters to the WorkOS API based on the hash format Descope provided:

- The `password_hash_type` set to the appropriate algorithm (e.g., `'bcrypt'`, `'argon2'`, or `'pbkdf2'`)
- The `password_hash` set to the password hash value from your Descope export

For `argon2` and `pbkdf2` passwords, WorkOS expects the PHC string format. Refer to the [other services migration guide](/migrate/other-services/2-importing-users-into-workos/importing-passwords) for detailed formatting requirements for these hash types.

- | Without passwords

  ```typescript
  ;

  const workos = new WorkOS(process.env.WORKOS_API_KEY);

  async function migrateUsers(descopeUsers) {
    for (const user of descopeUsers) {
      try {
        // In the JavaScript SDK, the property names are camelCase
        const workosUser = await workos.userManagement.createUser({
          email: user.email,
          emailVerified: user.verifiedEmail,
          firstName: user.givenName,
          lastName: user.familyName,
        });

        console.log(`Migrated user: ${user.email} -> ${workosUser.id}`);
      } catch (error) {
        console.error(`Failed to migrate user ${user.email}:`, error);
      }
    }
  }
  ```

- | With passwords

  ```typescript
  ;

  const workos = new WorkOS(process.env.WORKOS_API_KEY);

  async function migrateUsersWithPasswords(descopeUsers) {
    for (const user of descopeUsers) {
      try {
        const workosUser = await workos.userManagement.createUser({
          email: user.email,
          emailVerified: user.verifiedEmail,
          firstName: user.givenName,
          lastName: user.familyName,
          // Include password hash if available from Descope export
          passwordHash: user.passwordHash,
          passwordHashType: user.passwordHashType, // 'bcrypt', 'argon2', or 'pbkdf2'
        });

        console.log(
          `Migrated user with password: ${user.email} -> ${workosUser.id}`,
        );
      } catch (error) {
        console.error(`Failed to migrate user ${user.email}:`, error);
      }
    }
  }
  ```

### Migrate social auth users

If you have users who previously signed in through Descope using social auth providers, such as [Google](/integrations/google-oauth) or [Microsoft](/integrations/microsoft-oauth), those users can continue to sign in with those providers after you've migrated.

Check out the [integrations](/integrations) page for guidance on configuring the relevant provider's client credentials.

After your provider is configured, users can sign in with their provider credentials and will be automatically linked to a WorkOS user. WorkOS uses the **email address** from the social auth provider to determine this match.

> Some users may need to verify their email address through WorkOS if email verification is enabled in your environment's authentication settings.

Email verification behavior varies depending on whether the provider is known to verify email addresses. For example, users signing in using Google OAuth and a `gmail.com` email domain will not need to perform the extra verification step.

---

## (3) Organizations

Descope has a concept of ["Tenants"](https://docs.descope.com/b2b) which are analogous to [WorkOS Organizations](/reference/organization), in that both represent a B2B customer or organization within your application.

### Creating Organizations

If you'd like to export your Descope tenants, you can use the [Descope Management API](https://docs.descope.com/management/tenant-management/sdks) to programmatically retrieve each tenant. You can then call the [Create Organization API](/reference/organization/create) to create matching Organizations in WorkOS.

When creating Organizations in WorkOS, you can map the following fields from Descope tenants:

| Descope Tenant |     | WorkOS Organization |
| -------------- | --- | ------------------- |
| `name`         | →   | `name`              |
| `id`           | →   | `external_id`       |

Storing the Descope tenant ID as the `external_id` in WorkOS can help you maintain a reference between the two systems during migration.

Here's an example migration script:

```typescript
;

const workos = new WorkOS(process.env.WORKOS_API_KEY);

async function migrateOrganizations(descopeTenants) {
  const orgIdMap = new Map();

  for (const tenant of descopeTenants) {
    try {
      const workosOrg = await workos.organizations.createOrganization({
        name: tenant.name,
        // Store the Descope tenant ID for reference
        externalId: tenant.id,
      });

      console.log(`Migrated organization: ${tenant.name} -> ${workosOrg.id}`);

      // Store this mapping for migrating user memberships later
      orgIdMap.set(tenant.id, workosOrg.id);
    } catch (error) {
      console.error(`Failed to migrate organization ${tenant.name}:`, error);
    }
  }

  return orgIdMap;
}
```

### Adding user memberships

Once you've created Organizations in WorkOS, you can add users to their respective organizations using the [Organization Membership API](/reference/authkit/organization-membership/create).

In Descope, users can be associated with tenants, and this information is available when you export users via the Search Users API. Use this tenant association data to create the corresponding organization memberships in WorkOS.

RBAC capabilities are available through [roles and permissions](/authkit/roles-and-permissions). When migrating, identify your roles defined in Descope, then create equivalent roles in [the dashboard](https://dashboard.workos.com/environment/roles-and-permissions), and assign roles during migration by specifying the `roleSlug` parameter when creating organization memberships.

```typescript
async function migrateMemberships(descopeUserTenants, orgIdMap, userIdMap) {
  for (const userTenant of descopeUserTenants) {
    const orgId = orgIdMap.get(userTenant.tenantId);
    const userId = userIdMap.get(userTenant.userId);

    if (!orgId || !userId) {
      console.error(`Missing mapping for user-tenant relationship`);
      continue;
    }

    try {
      await workos.userManagement.createOrganizationMembership({
        userId: userId,
        organizationId: orgId,
        // Map Descope roles to WorkOS roles as needed
        roleSlug: userTenant.roleNames?.[0] || 'member',
      });

      console.log(`Migrated membership: ${userId} -> ${orgId}`);
    } catch (error) {
      console.error(`Failed to migrate membership:`, error);
    }
  }
}
```

---

## (4) Special considerations

There are some differences between the authentication strategies offered by Descope and WorkOS that you should be aware of when planning your migration.

### Multi-Factor Auth

Descope supports SMS-based one-time passwords (OTP) for authentication and multi-factor auth. However, WorkOS does not support SMS-based second factors due to known security issues with SMS.

Users who have SMS-based authentication or second factors will need to switch to using [email-based Magic Auth](/authkit/magic-auth), or re-enroll in MFA using a [TOTP-based authenticator](/authkit/mfa) instead.

### Passkeys and advanced authentication

Descope supports [passkeys](https://docs.descope.com/auth-methods/passkeys) (WebAuthn) for passwordless authentication. [Passkey authentication](/authkit/passkeys) is also available through AuthKit's hosted UI, using the WebAuthn standard. Passkeys offer:

- **Progressive enrollment**: Users with password-based accounts can be prompted to create passkeys
- **MFA integration**: Passkeys serve as both first and second factors when MFA is enabled
- **Secure authentication**: Using biometric or PIN verification on the user's device

Note that passkey authentication is currently available through the hosted UI. You'll need to configure a custom domain for your AuthKit environment before enabling passkeys in production.

Descope also offers other authentication methods like Magic Links and Enchanted Links. [Magic Auth](/authkit/magic-auth) delivers a similar passwordless email-based authentication experience.

### Enterprise SSO and SCIM

Both Descope and WorkOS provide robust enterprise authentication features. If you're currently using Descope's [SSO](https://docs.descope.com/auth-methods/sso) or [SCIM provisioning](https://docs.descope.com/b2b/scim) features, WorkOS offers equivalent capabilities:

- [Single Sign-On (SSO)](/sso) - Support for SAML and OIDC providers
- [Directory Sync](/directory-sync) - SCIM-based user provisioning from identity providers

When migrating enterprise customers who use SSO, you'll need to coordinate with them to reconfigure their Identity Provider (IdP) to point to WorkOS instead of Descope. WorkOS provides [comprehensive documentation](/sso) for setting up SSO connections with various providers.

### Account linking behavior

Descope has account linking capabilities that automatically link social accounts with matching verified email addresses. WorkOS also supports automatic account linking based on email addresses. When migrating users who have multiple linked accounts in Descope (e.g., password + Google OAuth), you should:

1. Import the user once with their primary email
2. Configure the relevant social providers
3. When users sign in with their social provider, they will automatically be linked with the accounts based on email match

### Handling interim new users

If your application allows users to sign up at any time, you should [consider the timing of your migration](/migrate/other-services/3-handling-interim-new-users). Users who sign up after you've exported data from Descope but before you've switched to WorkOS for authentication will be omitted from the migration.

There are two main strategies to handle this:

#### (A) Disable signups during migration

Schedule an appropriate time for the migration and temporarily disable signup functionality. This can be controlled using a feature flag in your application. After the migration is complete and your application is using WorkOS for authentication, re-enable signups.

#### (B) Use a dual-write strategy

For applications that cannot disable signups, implement a "dual-write" strategy. When a new user signs up, create records in both your Descope project and WorkOS using the [Create User API](/reference/authkit/user/create). This keeps WorkOS synchronized with new users, though you'll still need to perform the historical user migration. Be aware that you'll need to keep user updates (email changes, password changes) synchronized between both systems until the migration is complete.

---

## Next steps

With your users now imported, you can start using WorkOS to manage authentication for your application. If you haven't already, take a look at the [AuthKit Quick Start guide](/authkit) to learn how to integrate AuthKit into your application.

### Migrate from Clerk

Learn how to migrate users and organizations from Clerk.

## Introduction

The WorkOS AuthKit API allows you to migrate your existing user data from a variety of existing sources. In this guide, we will walk through the steps to export, and then import your users from Clerk.

---

## (1) Export Clerk user data

Clerk allows for exporting user data [directly from their API](https://clerk.com/docs/deployments/exporting-users) using their Backend SDK.

### Export passwords

If your Clerk users currently sign in using password-based authentication, and you'd like to import those passwords into WorkOS, then you'll need to use the [Clerk backend API](https://clerk.com/changelog/2024-10-23-export-users) to export them with your user data as a CSV file.

> Clerk does not make the plaintext passwords available for export.

---

## (2) Import users into WorkOS

Once you’ve obtained the necessary export files, you have two options for importing your user data into WorkOS.

### (A) Using the WorkOS import tool

WorkOS has a public [GitHub repository](https://github.com/workos/migrate-clerk-users) containing code that can be run to import users into WorkOS using the data retrieved from Clerk support in the previous step.

If you’d rather write your own code, or if you chose to not export data via Clerk support, the same process can be completed using the public WorkOS APIs, as described below.

### (B) Using WorkOS APIs

Using the data either from the Clerk API or from a JSON file received from their support team, you can use the WorkOS API to [create users](/reference/authkit/user/create) during the import. Keep in mind that user creation is rate-limited. You can view the docs on the [rate limits](/reference/rate-limits) for more information.

Using the default fields from the [Clerk export](https://clerk.com/docs/deployments/exporting-users), use the following mapping from Clerk to parameters in your WorkOS Create User API calls:

| Clerk             |     | WorkOS API   |
| ----------------- | --- | ------------ |
| `email_addresses` | →   | `email`      |
| `first_name`      | →   | `first_name` |
| `last_name`       | →   | `last_name`  |

### Handle users with multiple email addresses

In the case of a user with multiple email addresses, Clerk separates them with a pipe symbol:

```json
"email_addresses": "john@example.com|john.doe@example.com",
```

Unfortunately there's no way to know which email is the primary one from the export alone. Clerk does expose this information by retrieving the [User object from their API](https://clerk.com/docs/references/javascript/user/user#properties).

### Import passwords

If you also exported passwords from Clerk, you can import them during the [user creation](/reference/authkit/user/create) process, or later using the WorkOS [Update User API](/reference/authkit/user/update).

Clerk uses the `bcrypt` password hashing algorithm, which is supported by WorkOS. Make sure to pass the following parameters to the WorkOS API:

- The `password_hash_type` set to `'bcrypt'`
- The `password_hash` set to the `password_digest` field from your Clerk export

### Migrate social auth users

If you have users who previously signed in through Clerk using social auth providers, such as [Google](/integrations/google-oauth) or [Microsoft](/integrations/google-oauth), those users can continue to sign in with those providers after you’ve migrated to WorkOS.

Check out our [integrations](/integrations) page for guidance on configuring the relevant provider’s client credentials in WorkOS.

After your provider is configured in WorkOS, users can sign in with their provider credentials and will be automatically linked to a WorkOS user. WorkOS uses the **email address** from the social auth provider to determine this match.

---

## (3) Create organizations

Clerk’s [organizations](https://clerk.com/docs/organizations/overview) are analogous to WorkOS [organizations](/reference/organization) – both represent a B2B customer.

### Creating Organizations

If you’d like to export your Clerk organizations, you can use the [Clerk Backend SDK](https://clerk.com/docs/references/backend/organization/get-organization-list) to programmatically paginate through each organization. You can then use the WorkOS API to [create matching organizations](/reference/organization/create).

### Adding user memberships

You can export Clerk organization memberships using Clerk’s [Backend SDK](https://clerk.com/docs/references/backend/organization/get-organization-membership-list), and then use the WorkOS [Organization Membership API](/reference/authkit/organization-membership/create) to add each user to their respective organization.

---

## (4) Multi-Factor Auth

There are some differences between the MFA strategies offered by Clerk and WorkOS.

Clerk supports SMS-based second factors, however WorkOS does not due to known security issues with SMS. Users who have SMS-based second factors will need to switch to using email-based Magic Auth, or re-enroll in MFA using a TOTP-based authenticator instead. See the [MFA guide](/authkit/mfa) for more information on enrolling users.

---

## Next steps

After the import, you can now start using WorkOS to manage your users. If you haven't, take a look at our [Quick Start guide](/authkit) to learn how to integrate WorkOS AuthKit into your application.

### Migrate from Better Auth

Learn how to migrate users and organizations from Better Auth.

## Introduction

You can migrate your existing user data from a variety of sources into WorkOS using the AuthKit API. This guide will walk you through the steps to export your data from Better Auth, and import into WorkOS.

---

## (1) Export Better Auth data

Better Auth stores user data directly in your database, which means you have full control over exporting your data. Unlike hosted authentication services, Better Auth does not provide a built-in export tool, but you can access your data directly through your database.

### Accessing your database

Better Auth uses [multiple database tables](https://www.better-auth.com/docs/concepts/database) to store authentication data. The main tables you'll need to export are:

- **user**: Contains core user information (`id`, `name`, `email`, `emailVerified`, `image`, timestamps)
- **account**: Stores provider-specific authentication data, including password hashes for credential-based accounts
- **organization**: Available when using the [organization plugin](https://www.better-auth.com/docs/plugins/organization)
- **member**: Mapping of users (and their roles) to organizations

You can export this data using your database's native export tools, your ORM (for example, Prisma), or direct SQL queries.

### Exporting user data

To export users, query the `user` table directly.

```sql
SELECT * FROM user;
```

You can export this data to JSON, CSV, or any format that works for your migration script.

### Exporting passwords

Better Auth stores password hashes in the `account` table with `providerId` set to `'credential'`. The passwords are hashed using [scrypt by default](https://www.better-auth.com/docs/authentication/email-password), though Better Auth supports custom hashing functions.

To export password hashes, query the `account` table:

```sql
SELECT userId, password
FROM account
WHERE providerId = 'credential';
```

If you're using a custom password hashing algorithm in Better Auth, make note of the algorithm for the import step. The default is `scrypt`, which is supported by WorkOS.

---

## (2) Import users into WorkOS

Once you've exported your user data from Better Auth, you can import it into WorkOS using the WorkOS APIs.

### Using WorkOS APIs

With the data from your Better Auth database, you can use the [Create User API](/reference/authkit/user/create) to import each user. The API is rate-limited, so for large migrations, you may want to implement batching with appropriate delays. You can view the [rate limits](/reference/rate-limits) documentation for more information.

Using the Better Auth user table schema, use the following mapping to Create User API parameters:

| Better Auth     |     | WorkOS           |
| --------------- | --- | ---------------- |
| `email`         | →   | `email`          |
| `emailVerified` | →   | `email_verified` |
| `name`          | →   | `first_name`     |
| `name`          | →   | `last_name`      |
| `image`         | →   | (not supported)  |

> Better Auth stores a single `name` field, while WorkOS has separate `first_name` and `last_name` fields. You'll need to parse the name field or use it entirely for `first_name`.

Here's an example migration script:

```typescript
;

const workos = new WorkOS(process.env.WORKOS_API_KEY);

async function migrateUsers(betterAuthUsers) {
  for (const user of betterAuthUsers) {
    // Parse name into first and last name if possible
    const [firstName, ...lastNameParts] = user.name.split(' ');
    const lastName = lastNameParts.join(' ') || undefined;

    try {
      // In the JavaScript SDK, the property names are camelCase
      const workosUser = await workos.userManagement.createUser({
        email: user.email,
        emailVerified: user.emailVerified,
        firstName: firstName,
        lastName: lastName,
      });

      console.log(`Migrated user: ${user.email} -> ${workosUser.id}`);
    } catch (error) {
      console.error(`Failed to migrate user ${user.email}:`, error);
    }
  }
}
```

### Importing passwords

If you exported password hashes from Better Auth, you can import them during the [user creation](/reference/authkit/user/create) process, or later using the [Update User API](/reference/authkit/user/update).

Better Auth uses `scrypt` as the default password hashing algorithm, which is supported by WorkOS. Make sure to pass the following parameters:

- The `password_hash_type` set to `'scrypt'`
- The `password_hash` set to the password hash value from your Better Auth `account` table

The password hash should be in PHC string format. If Better Auth is storing raw scrypt hashes, you'll need to convert them to PHC format. See the [other services migration guide](/migrate/other-services/2-importing-users-into-workos/importing-passwords) for detailed information about PHC format parameters for scrypt.

If you configured Better Auth to use a different password hashing algorithm, such as bcrypt, argon2, or pbkdf2, WorkOS supports these as well. Refer to the [password hash types](/migrate/other-services/2-importing-users-into-workos/importing-passwords) documentation for format requirements.

### Migrating social auth users

If you have users who previously signed in through Better Auth using social auth providers, such as [Google](/integrations/google-oauth) or [Microsoft](/integrations/microsoft-oauth), those users can continue to sign in with those providers after you've migrated.

Better Auth stores social auth accounts in the `account` table with different `providerId` values (e.g., `'google'`, `'github'`, `'microsoft'`). These accounts are linked to users via the `userId` field.

Check out our [integrations](/integrations) page for guidance on configuring the relevant provider's client credentials. After your provider is configured, users can sign in with their provider credentials and will be automatically linked to a user. The **email address** from the social auth provider is used to determine this match.

> Some users may need to verify their email address through WorkOS if email verification is enabled in your environment's authentication settings.

Email verification behavior varies depending on whether the provider is known to verify email addresses. For example, users signing in using Google OAuth and a `gmail.com` email domain will not need to perform the extra verification step.

---

## (3) Organizations

Better Auth has an [organization plugin](https://www.better-auth.com/docs/plugins/organization) that allows you to manage organization members and teams. If you're using this plugin, you can migrate your organizations to WorkOS, which has native support for [Organizations](/reference/organization) as a core B2B feature.

### Creating Organizations

Better Auth stores organizations in an `organization` table with fields like `id`, `name`, `slug`, `logo`, and `metadata`. To migrate these, you'll need to:

1. Export organizations from your Better Auth database:

```sql
SELECT * FROM organization;
```

2. Create matching organizations using the [Create Organization API](/reference/organization/create):

```typescript
;

const workos = new WorkOS(process.env.WORKOS_API_KEY);

async function migrateOrganizations(betterAuthOrgs) {
  for (const org of betterAuthOrgs) {
    try {
      const workosOrg = await workos.organizations.createOrganization({
        name: org.name,
        // You may want to store the Better Auth slug in organization metadata
        metadata: {
          betterAuthSlug: org.slug,
        },
      });

      console.log(`Migrated organization: ${org.name} -> ${workosOrg.id}`);

      // Store this mapping for migrating user memberships later
      orgIdMap.set(org.id, workosOrg.id);
    } catch (error) {
      console.error(`Failed to migrate organization ${org.name}:`, error);
    }
  }
}
```

### Adding organization memberships

Better Auth stores organization memberships in a `member` table that links users (and their roles) to organizations.

```sql
SELECT * FROM member;
```

Then use the [Organization Membership API](/reference/authkit/organization-membership/create) to add each user to their respective organization.

WorkOS offers RBAC capabilities through [roles and permissions](/authkit/roles-and-permissions). When migrating, identify your roles defined in Better Auth, then create equivalent roles in the WorkOS Dashboard, and assign roles during migration by specifying the `roleSlug` parameter when creating organization memberships. If your Better Auth implementation uses complex RBAC policies with custom resources and actions, you may need to simplify to standard roles or implement custom authorization in your application logic.

```typescript
async function migrateMemberships(betterAuthMemberships, orgIdMap, userIdMap) {
  for (const membership of betterAuthMemberships) {
    const orgId = orgIdMap.get(membership.organizationId);
    const userId = userIdMap.get(membership.userId);

    if (!orgId || !userId) {
      console.error(`Missing mapping for membership: ${membership.id}`);
      continue;
    }

    try {
      await workos.userManagement.createOrganizationMembership({
        userId: userId,
        organizationId: orgId,
        // Better Auth uses custom role strings; map these to WorkOS roles as needed
        roleSlug: getRole(membership.role),
      });

      console.log(`Migrated membership: ${membership.userId} -> ${orgId}`);
    } catch (error) {
      console.error(`Failed to migrate membership:`, error);
    }
  }
}
```

### Migrating teams

If you're using the teams feature within Better Auth (an optional hierarchical level within organizations), note that there is not a directly corresponding "teams" concept. However, you have several options:

1. **Convert to organizations**: Create separate organizations for each Better Auth team
2. **Use organization metadata**: Store team information in organization metadata
3. **Use RBAC roles**: Represent team membership through custom roles in [role-based access control](/rbac/quick-start)

For most B2B applications, flattening teams into separate organizations provides the cleanest migration path and takes full advantage of enterprise features like SSO and Directory Sync, which operate at the organization level.

---

## (4) Special considerations

There are several differences between Better Auth and WorkOS that you should be aware of during migration.

### Multi-Factor Authentication

Better Auth offers a [Two-Factor Authentication plugin](https://www.better-auth.com/docs/plugins/2fa) that supports TOTP-based authenticators. If your Better Auth users have enrolled in 2FA, they will need to re-enroll in MFA after migrating, as MFA secrets cannot be migrated for security reasons. See the [MFA guide](/authkit/mfa) for information on enrolling users in MFA.

> WorkOS does not support SMS-based factors due to known security vulnerabilities with SMS.

### Account linking behavior

Better Auth has sophisticated [account linking capabilities](https://www.better-auth.com/docs/concepts/users-accounts#account-linking) that automatically link social accounts with matching verified email addresses. WorkOS also supports automatic account linking based on email addresses. When migrating users who have multiple linked accounts in Better Auth (e.g., password + Google OAuth), you should:

1. Import the user once with their primary email
2. Configure the relevant social providers
3. When users sign in with their social provider, they will automatically be linked with the accounts based on email match

### Handling interim new users

If your application allows users to sign up at any time, you should [consider the timing of your migration](/migrate/other-services/3-handling-interim-new-users). Users who sign up after you've exported data from Better Auth but before you've switched to WorkOS for authentication will be omitted from the migration.

There are two main strategies to handle this:

#### (A) Disable signups during migration

Schedule an appropriate time for the migration and temporarily disable signup functionality. This can be controlled using a feature flag in your application. After the migration is complete and your application is using WorkOS for authentication, re-enable signups.

#### (B) Use a dual-write strategy

For applications that cannot disable signups, implement a "dual-write" strategy. When a new user signs up, create records in both your Better Auth database and WorkOS using the [Create User API](/reference/authkit/user/create). This keeps WorkOS synchronized with new users, though you'll still need to perform the historical user migration. Be aware that you'll need to keep user updates (email changes, password changes) synchronized between both systems until the migration is complete.

### Database-specific considerations

Since Better Auth stores data in your own database, you have flexibility in how you structure the migration:

- You can keep Better Auth tables in your database during a transition period
- Consider implementing a gradual rollout where some users authenticate via WorkOS while others continue using Better Auth
- Database schema is extensible, so custom fields will need to be handled separately (consider using [user metadata](/authkit/metadata) for custom data)

---

## Next steps

With your users and organizations now imported, you can start using WorkOS to manage authentication for your application. If you haven't already, take a look at our [Quick Start guide](/authkit) to learn how to integrate AuthKit into your application.

These enterprise-ready features go beyond basic authentication:

- **[Single Sign-On](/sso)**: Enable SAML and OIDC SSO for enterprise customers
- **[Directory Sync](/directory-sync)**: Automatically provision and deprovision users from identity providers
- **[Admin Portal](/admin-portal)**: Allow your customers to self-serve SSO and Directory Sync configuration
- **[Audit Logs](/audit-logs)**: Track security-relevant events in your application

If you have questions about your migration or need assistance, reach out to [support@workos.com](mailto:support@workos.com).

### Migrate from AWS Cognito

Learn how to migrate users to WorkOS from AWS Cognito.

## Introduction

The WorkOS AuthKit API allows you to migrate your existing user data from a variety of existing sources. In this guide, we’ll walk through the steps to export, and then import your users from AWS Cognito.

> AWS Cognito does not offer exports of user password hashes or MFA keys. This means that your imported users will need to reset their passwords and reconfigure any required MFA.

## (1) Exporting Cognito user data

User data in an AWS Cognito User Pool can be exported using the AWS CLI’s [list-users command](https://docs.aws.amazon.com/cli/latest/reference/cognito-idp/list-users.html).

To retrieve the first page of results, use the command:

```bash title="List users using the Cognito CLI"
aws cognito-idp list-users --user-pool-id  --region 
```

Add the `--pagination-token ` argument to paginate subsequent requests:

```bash title="export-aws-cognito-users.sh"
#!/bin/bash
user_pool_id=""
region=""
output_dir="cognito_exports"
file_index=1

mkdir -p "$output_dir"

export_users() {
  aws cognito-idp list-users --user-pool-id "$user_pool_id" --region "$region" $1 | \
  jq '.' > "$output_dir/users_$2.json"
}

next_token=""
while true; do
  next_token=$(export_users "${next_token:+--pagination-token $next_token}" "$file_index" | jq -r '.PaginationToken // empty')
  [ -z "$next_token" ] && break
  ((file_index++))
done
echo "Export complete."
```

## (2) Importing users into WorkOS

After obtaining your user data from Cognito, it’s time to import them into WorkOS, mapping attributes from the AWS Cognito User format to WorkOS API parameters.

```json title="Example AWS Cognito list-users response object"
{
  "Users": [
    {
      "Username": "22704aa3-fc10-479a-97eb-2af5806bd327",
      "Enabled": true,
      "UserStatus": "FORCE_CHANGE_PASSWORD",
      "UserCreateDate": 1548089817.683,
      "UserLastModifiedDate": 1548089817.683,
      "Attributes": [
        {
          "Name": "sub",
          "Value": "22704aa3-fc10-479a-97eb-2af5806bd327"
        },
        {
          "Name": "family_name",
          "Value": "Mouse"
        },
        {
          "Name": "given_name",
          "Value": "Mickey"
        },
        {
          "Name": "email_verified",
          "Value": "true"
        },
        {
          "Name": "email",
          "Value": "mary@example.com"
        }
      ]
    }
  ]
}
```

Using the WorkOS [Create User API](/reference/authkit/user/create), you can create a corresponding record in WorkOS for each exported user. Use the following mapping from the AWS Cognito object to parameters in your WorkOS Create User API calls:

| AWS Cognito     |     | WorkOS API       |
| --------------- | --- | ---------------- |
| `email`         | →   | `email`          |
| `emailVerified` | →   | `email_verified` |
| `given_name`    | →   | `first_name`     |
| `family_name`   | →   | `last_name`      |

> Migrated users **must reset their passwords** before they can sign in.

### Triggering password resets

It’s important to have a strategy for triggering password resets after importing your users into WorkOS. You may want to ask users to reset their password the next time they attempt to sign in, or proactively send them password reset emails.

In either case, you can trigger the password reset flow by using the WorkOS [Send Password Reset Email API](/reference/authkit/password-reset/create).

## Other authentication methods

In addition to migrating username and password users to WorkOS, you can migrate users who authenticate using third-party identity providers, such as Google, without re-obtaining access.

Ensure you use the same credentials (i.e. Client ID and Client Secret) in WorkOS as those used for your connection in AWS Cognito.

For OAuth providers, you will need to add WorkOS as an additional Redirect URI. See the [Google OAuth integration guide](/integrations/google-oauth/customize-google-oauth-domain-optional/3-add-new-redirect-uri-to-google) as an example of what this process looks like.

### Migrate from Auth0

Learn how to migrate users and organizations from Auth0.

## Introduction

The WorkOS AuthKit API allows you to migrate your existing user data from a variety of existing sources. In this guide, we will walk through the steps to export, and then import your users from Auth0.

## (1) Exporting Auth0 user data

Auth0 allows their customers to export user data using several tools, which are outlined in [Auth0’s export documentation](https://auth0.com/docs/troubleshoot/customer-support/manage-subscriptions/export-data). A combination of exports may be necessary to retrieve all of the desired user information, including passwords.

The first tool is [Auth0’s “Bulk User Export” jobs](https://auth0.com/docs/manage-users/user-migration/bulk-user-exports). These export jobs can be created programmatically using the [Auth0 Management API](https://auth0.com/docs/api/management/v2/jobs/post-users-exports), or through the official [Auth0 "User Import / Export Extension"](https://auth0.com/docs/customize/extensions/user-import-export-extension).

In both cases, an Auth0 customer can request which fields they’d like exported for each user, with the final output of the process being a newline-delimited JSON
file.

### Exporting passwords

If your Auth0 users currently sign-in using password-based authentication, and you’d like to import those passwords into WorkOS, then you will need to [contact Auth0 support](https://auth0.com/docs/troubleshoot/customer-support).

After opening a ticket with Auth0, it can take up to a week or more for your request to be processed. At the end you’ll be given another newline-delimited JSON file, containing a subset of user data such as ID, but more importantly the password hash.

> Auth0 does not make the plaintext passwords available for export.

---

## (2) Importing Users into WorkOS

Once you’ve obtained the necessary export files, you have two options for importing your user data into WorkOS.

### (A) Using the WorkOS import tool

WorkOS has a public [GitHub repository](https://github.com/workos/migrate-auth0-users) containing code that can be run to import users into WorkOS using the data retrieved in the previous step.

If you’d rather write your own code, the same process can be completed using the public WorkOS APIs, as described below.

### (B) Using WorkOS APIs

With the data from Auth0’s “Bulk User Export” job, you can use the WorkOS [Create User API](/reference/authkit/user/create) to import each of the users. Using the default fields from the [Auth0 export](https://auth0.com/docs/customize/extensions/user-import-export-extension#export-users), use the following mapping from Auth0 to parameters in your WorkOS Create User API calls:

| Auth0          |     | WorkOS API       |
| -------------- | --- | ---------------- |
| Email          | →   | `email`          |
| Email Verified | →   | `email_verified` |
| Given Name     | →   | `first_name`     |
| Family Name    | →   | `last_name`      |

### Importing passwords

If you also exported passwords from Auth0, you can import them during the [user creation](/reference/authkit/user/create) process, or later using the WorkOS [Update User API](/reference/authkit/user/update).

Auth0 uses the `bcrypt` password hashing algorithm, which is supported by WorkOS. Make sure to pass the following parameters to the WorkOS API:

- The `password_hash_type` set to `'bcrypt'`
- The `password_hash` set to the `passwordHash` field from your Auth0 export

### Migrating social auth users

If you have users who previously signed in through Auth0 using social auth providers, such as [Google](/integrations/google-oauth) or [Microsoft](/integrations/google-oauth), those users can continue to sign in with those providers after you’ve migrated to WorkOS.

Check out our [integrations](/integrations) page for guidance on configuring the relevant provider’s client credentials in WorkOS.

After your provider is configured in WorkOS, users can sign in with their provider credentials and will be automatically linked to a WorkOS user. WorkOS uses the **email address** from the social auth provider to determine this match.

> Some users may need to verify their email address through WorkOS if email verification is enabled in your WorkOS environment’s authentication settings.

Email verification behavior varies depending on whether the provider is known to verify email addresses. For example, users signing in using Google OAuth and a `gmail.com` email domain will not need to perform the extra verification step.

---

## Organizations

Auth0 has a concept of [“Organizations”](https://auth0.com/docs/manage-users/organizations) which are analogous to [WorkOS Organizations](/reference/organization), in that both represent a B2B customer.

### Creating Organizations

If you’d like to export your Auth0 organizations, you can use the [Auth0 Management API](https://auth0.com/docs/api/management/v2/organizations/get-organizations) to programmatically paginate through each Organization. You can then call the WorkOS [Create Organization API](/reference/organization/create) to create matching Organizations in WorkOS.

### Adding user memberships

You can export Auth0 organization memberships using Auth0’s “Bulk User Export” as described in the [Exporting Auth0 user data](/migrate/auth0/1-exporting-auth0-user-data) step, and then use the WorkOS [Organization Membership API](/reference/authkit/organization-membership/create) to add each user to their respective organization.

## Multi-Factor Auth

There are some differences between the Multi-Factor Auth (MFA) strategies offered by Auth0 and WorkOS.

Auth0 supports SMS-based second factors, however WorkOS does not due to known security issues with SMS. Users who have SMS-based second factors will need to switch to using email-based Magic Auth, or re-enroll in MFA using a TOTP-based authenticator instead.

## Wrapping-up

With your users now imported, you can now start using WorkOS to manage your Auth0 users. If you haven't, take a look at our [Quick Start guide](/authkit) to learn how to integrate WorkOS AuthKit into your application.


## Multi-Factor Auth {#mfa}

### Multi-Factor Authentication

A composable API for implementing multi-factor authentication.

## Introduction

The Multi-Factor Authentication (MFA) API is intended to be a composable, unopinionated set of endpoints that can be integrated into existing application/session management strategies.

The available types of authentication factors are:

- `totp` – Time-based one-time password
- `sms` – One-time password via SMS message

> The MFA API is not intended to be used with the WorkOS SSO feature. It’s recommended to leverage the MFA features of the Identity Provider that is powering your SSO implementation.

## What you’ll build

In this guide, we’ll walk you through the process of enrolling new authentication factors for a user, and the challenge/verification process for existing authentication factors.

This guide will show you how to:

1. Create an Authentication Factor
2. Challenge the Authentication Factor
3. Verify the Challenge

## Before getting started

To get the most out of this guide, you’ll need:

- A [WorkOS account](https://dashboard.workos.com/)

## API object definitions

[Authentication Factor](/reference/mfa/authentication-factor)
: A factor of authentication that can be used in conjunction with a primary factor to provide multiple factors of authentication.

[Authentication Challenge](/reference/mfa/authentication-challenge)
: A request for an Authentication Factor to be verified.

## (1) Create an Authentication Factor

We’ll first need to enroll a new Authentication Factor.

### Install the WorkOS SDK

WorkOS offers native SDKs in several popular programming languages. Choose a language below to see instructions in your application’s language.



### Set secrets

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.

```plain title="Environment variables"
WORKOS_API_KEY='sk_example_123456789'
WORKOS_CLIENT_ID='client_123456789'
```

### Enroll the Authentication Factor

- | Using TOTP

  Use the TOTP type when the user is using a third-party authenticator app such as Google Authenticator or Authy.

  

  The response returns a `qr_code` and a secret. The `qr_code` value is a base64 encoded data URI that is used to [display the QR code](https://css-tricks.com/data-uris/) in your application for enrollment with an authenticator application.

  The `secret` can be entered into some authenticator applications in place of scanning a QR code.

- | Using SMS

  Use the SMS type when the user wants to receive one time passwords as SMS messages to their mobile device.

  Phone number must be valid. An error will be returned for malformed or invalid phone numbers.

  

Now that we’ve successfully created an authentication factor, we’ll need to save the ID for later use. It’s recommended that you persist the factor ID in your own user model according to your application’s needs.

## (2) Challenge the Authentication Factor

Next we’ll initiate the authentication process for the newly created factor which we’ll refer to as a challenge.

- | Create Authentication Challenge

  

- | Sending Custom SMS Message

  When challenging an SMS authentication factor, you can pass an optional SMS template to customize the SMS message that is sent to the end user. Use the `{{code}}` token to inject the one time password into the message.

  

Now that we’ve successfully challenged the authentication factor, we’ll need to save the challenge ID for the last step, challenge verification.

## (3) Verify the Challenge

The last step in the authentication process is to verify the one time password provided by the end-user.



### Verification Response

If the challenge is successfully verified `valid` will return `true`. Otherwise it will return `false` and another verification attempt must be made.



### Already Verified Error

If a challenge was already successfully verified, it cannot be used a second time. If further verification is needed in your application, create a new challenge.



### Expired Error

For SMS authentication factors, challenges are only available for verification for 10 minutes. After that they are expired and cannot be verified.



We’ve now successfully verified an end-user’s authentication factor. This authentication factor can now be used as a second factor of authentication in your application’s existing authentication strategy.

The ID of the authentication factor should be persisted in your application for future authentication challenges.

### Example Apps

View sample Multi-Factor Auth apps for each SDK.

You can view minimal example apps that demonstrate how to use the WorkOS SDKs to authenticate users via MFA:


  
  
  
  
  
  
  
  
  
</ExampleApps.Root>

### Sign-In UX

User experience considerations for MFA sign-in.

## Introduction

Once a user has setup two-factor authentication, their sign-in process will be different from the standard sign-in flow. This guide will walk you through the adjustments you need to make to support this in your application.

## Prompt user to verify the extra factor

At the very least, assuming the user has enrolled in one method (e.g. SMS/Text message) you should present the user with a new screen for the extra verification step after they have entered their username and password.



## When the user has enrolled in multiple methods

If the user has enrolled in multiple methods, consider including both methods in the verification step after they have entered their username and password. Following what we discussed in the [enrollment guide](mfa/ux/enrollment/let-users-choose-their-primary-method), consider presenting the user with their primary method first as well as letting them switch.



---

## Full interactive UI example

The following interactive example shows a full UI for signing-in using MFA encompassing all the considerations mentioned above.

### Enrollment UX

User experience considerations for MFA enrollment.

## Introduction

Now that we've seen how the MFA APIs work, you may want to consider how you want to present the MFA enrollment experience to your users. This guide will cover some of the considerations you should take into account when designing your enrollment experience.

## Provide multiple methods

The MFA APIs support multiple methods of authentication. Consider providing your users with multiple options for enrolling in MFA. Adding flexibility will reduce friction in users adoption.



## Let users choose their primary method

If a user has enrolled in multiple methods, consider letting them select a primary. This will allow you to challenge them with the method they are most comfortable, whilst still benefiting from the security of a backup in case they lose access.



## Setup a `totp` factor accessibly

As we have previously seen, [when enrolling a `totp` factor using the MFA API](mfa/1-create-an-authentication-factor/enroll-the-authentication-factor), the response returns a `qr_code` and a `secret`.

The `qr_code` value can be passed directly to the source on an image tag as follows:



However, some users may not be able to scan the QR code. Consider providing the `secret` value in the UI as an alternate way to set up their authenticator app.



Additionally, consider describing the QR code for assistive technologies:



## Interoperable one-time-passcode input

In order to make the experience as smooth as possible for your users, there are a few things to consider regarding the input they will use to fill in their one-time-passcode.

### Provide the right affordance

You may be tempted to use [a number input](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/number) as it will show the mobile keyboard for numbers only. This is not recommended because a browser expects a number input to be countable, rather than a sequence of multiple numbers, which can cause unexpected behavior.

Instead, we recommend using a text input (`type="text"`) with the `inputmode="numeric"` attribute to provide mobile devices with the expected numerical keyboard prompt.

### Autofill

Setting `autocomplete="one-time-code"` will enable autofill with in any user-agent that supports it. This will for example ensure Safari on iOS/MacOS can suggest/auto-fill the one-time-code received via SMS.

Consider also submitting the form automatically as soon as the passcode length has been met. This should help reduce the friction of using two-factor authentication for your users.

### Validation

Consider using client-side validation to ensure the user enters a valid one-time-passcode. This will reduce the number of requests to the server and improve the user experience.

`pattern="^\d{6}$"` can be used to validate the length of the one-time-passcode.

Here is a code example implementing the above considerations:





---

## Full UI interactive example

The following interactive example shows a full UI for enrolling in MFA, and encompasses all of the considerations mentioned above.


## Magic Link {#magic-link}

### Launch Checklist

Make sure you’re ready to take your app to production.

## Create an IP Allowlist

WorkOS makes use of Cloudflare to ensure security and reliability of all operations. If you are looking to create a list of allowed IP addresses for redirect requests, you can use the IP Ranges listed in the [Cloudflare documentation](https://www.cloudflare.com/ips/).

## Go-live checklist

- [ ] Unlock your Production environment by adding your billing information

  > Only enterprise connections in your Production environment will be charged. Any Google OAuth or Magic Link connections in Production will be free.

- [ ] Configure a production redirect URI in your Production project
- [ ] Secure your Production project’s API key
- [ ] Ensure that your application can receive redirects from WorkOS

  Depending on your network architecture, you may need to allowlist incoming redirect traffic from `api.workos.com`.

## Frequently asked questions

### Can I customize the email sent via Magic Link?

Yes, you can use your own email service and custom branded email template to send the authentication link to the user. See the custom email code snippet in the [create passwordless session section](/magic-link/1-add-magic-link-to-your-app/create-a-passwordless-session-and-email-the-user) for an example.

### Magic Link

The fastest way to securely enable authentication – passwordless sign-in via email in a couple lines of code.

> **Deprecated:** Magic Link is not recommended due to issues with email clients or other security software visiting the links and invalidating them. Instead, use [Magic Auth](/authkit/magic-auth), which provides a more secure passwordless authentication method.

## Introduction

Managing password authentication entails significant overhead for engineering teams and opens up many risks for breaches. Magic Link from WorkOS gives you the ability to build a secure passwordless authentication flow utilizing email. Send users a one-time-use link and let them sign in with a single click.

> Magic Link sets you up to handle Single Sign-On via the [WorkOS SSO API](/sso). The redirect URI / profile retrieval process is identical between Magic Link and SSO.

![Diagram showing Magic Link flow which emphasizes that WorkOS does not manage the session.](https://images.workoscdn.com/docs/guides/magic-link/v1/magic-link-diagram.png?auto=format&fit=clip&q=50)[border=false]

Magic Link is not a session management solution – instead it is an authentication solution. You as the developer have the ability to manage user sessions as you see fit. This means you determine how long a session is valid for, as well as how to store and invalidate a session.

Magic Links are single use, meaning that they will immediately expire after they are first clicked. If end users have security checks included with their email provider that test all embedded URLs, it can cause the Magic Links to expire before they reach the user’s inbox. To work around this, we recommend that end users add these Magic Link emails to an allowlist in order to bypass these security checks.

## What you’ll build

In this guide, we’ll take you from learning about passwordless authentication all the way through to building production-ready passwordless authentication flows with the WorkOS Magic Link API.

This guide will show you how to:

1. Add Magic Link to your app
2. Configure a redirect URI
3. Create a new Magic Link Connection

## Before getting started

To get the most out of this guide, you’ll need:

- A [WorkOS account](https://dashboard.workos.com/)

## API object definitions

[Passwordless Session](/reference/magic-link/passwordless-session)
: Represents a passwordless authentication session.

[Profile](/reference/sso/profile)
: Represents an authenticated user. The Profile object contains information relevant to a user in the form of normalized and raw attributes.

## (1) Add Magic Link to your app

### Install the WorkOS SDK

WorkOS offers native SDKs in several popular programming languages. Choose a language below to see instructions in your application’s language.



### Set secrets

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.

```plain title="Environment variables"
WORKOS_API_KEY='sk_example_123456789'
WORKOS_CLIENT_ID='client_123456789'
```

### Add a callback endpoint

Let’s first add the redirect endpoint which will handle the callback from WorkOS after a user has authenticated via a magic link. This endpoint should exchange the authorization code (valid for 10 minutes) returned by WorkOS with the authenticated user’s Profile.



### Create a Passwordless Session and email the user

Create a Passwordless Session to generate an authentication link for a user. An authentication link is valid for 15 minutes and can be sent via the WorkOS API or using your own email service.

You can use the optional `state` parameter to encode arbitrary information to help restore application state between redirects.

You can use the optional `redirect_uri` parameter to override the default [Redirect URI](/glossary/redirect-uri) set in the dashboard.

> A Magic Link Connection will be automatically created if there isn’t already one for the domain specified when creating a new Passwordless Session.

- | WorkOS email

  Use the WorkOS API to send the authentication link to the user. The email sent will be WorkOS branded.

  

- | Custom email

  Use your own email service and custom branded email template to send the authentication link to the user.

  

---

## (2) Configure a redirect URI

You should set a redirect URI (i.e. the callback endpoint from [Add a callback endpoint](/magic-link/1-add-magic-link-to-your-app/add-a-callback-endpoint)) via the Configuration page in the WorkOS Dashboard – be sure not to include wildcard subdomains or query parameters.

![A screenshot showing where to add a callback in the WorkOS Dashboard.](https://images.workoscdn.com/images/43ffd916-890b-4f1f-8767-0b70113288d9.png?auto=format&fit=clip&q=50)

### Example Apps

View sample Magic Link apps for each SDK.

You can view minimal example apps that demonstrate how to use the WorkOS SDKs to authenticate users via Magic Link:


  
  
  
  
  
  
  
  
  
</ExampleApps.Root>


## Integrations {#integrations}

### Xero OAuth

Learn how to set up OAuth with Xero

## Introduction

The Xero OAuth integration allows your users to authenticate using their Xero credentials through the "Sign in with Xero" flow.

The configuration process involves creating an OAuth application in Xero and configuring the client credentials in your WorkOS Dashboard.

---

## What WorkOS provides

When setting up Xero OAuth, WorkOS provides one key piece of information that needs to be configured in your Xero OAuth application:

- [Redirect URI](/glossary/redirect-uri): The endpoint where Xero will send authentication responses after successful login

The Redirect URI is available in the [WorkOS Dashboard](https://dashboard.workos.com/). In the left navigation menu, select the **Authentication** tab and the **OAuth providers** sub-tab. Locate the **Xero** section.

![The Xero OAuth section in the WorkOS Dashboard.](https://images.workoscdn.com/images/ea385495-75f6-4357-b16a-97c1383bbc9b.png?auto=format&fit=clip&q=50)

Click **Enable**. The **Xero OAuth** configuration dialog will open. Locate the **Redirect URI**.

![Xero OAuth Redirect URI in the WorkOS Dashboard.](https://images.workoscdn.com/images/75e4e68e-cf07-4277-8979-7cd81f82f68f.png?auto=format&fit=clip&q=50)

The **Redirect URI** serves as the destination for authentication responses and must be configured in your Xero application's OAuth settings.

---

## What you'll need

You will need to obtain two pieces of information from a Xero Developer application:

- **Xero Client ID**: Application identifier from Xero
- **Xero Client Secret**: Authentication secret for the application

The following sections will guide you through creating an OAuth application in your Xero Developer account and generating these credentials.

---

## (1) Create the Xero OAuth application

Log in to your [Xero developer account](https://developer.xero.com) and create a new application.

![The Xero developer homepage.](https://images.workoscdn.com/images/58e9b3af-7442-45e7-8be2-cb1fa9ab39a2.png?auto=format&fit=clip&q=80)

In the top right corner, select **New app**. Fill out the form starting with the application name.

![The Xero form to create a new OAuth application.](https://images.workoscdn.com/images/f78a99b4-f004-4437-9612-6d97ef49bf3d.png?auto=format&fit=clip&q=50)

For the **Integration type**, select **Web app**.

For **Company or application URI**, use your application's homepage URI.

For **Redirect URI**, use the **Redirect URI** from the Xero OAuth configuration in the WorkOS Dashboard.

![OAuth client credentials in the Xero application settings.](https://images.workoscdn.com/images/9a0c3175-3af3-4613-a9f9-c9e6851507fe.png?auto=format&fit=clip&q=50)

Agree to Xero's Developer Platform Terms & Conditions and click **Create app**.

---

## (2) Generate client credentials

On the next page, you will see the Xero **App details** for your new OAuth application. From the left navigation menu, navigate to the **Configuration** page.

![OAuth client credentials in the Xero application settings before creating a client secret.](https://images.workoscdn.com/images/5ec780c3-c325-4455-992e-20727c39f8f9.png?auto=format&fit=clip&q=50)

Select **Generate a secret** to create a client secret.

![OAuth client credentials in the Xero application settings after creating a client secret.](https://images.workoscdn.com/images/58158b26-0854-496f-9ccc-660955735463.png?auto=format&fit=clip&q=50)

Copy the **Client ID** and **Client secret 1** as you'll need them for the WorkOS configuration.

---

## (3) Configure Xero credentials in WorkOS

Now that you have the **Xero Client ID** and **Xero Client Secret** from the previous steps, return to the [WorkOS Dashboard](https://dashboard.workos.com).

In the **Xero OAuth** configuration dialog, enable the integration. Paste the credentials from Xero into their respective fields in the WorkOS Dashboard.

![OAuth client credentials in the WorkOS Xero setup modal filled with client id and client secret.](https://images.workoscdn.com/images/9bb1cd53-a5cc-4a04-b7d4-2fd9791ad499.png?auto=format&fit=clip&q=50)

Click **Save** to complete the configuration.

You are now ready to start authenticating with Xero OAuth. You will use the `provider` query parameter in the Get Authorization URL API endpoint to support global Xero OAuth for any domain. The `provider` query parameter should be set to `XeroOAuth`.

---

## Configure Additional OAuth Scopes (Optional)

WorkOS will request the OAuth scopes that are required for authentication by default. You can optionally configure your integration to request additional OAuth scopes as needed.

When the **Return Xero OAuth tokens** option is selected, the access token and refresh token from Xero will be included in the response from the [Authenticate with code API](/reference/authkit/authentication/code).

![A screenshot showing Xero OAuth scopes configuration in the WorkOS Dashboard](https://images.workoscdn.com/images/a39beaaf-faf4-4fcf-98b7-eeb54f0135fb.png?auto=format&fit=clip&q=50)

Any scopes configured here will be included on every Xero OAuth request. To specify additional scopes dynamically, use the `provider_scopes` query parameter on the [Get Authorization URL API endpoint](/reference/authkit/authentication/get-authorization-url).

For more information, see Xero's OAuth scopes [documentation](https://developer.xero.com/documentation/oauth2/scopes).

---

## Frequently asked questions

### How is the WorkOS Xero OAuth integration different from implementing regular Xero OAuth flow?

It's the same Xero OAuth flow as you could build yourself, but it's encapsulated within WorkOS SSO. This means you don't need to build it yourself. In addition to Xero OAuth, you can use WorkOS SSO to support other identity providers, all with a single integration.

### What is the provider query parameter and how is it used in the Xero OAuth integration?

You can use the `provider` query parameter in the [Get Authorization URL API endpoint](/reference/sso/get-authorization-url) to support global Xero OAuth for any domain. The `provider` query parameter should be set to `XeroOAuth`.

### What type of Xero integration should I select?

You should select **Web app** as the integration type when creating your Xero OAuth application. This is the correct type for OAuth integrations that will work with WorkOS.

### Where can I find my Xero application after creation?

After creating your Xero application, you can find it in your [Xero Developer Portal](https://developer.xero.com) under your apps list. From there, you can access the **Configuration** page to manage your OAuth settings and regenerate credentials if needed.

### Workday

Learn about syncing your user list with Workday.

## Introduction

This guide outlines how to synchronize your application’s Workday directories.

To synchronize an organization’s users and groups provisioned for your application, you’ll need the following information from the organization:

- The Workday Custom Report JSON endpoint
- The Workday Custom Group Report JSON endpoint
- Username for accessing the Custom Report endpoint
- Password for accessing the Custom Report endpoint

> Note: The Workday integration isn't enabled by default in the WorkOS Dashboard or Admin Portal. Please reach out to [support@workos.com](mailto:support@workos.com) or via your team’s WorkOS Slack channel if you would like Workday enabled.

---

## (1) Create an Integration System User

It’s recommended that the organization creates an Integration System User within Workday. The Integration System User will be used to access Custom Reports.

![A screenshot of the "Create Integration System User" form in the Workday Dashboard.](https://images.workoscdn.com/images/24b0561d-cd74-46a1-939e-3c76ead90c89.png?auto=format&fit=clip&q=50)

> If you’ve finished the setup, and everything works as expected but fields are missing from the Report, ensure that the user created has access to access to the fields.

![A screenshot showing user access to a report in the Workday Dashboard.](https://images.workoscdn.com/images/7e3e33f1-3724-4ff9-a4b6-ad2ac475ccb3.png?auto=format&fit=clip&q=50)

---

## (2) Create a Security Group

Create a new security group in Workday. Set the Type of Tenanted Security Group to Integration System Security Group (Unconstrained). Then add a name for the Security Group and select OK.

![A screenshot showing the "Create Security Group" form in the Workday Dashboard.](https://images.workoscdn.com/images/5e24e9d0-fba3-4e1d-8782-67c6491b3652.png?auto=format&fit=clip&q=50)

Next, for Integration System Users, add the integration system user you created in the previous step, and select OK.

![A screenshot showing where to add the Integration System User in the Workday Dashboard.](https://images.workoscdn.com/images/5483b3eb-3995-48b6-8718-a4eb07ccf681.png?auto=format&fit=clip&q=50)

---

## (3) Add domain security policies to the Security Group

Next, you’ll need to add domain security policies to the newly created security group. You can access this on the Security Group Settings → Maintain Domain Permissions for Security Group page.

![A screenshot showing where to find the "Maintain Domain Permissions for Security Group" option in the Workday Dashboard.](https://images.workoscdn.com/images/592f1450-d6d4-4a47-adef-6d1ce9007f4a.png?auto=format&fit=clip&q=50&w=2048)

You’ll need to permit the following domain security policies to have “Get” access under Integration Permissions:

- Person Data: Work Contact Information
- Workday Accounts
- Worker Data: Active and Terminated Workers
- Worker Data: All Positions
- Worker Data: Business Title on Worker Profile
- Worker Data: Current Staffing Information
- Worker Data: Public Worker Reports
- Worker Data: Workers

![A screenshot showing Integration Permissions in the Workday Dashboard.](https://images.workoscdn.com/images/32f4bae2-9ef0-4a7b-a27e-6c28268298d6.png?auto=format&fit=clip&q=50)

To activate these new security settings, you need to go to the Activate Pending Security Policy Changes page and click OK.

![A screenshot showing the Activate Pending Security Policy Changes page in the Workday Dashboard.](https://images.workoscdn.com/images/2c708837-b39d-454f-90b0-acfe377d4ad5.png?auto=format&fit=clip&q=50)

Then, select the Confirm checkbox to finish activating.

![A screenshot showing where to confirm the Active Pending Security Policy Changes in the Workday Dashboard.](https://images.workoscdn.com/images/664f3905-d9e6-4390-b210-1e7eaffa25c2.png?auto=format&fit=clip&q=50)

---

## (4) Create and Populate Custom Reports

You will need to create two Custom Reports. The first Custom Report will be used for syncing User information. The second report will be used for syncing Group information.

When creating the report, make sure to select the Advanced report type and to have the Enable as Web Service box checked.

![A screenshot showing the "Create Custom Report" page in the Workday Dashboard.](https://images.workoscdn.com/images/8fa8ffb7-e377-4289-a130-3719646dea8a.png?auto=format&fit=clip&q=50)

You need to add information for certain fields to the report. You can do this by directly adding columns to the report for the attributes in Workday with column heading names specified as follows:



![A screenshot showing an example of Custom User Report in the Workday Dashboard.](https://images.workoscdn.com/images/d3d4bb22-b4c8-467a-a3b4-bd0e6b4d2aea.png?auto=format&fit=clip&q=50)
Along the same lines as the User Report, WorkOS looks for the following information in the Group Report:



---

## (5) Add an authorized user

If an Integration System User was created, the organization will want to have that user added as an authorized user. This can be found under the **Share** tab from within a Report.

![A screenshot showing the "Share" tab in the Workday Dashboard.](https://images.workoscdn.com/images/8794da9c-89ca-4b84-842b-3f3fe6648d39.png?auto=format&fit=clip&q=50)

---

## (6) Get the RaaS endpoint

Now that the Report itself is setup and access to it had been configured, the organization will need to get the RaaS endpoint. The page with the endpoints can be found under **Actions → Web Service → View URLs**.

![A screenshot showing where to find the view URLs option in the Workday Dashboard.](https://images.workoscdn.com/images/d212438c-951b-464f-aa42-2bebd0e2bdf2.png?auto=format&fit=clip&q=50)

Once on the URLs page, the one that WorkOS will need is listed under the **JSON** section.

![A screenshot showing the View URLs Web Service page in the Workday Dashboard.](https://images.workoscdn.com/images/8698f25c-22bc-48ee-82c7-5fa885b20215.png?auto=format&fit=clip&q=50)

---

## (7) Create your Directory Sync Connection

Login to your WorkOS Dashboard and select “Organizations” from the left hand navigation bar.

Select the organization you’ll be configuring a new Directory Sync Connection with.

Click “Add Directory”.

![A screenshot showing where to find the "Add Directory" button in the WorkOS Dashboard.](https://images.workoscdn.com/images/6244ae58-85a4-4c14-b6c0-c12bca04408e.png?auto=format&fit=clip&q=50)

Select “Workday” as the directory type, and then input the Company Name.

Click the “Create Directory” button.

![A screenshot showing the "Create Directory" button in the WorkOS Dashboard.](https://images.workoscdn.com/images/27e9b01f-52e6-433b-af33-38eb3961dc70.png?auto=format&fit=clip&q=50)

---

## (8) Setup your Directory Sync Connection

Click “Update Directory” to input the organization's Custom Report JSON endpoints, username and password.

![A screenshot showing where to find the "Update Directory" button in the WorkOS Dashboard.](https://images.workoscdn.com/images/0c51f74e-8705-4193-93db-126a61bb367c.png?auto=format&fit=clip&q=50)

Then, click “Save Directory Details”.

---

## (9) View users and groups in your dashboard

Now, whenever the organization assigns users or groups to your application, you’ll receive Dashboard updates based on changes in their directory.

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

## Frequently asked questions

### How often does the Workday directory perform a sync?

The Workday directory polls in every 30 minutes starting from the time of the initial sync.

### VMware

Learn how to configure a connection to VMware via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

---

## What WorkOS provides

WorkOS provides the [SP Metadata](/glossary/sp-metadata) link. It’s readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot showing where to find the SP Metadata in the WorkOS dashboard.](https://images.workoscdn.com/images/e253ad08-a85b-4586-bf8c-970059eb286c.png?auto=format&fit=clip&q=50)

---

## What you’ll need

Next, you will provide the Metadata URL from VMware.

Normally, this information will come from the organization's IT Management team when they set up your application’s SAML 2.0 configuration in their VMware admin dashboard. But, should that not be the case during your setup, here’s how to obtain it.

---

## (1) Create a new SaaS Application

In your Workspace ONE Catalog, click “New”. Give your application a descriptive name.

![A screenshot showing how to create new application in VMware.](https://images.workoscdn.com/images/576ed672-e030-4f1e-936e-c04d33ff7dfd.png?auto=format&fit=clip&q=50)

---

## (2) Basic SAML Configuration

Click the “Configuration” tab from the left sidebar.

Copy the SP Metadata Link from your VMware connection in the WorkOS dashboard and paste it in the URL/XML field under Configuration in Workspace One.

![A screenshot showing where to input WorkOS SP metadata when configuring VMware application.](https://images.workoscdn.com/images/6d7bace5-a513-4782-ac18-8327b5e364a3.png?auto=format&fit=clip&q=50)

---

## (3) Advanced SAML Configuration

Continue scrolling and expand “Advanced Properties”.

![A screenshot showing where to find "Advanced Properties" dropdown in VMware application.](https://images.workoscdn.com/images/dc6d711a-104c-4cd6-bca7-dff852dbb2c9.png?auto=format&fit=clip&q=50)

Enable “Sign Assertion” and “Include Assertion Signature”.

![A screenshot showing where to enable "Sign Assertion" and "Include Assertion Signature" in VMware application.](https://images.workoscdn.com/images/98b0a17a-51a4-41c4-87be-1ffadfce96aa.png?auto=format&fit=clip&q=50)

---

## (4) Configure Attribute Map

Continue scrolling until “Custom Attribute Mapping”.

![A screenshot showing where to find "Custom Attribute Mapping" in VMware application.](https://images.workoscdn.com/images/d35112ac-5d76-47c4-aa6c-436321d30b06.png?auto=format&fit=clip&q=50)

Fill in the following attribute mappings and select “Next” until you are prompted to “Save”.

- `id` → `${user.objectGUID}`
- `firstName` → `${user.firstName}`
- `lastName` → `${user.lastName}`
- `email` → `${user.email}`

![A screenshot showing how to configure attribute mappings in VMware application.](https://images.workoscdn.com/images/2ef20a4a-9095-4c35-85b8-cf4e16c79da9.png?auto=format&fit=clip&q=50)

Some VMware configurations use `user.ExternalId` instead of `user.objectGUID`. In this case, you would map the id attribute to `user.ExternalId`.

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, map the groups in your identity provider to a SAML attribute named `groups`.

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (5) Upload Metadata URL

After saving your SaaS Application, click “Settings” then “SAML Metadata”. Click on “Copy URL” next to “Identity Provider (IdP) metadata”.

![A screenshot showing where to find metadata URL in VMware application.](https://images.workoscdn.com/images/f99932ab-8828-4b78-a044-0c19c35859dd.png?auto=format&fit=clip&q=50)

Back in the WorkOS Dashboard, click on “Edit Metadata Configuration” in the “Metadata Configuration” section of the Connection.

![A screenshot showing where to edit the IdP metadata URL in the WorkOS dashboard.](https://images.workoscdn.com/images/d743c922-1517-4dd2-80ab-cab5e4a9c53f.png?auto=format&fit=clip&q=50)

Finally, input the Metadata URL and click “Save Metadata Configuration”. Your Connection will then be linked and good to go!

![A screenshot showing how to configure IdP metadata URL in the WorkOS dashboard.](https://images.workoscdn.com/images/30130529-4132-45f6-aa33-70d8760612fd.png?auto=format&fit=clip&q=50)

### Vercel OAuth

Learn how to set up OAuth with Vercel

## Introduction

The Vercel OAuth integration allows your users to authenticate using their Vercel credentials.

The configuration process involves creating an OAuth application in Vercel and configuring the client credentials in your WorkOS Dashboard.

---

## What WorkOS provides

When setting up Vercel OAuth, WorkOS provides one key piece of information that needs to be configured in your Vercel OAuth application:

- [Redirect URI](/glossary/redirect-uri): The endpoint where Vercel will send authentication responses after successful login

The Redirect URI is available in the [WorkOS Dashboard](https://dashboard.workos.com/). In the left navigation menu, select the **Authentication** tab and the **Providers** sub-tab. Locate the **Vercel** section.

![The Vercel OAuth section in the WorkOS Dashboard](https://images.workoscdn.com/images/fbd35719-bb0d-4ccc-a613-a63dc3ba97b5.png?auto=format&fit=clip&q=50)

Click **Enable**. The **Vercel OAuth** configuration dialog will open. Locate the **Redirect URI**.

![The Vercel OAuth configuration modal in the WorkOS Dashboard](https://images.workoscdn.com/images/648eb886-837f-4eb2-a366-6d6094187a5d.png?auto=format&fit=clip&q=50)

The **Redirect URI** serves as the destination for authentication responses and must be configured in your Vercel OAuth application as the Authorization Callback URL.

---

## What you'll need

You will need to obtain two pieces of information from a Vercel OAuth application:

- **Vercel Client ID**: Application identifier from Vercel
- **Vercel Client Secret**: Authentication secret for the application

The following sections will guide you through creating an OAuth application in your Vercel account and generating these credentials.

---

## (1) Create the Vercel OAuth application

Log in to your [Vercel account](https://vercel.com/login) and navigate to your team Settings tab.

In the left navigation menu, scroll down to select **Apps**. Click **Create** to create a new application.

![Vercel Apps page with Create button](https://images.workoscdn.com/images/1c5a34a7-64c1-42d1-b2e8-363b3e14a1be.png?auto=format&fit=clip&q=50)

Choose a name for your app, optionally add a logo, and click Save.

---

## (2) Configure the Vercel OAuth application

In the left navigation menu, ensure that the **General** tab is selected. Scroll down to the **Authorization Callback URLs** section, and enter the **Redirect URI** from the Vercel OAuth configuration in the WorkOS Dashboard. Click **Save**.

![Configuring Redirect URI in Vercel](https://images.workoscdn.com/images/b9e526f1-099b-472b-9a46-e9504ae2c106.png?auto=format&fit=clip&q=50)

In the left navigation menu, select the **Authentication** tab. In the **Client Authentication Methods** section, make sure that **client_secret_post** is selected.

![Configuring Client Authentication Methods in Vercel](https://images.workoscdn.com/images/65baf589-746b-4b33-b648-36f1d8b57c5d.png?auto=format&fit=clip&q=50)

In the left navigation menu, select the **Permissions** tab. In the **Scopes** section, enable the **openid**, **email**, and **profile** scopes to allow the application to read basic user profile information. Click **Save**.

![Configuring Scopes in Vercel](https://images.workoscdn.com/images/7240cd69-de9b-4a20-9f1a-13ed6beaf825.png?auto=format&fit=clip&q=50)

---

## (3) Generate client credentials

In the left navigation menu, select the **General** tab and view your Client ID in the **Details** section.

![View Client ID in Vercel](https://images.workoscdn.com/images/fef2735e-9a66-47f0-a0d5-e6d402a3ae7d.png?auto=format&fit=clip&q=50)

In the left navigation menu, select the **Authentication** tab. Scroll down to the **Client Secrets** section and click **Generate** to generate a new Client Secret.

![Generate Client Secret in Vercel](https://images.workoscdn.com/images/72e4b918-80ec-4aa8-b54a-349ca6d3bff2.png?auto=format&fit=clip&q=50)

Note the **Client ID** and **Client Secret** values as you'll need them for the WorkOS configuration.

> **Important**: The Client Secret is only shown once. Make sure to copy and store it securely.

---

## (4) Configure Vercel credentials in WorkOS

Now that you have the **Vercel Client ID** and **Vercel Client Secret** from the previous step, return to the [WorkOS Dashboard](https://dashboard.workos.com).

In the **Vercel OAuth** configuration dialog, enable the integration. Paste the credentials from Vercel into their respective fields in the WorkOS Dashboard.

![Entering Vercel Credentials in WorkOS Dashboard](https://images.workoscdn.com/images/ff653223-0ace-4f91-85f5-48e238e48666.png?auto=format&fit=clip&q=50)

Click **Save changes** to complete the configuration.

You are now ready to start authenticating with Vercel OAuth. If you are using AuthKit's [Hosted UI](/authkit/hosted-ui), a Continue with Vercel button will be added to your login page.

If you are building your own authentication flows outside of AuthKit's hosted UI, you will use the `provider` query parameter in the [Get Authorization URL API endpoint](/reference/authkit/authentication/get-authorization-url) to support global Vercel OAuth for any domain. The `provider` query parameter should be set to `VercelOAuth`.

---

## Frequently asked questions

### How is the WorkOS Vercel OAuth integration different from implementing regular Vercel OAuth flow?

It's the same Vercel OAuth flow as you could build yourself, but it's encapsulated within WorkOS SSO. This means you don't need to build it yourself. In addition to Vercel OAuth, you can use WorkOS SSO to support other identity providers, all with a single integration.

### What is the provider query parameter and how is it used in the Vercel OAuth integration?

If you are building your own authentication flows outside of AuthKit's hosted UI, you can use the `provider` query parameter in the [Get Authorization URL API endpoint](/reference/authkit/authentication/get-authorization-url) to support global Vercel OAuth for any domain. The `provider` query parameter should be set to `VercelOAuth`.

### What scopes are required for Vercel OAuth?

The **openid**, **profile**, and **email** scopes are required to allow the application to read user profile information necessary for authentication. These scopes provide access to the user's basic profile data and email address.

### Supabase + WorkOS SSO

Learn how to use WorkOS for SSO with your Supabase application.

## Introduction

This guide outlines the steps to make WorkOS SSO connections available to your application using Supabase Auth. It will require a few changes to your existing Supabase application code.

If you are wanting to instead use AuthKit with your Supabase application, check out our [Supabase + AuthKit guide](/integrations/supabase-authkit).

---

## (1) Copy WorkOS Client ID and API Key

Supabase uses the WorkOS Client ID and API Key to initiate the authentication flow and to return the SSO user profile. The first step is finding the Client ID and the API Key in the WorkOS dashboard.

In the WorkOS dashboard, go to **Configuration** and under the "Settings" tab and copy the Client ID.

![A screenshot showing where to find the Client ID in the WorkOS dashboard configurations page.](https://images.workoscdn.com/images/5cdbbd7e-2141-470c-8b86-b0876974e58a.png?auto=format&fit=clip&q=50)

Select **API Keys** on the left-side navigation bar and either copy an existing API Key or create a new API Key and copy it.

![A screenshot showing where the WorkOS API Key is in the dashboard.](https://images.workoscdn.com/images/fe6c9ad1-f04a-4335-9752-4ef149fa3147.png?auto=format&fit=clip&q=50)

---

## (2) Add your WorkOS credentials into your Supabase Project and configure the Redirect URL

Sign in to Supabase and then go to your Supabase Project Dashboard. Navigate to **Authentication** → **Explore Auth**.

![A screenshot showing when to the Authentication section is in the Supabase project dashboard.](https://images.workoscdn.com/images/f773aeb8-5bee-4eba-89a0-62441a79be11.png?auto=format&fit=clip&q=50)

Select the Providers tab and scroll down to WorkOS and enter the WorkOS URL as **https://api.workos.com**. Then enter the Client ID and API Key copied from the WorkOS Dashboard, toggle to enable WorkOS as a provider and click **Save**.

![A screenshot showing how to enable WorkOS as a provider in Supabase and input the WorkOS URL, Client ID and Secret Key.](https://images.workoscdn.com/images/c275b3f4-807c-4961-916b-c0ed2d6717dd.png?auto=format&fit=clip&q=50)

Copy the Redirect URL from the WorkOS provider section. In the WorkOS dashboard navigate to **Configuration** → **Settings** → **Redirect URIs** and click **Edit Redirect URIs** to input the copied Redirect URL.

![A screenshot showing where to add the WorkOS Redirect URL.](https://images.workoscdn.com/images/27ad127c-3631-45d0-aedc-39ab90f03ed6.png?auto=format&fit=clip&q=50)

---

## (3) Add login code to your client app

When a user signs in, call `signInWithOAuth` with `workos` as the provider. Pass in a Connection ID, Organization ID, or provider type (for OAuth) under `queryParams`.


---

## Summary

With a few lines of code, you can add WorkOS as an SSO provider and enable features like the admin portal and dozens of integrations within your Supabase application.

### Supabase + AuthKit

Learn how to use AuthKit with your Supabase application.

## Introduction

This guide outlines the steps to use WorkOS as a Supabase [third-party auth provider](https://supabase.com/docs/guides/auth/third-party/overview). This will allow you to authenticate users with AuthKit and use AuthKit access tokens to access Supabase's REST and GraphQL APIs in your app.

## (1) Add a WorkOS third-party auth integration

Configure a WorkOS integration in the [Supabase dashboard](https://supabase.com/dashboard/project/_/auth/third-party).

![Supabase 3rd party auth dashboard](https://images.workoscdn.com/images/6494746d-f6d2-46a1-bf26-f4fe7370e12b.png?auto=format&fit=clip&q=50)

Your issuer URL is:

```txt title="WorkOS Issuer"
https://api_workos_com/user_management/client_123456789
```

![Supabase WorkOS Connection dialog](https://images.workoscdn.com/images/e4d5c238-a217-4c9c-a955-a882074919bb.png?auto=format&fit=clip&q=50)

## (2) Set up a JWT Template

Supabase RLS policies expect a `role` claim in the access token that corresponds to a database role. WorkOS already adds a `role` claim corresponding to the user's role in an organization. Set up a JWT template in the WorkOS dashboard (Authentication → Sessions) so that the role works with Supabase:



We add a `user_role` claim so that your application can still determine the role assigned to that user.

## (3) Pass the access token to Supabase APIs

Pass in your WorkOS client ID and auth domain when initializing the [Supabase client library](https://supabase.com/docs/guides/auth/third-party/workos#setup-the-supabase-client-library).



That's it! Supabase will now accept the access tokens returned by AuthKit.

### Slack OAuth

Learn how to set up OAuth with Slack

## Introduction

The Slack OAuth integration allows your users to authenticate using their Slack credentials through the "Sign in with Slack" flow.

The configuration process involves creating or configuring a Slack App and setting up OAuth permissions with the client credentials in your WorkOS Dashboard.

---

## What WorkOS provides

When setting up Slack OAuth, WorkOS provides one key piece of information that needs to be configured in your Slack App:

- [Redirect URI](/glossary/redirect-uri): The endpoint where Slack will send authentication responses after successful login

The Redirect URI is available in the [WorkOS Dashboard](https://dashboard.workos.com/). In the left navigation menu, select the **Authentication** tab and the **OAuth providers** sub-tab. Locate the **Slack** section.

![The Slack OAuth section in the WorkOS Dashboard.](https://images.workoscdn.com/images/9c70cdb3-0b02-4529-919a-3d91235e78cf.png?auto=format&fit=clip&q=50)

Click **Enable**. The **Slack OAuth** configuration dialog will open. Locate the **Redirect URI**.

![Slack OAuth Redirect URI in the WorkOS Dashboard.](https://images.workoscdn.com/images/c7800ed9-c9b9-4893-8821-e3af465362c5.png?auto=format&fit=clip&q=50)

The **Redirect URI** serves as the destination for authentication responses and must be configured in your Slack App's OAuth & Permissions settings.

---

## What you'll need

You will need to obtain two pieces of information from a Slack App:

- **Slack Client ID**: Application identifier from Slack
- **Slack Client Secret**: Authentication secret for the application

The following sections will guide you through creating or configuring a Slack App and generating these credentials.

---

## (1) Create or open your Slack App

Navigate to the [Slack App management page](https://api.slack.com/apps).

If you don't already have a Slack App, click **Create an App**, provide a name, and choose the development workspace where you'll test.

![The Slack API portal showing the create new app button.](https://images.workoscdn.com/images/127f704d-ce13-49e0-9d82-2ba123547e3e.png?auto=format&fit=clip&q=80)

Once created, open your new Slack App to configure it.

---

## (2) Configure OAuth & Permissions

In your Slack App's settings, go to **OAuth & Permissions** in the left-hand navigation menu.

Under **Redirect URLs**, add the **Redirect URI** from the WorkOS Dashboard.

![The Slack API portal showing where to configure your redirect URI.](https://images.workoscdn.com/images/f0e7d586-a8e1-4a67-8c06-085dc4009b32.png?auto=format&fit=clip&q=80)

Click **Save URLs** to confirm.

Under **Scopes**, ensure you request the standard OpenID scopes (e.g., `openid`, `profile`, `email`), which Slack requires for Sign in with Slack using OIDC.

---

## (3) Retrieve Slack credentials

Still in your Slack App's settings, find your **Client ID** and **Client Secret**.

Copy both values as you'll need them for the WorkOS configuration.

---

## (4) Configure Slack credentials in WorkOS

Now that you have the **Slack Client ID** and **Slack Client Secret** from the previous steps, return to the [WorkOS Dashboard](https://dashboard.workos.com).

In the **Slack OAuth** configuration dialog, enable the integration. Paste the credentials from Slack into their respective fields in the WorkOS Dashboard.

![The WorkOS dashboard with the Slack OAuth connection enabled.](https://images.workoscdn.com/images/c9c7c0de-c1f1-4d73-8f68-1b415d3dc5cb.png?auto=format&fit=clip&q=50)

Click **Save** to complete the configuration.

---

## Frequently asked questions

### How is the WorkOS Slack OAuth integration different from implementing regular Slack OAuth flow?

It's the same Slack OAuth flow as you could build yourself, but it's encapsulated within WorkOS SSO. This means you don't need to build it yourself. In addition to Slack OAuth, you can use WorkOS SSO to support other identity providers, all with a single integration.

### What is the provider query parameter and how is it used in the Slack OAuth integration?

You can use the `provider` query parameter in the [Get Authorization URL API endpoint](/reference/sso/get-authorization-url) to support Slack OAuth for any domain. The `provider` query parameter should be set to `SlackOAuth`.

### What scopes are required for Slack OAuth?

The standard OpenID scopes (`openid`, `profile`, `email`) are required for Sign in with Slack using OIDC. These scopes provide access to the user's basic profile information necessary for authentication.

### SimpleSAMLphp

Learn how to configure a SimpleSAMLphp connection.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a SimpleSAMLphp SAML Connection, you’ll need the Identity Provider Metadata URL that is available from the organization's SimpleSAMLphp instance.

---

## What WorkOS provides

WorkOS provides the [ACS URL](/glossary/acs-url), the [SP Metadata](/glossary/sp-metadata) Link and the [SP Entity ID](/glossary/sp-entity-id). They are readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot showing where to find the ACS URL, SP Metadata and SP Entity ID in the WorkOS dashboard.](https://images.workoscdn.com/images/e2c962f1-2fe9-470f-af1f-684fe651fcbc.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. The SP Metadata link contains a metadata file that the organization can use to set up the SAML integration. The SP Entity ID is a URI used to identify the issuer of a SAML request, response, or assertion.

---

## What you’ll need

In order to integrate, you’ll need the [IdP Metadata URL](/glossary/idp-metadata).

Normally, this will come from the organization's IT Management team when they set up your application’s SAML configuration in their SimpleSAMLphp instance. But, should that not be the case during your setup, here’s how to obtain it.

---

## (1) Configure SAML Application with Service Provider Details

Follow the [SimpleSAMLphp documentation](https://simplesamlphp.org/docs/stable/simplesamlphp-idp.html) to set up SimpleSAMLphp as an Identity Provider and add a new SP.

Copy and paste the ACS URL and SP Entity ID into the corresponding fields for Service Provider configuration. You can find more on how to structure this under “Adding SPs to the IdP” in the SimpleSAMLphp documentation linked above.

The necessary SP metadata can also be found in the SP metadata URL provided in the WorkOS Dashboard.

---

## (2) Configure SAML Attributes

You will need to send the following 4 required attributes in the SAML Response: `firstName`, `lastName`, `email`, and `id`.

Ensure the following attribute mapping is set:

- A user’s first name → `firstName`
- A user’s last name → `lastName`
- A user’s email address → `email`
- A unique identifier representing a user → `id`

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, map the groups in your identity provider to a SAML attribute named `groups`.

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (3) Obtain Identity Provider Metadata

Obtain the IdP Metadata URL. As noted in the ["Adding this IdP to other SPs" section of the SimpleSAMLphp documentation](https://simplesamlphp.org/docs/stable/simplesamlphp-idp.html), the IdP metadata URL should be available from `/saml2/idp/metadata.php`.

![A screenshot showing where to edit the IdP metadata URL in the WorkOS dashboard.](https://images.workoscdn.com/images/07f6f9a0-4331-4124-b90e-dc8d24f7e2ea.png?auto=format&fit=clip&q=50)

Alternatively, you can manually configure the connection by providing the IdP URI (Entity ID), [IdP SSO URL](/glossary/idp-sso-url) and X.509 Certificate.

![A screenshot showing how to switch to manual IdP metadata configuration in the WorkOS dashboard.](https://images.workoscdn.com/images/07c47c03-354d-4df4-bdb9-bc25573aeb25.png?auto=format&fit=clip&q=50)

![A screenshot showing how to manually configure the IdP metadata in the WorkOS dashboard.](https://images.workoscdn.com/images/d838649f-ee75-429e-94b2-c1693294b81c.png?auto=format&fit=clip&q=50)

Your Connection will then be Active and good to go!

### Shibboleth Unsolicited SAML

Learn how to configure a Shibboleth Unsolicited connection via SAML.

## Introduction

These instructions are for connecting to Shibboleth using the [UnsolicitedSSOConfiguration](https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631696/UnsolicitedSSOConfiguration). If the organization requires the [generic SAML 2.0 configuration](https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631694/SAML2SSOConfiguration) instead, please use the [Shibboleth Generic SAML provider documentation](/integrations/shibboleth-generic-saml).

Each SSO Identity Provider requires specific information to create and configure a new [connection](/glossary/connection). Often, the information required to create a connection will differ by Identity Provider.

To create a Shibboleth Unsolicited SAML connection, you’ll need the Identity Provider metadata that is available from the organization's Shibboleth instance.

Start by logging in to your WorkOS dashboard and browse to the “Organizations” tab on the left hand navigation bar.

Select the organization you wish to configure a Shibboleth Unsolicited SAML connection for, and select “Manually Configure Connection” under “Identity Provider”.

![Create New Connection in WorkOS Dashboard](https://images.workoscdn.com/images/c4cf0500-9155-42dd-aa2d-fd40fbbc79bc.png?auto=format&fit=clip&q=50)

Select “Shibboleth Unsolicited SAML” from the Identity Provider dropdown, enter a descriptive name for the connection, and then select the “Create Connection” button.

![Select Shibboleth Unsolicited SAML Provider](https://images.workoscdn.com/images/8a32ce47-1087-420d-87b3-49e031308ae7.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

Once you’ve created your connection, WorkOS provides the [ACS URL](/glossary/acs-url), [SP Metadata](/glossary/sp-metadata) link, and [SP Entity ID](/glossary/sp-entity-id). It’s readily available in your connection settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot showing where to find the ACS URL, SP Metadata and SP Entity ID in the WorkOS dashboard.](https://images.workoscdn.com/images/a19338a8-f7a4-432a-8e7f-0f1b27a5422e.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. The SP Metadata link contains a metadata file that the organization can use to set up the Shibboleth Unsolicited SAML integration.

The SP Entity ID is a URI used to identify the issuer of a SAML request and the audience of a SAML response. In this case, the SP Entity ID is used to communicate that WorkOS will be the party performing SAML requests to the organization's Shibboleth instance, and that WorkOS is the intended audience of the SAML responses from the Shibboleth instance.

---

## What you’ll need

In order to integrate you’ll need the Shibboleth IdP metadata.

Normally, this information will come from the organization's IT Management team when they set up your application’s Shibboleth configuration. But, should that not be the case during your setup, here’s how to obtain them.

---

## (1) Enter Service Provider Details

Copy and Paste the “ACS URL” and “SP Entity ID” into the corresponding fields for Service Provider details and configuration. For some Shibboleth setups, you can use the metadata found at the SP Metadata link to configure the Shibboleth connection.

---

## (2) Obtain Identity Provider Metadata

Download the IdP metadata from the Shibboleth instance. Refer to the [Shibboleth documentation](https://shibboleth.atlassian.net/wiki/spaces/CONCEPT/pages/928645275/MetadataForIdP) for more information on this metadata file. Keep in mind where the file was saved, as we’ll be uploading it later to configure the connection.

---

## (3) Configure Attribute Mapping

At a minimum, the Attribute Statement in the SAML Response should include `id`, `email`, `firstName`, and `lastName` attributes. Refer to the [Shibboleth documentation](https://shibboleth.atlassian.net/wiki/spaces/CONCEPT/pages/928645122/SAMLAttributeNaming) for more information on adding and mapping attributes.

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, map the groups in your identity provider to a SAML attribute named `groups`.

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (4) Upload Metadata File

In the connection settings in the WorkOS dashboard, click “Edit Metadata Configuration”.

![A screenshot showing where to edit the IdP metadata URL in the WorkOS dashboard.](https://images.workoscdn.com/images/eaf5a624-5a5a-4702-a4f8-1cb3d55ed6e9.png?auto=format&fit=clip&q=50)

Upload the XML metadata file from Shibboleth into the “Metadata File” field and select “Save Metadata Configuration”. Your connection will then be linked and good to go!

![A screenshot showing where to upload and how to save the IdP metadata URL in the WorkOS dashboard.](https://images.workoscdn.com/images/ad7fc5c3-f3cf-4860-a219-00838ee5e766.png?auto=format&fit=clip&q=50)

### Shibboleth Generic SAML

Learn how to configure a Shibboleth Generic connection via SAML.

## Introduction

These instructions are for connecting to Shibboleth using the [generic SAML 2.0 configuration](https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631694/SAML2SSOConfiguration). If the organization requires the [UnsolicitedSSOConfiguration](https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631696/UnsolicitedSSOConfiguration) instead, please use the [Shibboleth Unsolicited SAML provider documentation](/integrations/shibboleth-unsolicited-saml).

Each SSO Identity Provider requires specific information to create and configure a new [connection](/glossary/connection). Often, the information required to create a connection will differ by Identity Provider.

To create a Shibboleth Generic SAML connection, you’ll need the Identity Provider metadata that is available from the organization's Shibboleth instance.

Start by logging in to your WorkOS dashboard and browse to the “Organizations” tab on the left hand navigation bar.

Select the organization you wish to configure a Shibboleth Generic SAML connection for, and select “Manually Configure Connection” under “Identity Provider”.

![A screenshot showing where to find "Manually Configure Connection" in the WorkOS Dashboard.](https://images.workoscdn.com/images/f07dc8e4-e97c-4bd0-9dbd-14915cd46e40.png?auto=format&fit=clip&q=50)

Select “Shibboleth Generic SAML” from the Identity Provider dropdown, enter a descriptive name for the connection, and then select the “Create Connection” button.

![A screenshot showing "Create Connection" details in the WorkOS Dashboard.](https://images.workoscdn.com/images/640b70d1-60ce-48c7-865f-2441325a078c.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

Once you’ve created your connection, WorkOS provides the [ACS URL](/glossary/acs-url), [SP Metadata](/glossary/sp-metadata) link, and [SP Entity ID](/glossary/sp-entity-id). It’s readily available in your connection settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot showing where to find the ACS URL, SP Metadata and SP Entity ID in the WorkOS Dashboard.](https://images.workoscdn.com/images/efd8ea95-9dbd-4a18-b961-7d9d1b4bc3ce.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. The SP Metadata link contains a metadata file that the organization can use to set up the Shibboleth Generic SAML integration.

The SP Entity ID is a URI used to identify the issuer of a SAML request and the audience of a SAML response. In this case, the SP Entity ID is used to communicate that WorkOS will be the party performing SAML requests to the organization's Shibboleth instance, and that WorkOS is the intended audience of the SAML responses from the Shibboleth instance.

---

## What you’ll need

In order to integrate you’ll need the Shibboleth IdP metadata.

Normally, this information will come from the organization's IT Management team when they set up your application’s Shibboleth configuration. But, should that not be the case during your setup, here’s how to obtain them.

---

## (1) Enter Service Provider Details

Copy and Paste the “ACS URL” and “SP Entity ID” into the corresponding fields for Service Provider details and configuration. For some Shibboleth setups, you can use the metadata found at the SP Metadata link to configure the Shibboleth connection.

---

## (2) Obtain Identity Provider Metadata

Download the IdP metadata from the Shibboleth instance. Refer to the [Shibboleth documentation](https://shibboleth.atlassian.net/wiki/spaces/CONCEPT/pages/928645275/MetadataForIdP) for more information on this metadata file. Keep in mind where the file was saved, as we’ll be uploading it later to configure the Connection.

---

## (3) Configure Attribute Mapping

At a minimum, the Attribute Statement in the SAML Response should include `id`, `email`, `firstName`, and `lastName` attributes. Refer to the [Shibboleth documentation](https://shibboleth.atlassian.net/wiki/spaces/CONCEPT/pages/928645122/SAMLAttributeNaming) for more information on adding and mapping attributes.

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, map the groups in your identity provider to a SAML attribute named `groups`.

Once your SAML app is configured to return groups, navigate to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (4) Upload Metadata File

In the connection settings in the WorkOS Dashboard, click “Edit Metadata Configuration”.

![A screenshot showing where to edit the IdP metadata URL in the WorkOS Dashboard.](https://images.workoscdn.com/images/8fb3610f-15a3-4e10-8441-50121bd32609.png?auto=format&fit=clip&q=50)

Upload the XML metadata file from Shibboleth into the “Metadata File” field and select “Save Metadata Configuration”. Your connection will then be linked and good to go!

![A screenshot showing where to upload and how to save the IdP metadata URL in the WorkOS Dashboard.](https://images.workoscdn.com/images/d9745f3c-4b3f-4e43-aea2-1b21e7160909.png?auto=format&fit=clip&q=50)

### SFTP

Learn about syncing users with an SFTP connection

## Introduction

To set up an SFTP (Secure File Transfer Protocol) directory sync connection, you'll need to provide the organization's IT team with specific configuration details from WorkOS. This allows them to upload CSV files containing user and group information via SFTP.

WorkOS maintains a receiving SFTP server that the organization's HRIS provider or SFTP client can connect to.

If the organization's HRIS has a built-in SFTP client, SFTP will allow them to automatically sync their data and ensure their data is always up to date. An SFTP integration allows for provider-agnostic ingestion of employee data into your product ecosystem.

Once the integration is set up, WorkOS automatically creates and hosts an SFTP folder for the organization's HRIS provider to upload files at a regular cadence.

An SFTP integration has the following advantages:

- Works with any system that has the ability to export CSVs
- Has an easy integration path for an organization comfortable working with CSVs and SFTP
- Allows a custom cadence of updates for your customer

Your application interfaces with an SFTP directory the same as with other directories; receiving [events](/events) when the directory is created or updated:



---

## What WorkOS provides

When setting up an SFTP directory sync connection, WorkOS provides two key pieces of information that you'll need to share with the organization:

- **SFTP Server URL**: The location where the organization will upload user and group CSV files
- **Username**: Authentication credentials for SFTP access

These are available in your directory’s settings in the [WorkOS Dashboard](https://dashboard.workos.com/) once the connection is configured.

![SFTP directory details in the WorkOS Dashboard.](https://images.workoscdn.com/images/46c63f08-579e-4e60-8cb6-b20d6f95ff8b.png?auto=format&fit=clip&q=50)

The SFTP server uses public key authentication, providing secure file transfer capabilities for user and group data synchronization.

---

## What you will need

The organization will need to provide a public key for authentication and prepare their user and group data in the required CSV format.

You will need to obtain from the organization:

- **Public Key**: For SFTP authentication (maximum key length is 2048 bytes; supported keys are: `ED25519`, `RSA`, and `ECDSA`)

The organization will need to export their users and groups as CSV files with the structure below.

### `users.csv`

This file is required.



### `user_groups.csv`

This file is _optional_.



### `groups.csv`

This file is _optional_. Additional metadata may be also included in this file.



---

## (1) Set up your directory sync endpoint

Login to the [WorkOS Dashboard](https://dashboard.workos.com/).

In the left navigation menu, select the **Organizations** tab. Select the appropriate organization for which you will enable a SFTP directory sync connection.

On the organization's page, scroll down to the **Directory Sync** section. Click **Configure manually**.

![WorkOS Dashboard showing directory sync card with configure manually button highlighted](https://images.workoscdn.com/images/ebf08eb3-a698-4498-adde-1b551ab0f519.png?auto=format&fit=clip&q=50)

Select **SFTP** as the directory type. Input an appropriate name for the connection. Click **Create Directory**.

![The WorkOS Dashboard with a create directory dialog](https://images.workoscdn.com/images/e1010105-9c22-4d20-88d0-8b316df97ad2.png?auto=format&fit=clip&q=50)

---

## (2) Configure SFTP authentication

Obtain the public key from the organization’s admin that will be used for SFTP authentication.

From the directory page in the WorkOS Dashboard, in the **Directory details** section click the **Update Directory** button.

![A screenshot showing where to find "Update directory" for an Organization in the WorkOS Dashboard.](https://images.workoscdn.com/images/d0847fd0-b9c9-4ec2-aa1e-b69c6aac1fa5.png?auto=format&fit=clip&q=50)

Paste the organization's public key into the input field.

The SSH public key format should include the key type (e.g. `ssh-rsa`, `ssh-ed25519`), base64 encoded body, and an optional comment, with spaces between each element. For example, `ssh-rsa AAAABB1 keycomment`.

RSA, ECDSA, and ED25519 keys are accepted:

- For RSA keys, the key type is `ssh-rsa`.
- For ED25519 keys, the key type is `ssh-ed25519`.
- For ECDSA keys, the key type is either `ecdsa-sha2-nistp256`, `ecdsa-sha2-nistp384`, or `ecdsa-sha2-nistp521`, depending on the size of the key generated.

![A screenshot showing how to update SFTP directory details in the WorkOS Dashboard.](https://images.workoscdn.com/images/77a535f1-87d4-410f-bd7c-09a4535e53c2.png?auto=format&fit=clip&q=50)

---

## (3) Provide SFTP configuration to the organization

After adding the public key, WorkOS generates a username. You will see the green **Linked** icon appear.

Copy the **Username** and SFTP server URL from the WorkOS Dashboard.

Share these values with the organization so they can configure their SFTP client:

- **SFTP Server**: `sftp.workos.com`
- **Username**: The generated username from the WorkOS Dashboard
- **Authentication**: Their private key (corresponding to the public key you uploaded)

Instruct the organization to upload their CSV files using these credentials.

---

## (4) Confirm users and groups are synced

Now, whenever your customer uploads updated CSV files via SFTP, you’ll receive updates based on the changes in their directory data.

The **Users** tab within the SFTP connection displays synced users.

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

## SFTP Security

### How is my organization’s data protected in transit?

SFTP uses SSH (Secure Shell protocol) to symmetrically encrypt traffic after an asymmetric key negotiation for authentication.

Our solution leverages the [AWS Transfer Family](https://docs.aws.amazon.com/transfer/latest/userguide/how-aws-transfer-works.html), so that we can support a common, secure protocol (SSH) with modern, isolated data storage (AWS S3).

We leverage the default security policy ([security-policy-transfer-2020-06](https://docs.aws.amazon.com/transfer/latest/userguide/security-policies.html#security-policy-transfer-2020-06)) for the choice of SSH cipher-suites, which determines the strength of cryptographic protection for data in transit.

### How is my organization’s data protected at rest?

As the data is stored in an AWS S3 bucket the default (since January 2023) is that it is encrypted at rest ([SSE-S3](https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-encryption.html)).
The symmetric encryption used is AES-256, more information is available in [the FAQ](https://docs.aws.amazon.com/AmazonS3/latest/userguide/default-encryption-faq.html).

### How does WorkOS isolate one of my organization’s data from the other?

Each of the organizations you onboard will [create an SSH key pair](/integrations/sftp/what-you-will-need), this consists of a public key, and a private key. They will retain the private key, ensuring that only they can authenticate. The public key uploaded to WorkOS will be used to authenticate the organization's connection via SFTP.

Each of your organizations is mapped to a distinct S3 bucket based on an internal (cryptographically random) identifier for the SSH key pair.

### When does WorkOS dispose of the data and how is this done?

In either of the following events your organization’s data, and the S3 bucket will be deleted:

1. You off-board the organization from your product/service.
2. You no longer use the WorkOS Directory Sync service.

---

## Frequently asked questions

### How often do SFTP directories perform a sync?

SFTP directories will sync automatically whenever file changes are detected and every 30 minutes following the initial synchronization.

### SCIM

Learn about syncing users with a custom SCIM provider

## Introduction

To set up a SCIM v2.0 directory sync connection, you'll need to provide the organization’s IT team with specific configuration details from WorkOS. This allows their SCIM server to synchronize users and groups with your application.

---

## What WorkOS provides

When setting up a SCIM directory sync connection, WorkOS provides two key pieces of information that you'll need to share with the organization:

- [Endpoint](/glossary/endpoint): The URL where the SCIM server will send requests
- [Bearer Token](/glossary/bearer-token): Authentication credentials for the endpoint requests

Both of these are available in the **Directory details** section of the directory sync connection in the [WorkOS Dashboard](https://dashboard.workos.com/).

![The WorkOS dashboard, highlights the directory details card with filled endpoint and bearer token inputs](https://images.workoscdn.com/images/1ae8c088-07d6-4512-9abf-1adec38f6b0b.png?auto=format&fit=clip&q=50)

These settings enable the organization’s SCIM server to securely send user and group data to your application through WorkOS.

---

## What you will need

The organization’s IT team will handle the SCIM server configuration on their end. You simply need to provide them with the endpoint URL and bearer token from the WorkOS Dashboard.

Typically, the organization's IT team will use these values to configure your application within their SCIM server or identity provider admin dashboard.

---

## (1) Set up your directory sync endpoint

Login to the [WorkOS Dashboard](https://dashboard.workos.com/).

In the left navigation menu, select the **Organizations** tab. Select the appropriate organization for which you will enable a SCIM directory sync connection.

On the organization’s page, scroll down to the **Directory Sync** section. Click **Configure manually**.

![WorkOS Dashboard showing directory sync card with configure manually button highlighted](https://images.workoscdn.com/images/ebf08eb3-a698-4498-adde-1b551ab0f519.png?auto=format&fit=clip&q=50)

Select **Custom SCIM v2.0** as the directory type. Input an appropriate name for the connection. Click **Create Directory**.

![The WorkOS Dashboard with a create directory dialog showing directory type and name inputs](https://images.workoscdn.com/images/aa5a17d9-0990-4af6-a61f-1640658650e1.png?auto=format&fit=clip&q=50)

The directory sync connection will now display the endpoint for the SCIM server and the bearer token.

> We have support for custom labeled URLs for directory sync endpoints. [Contact us](mailto:support@workos.com) for more info!

---

## (2) Provide SCIM configuration to the organization

Copy the **Endpoint** and **Bearer Token** from the **Directory details** section on the directory page of the WorkOS Dashboard.

Provide these values to the organization’s IT team so they can configure the application within their SCIM server or identity provider admin dashboard:

- **Endpoint URL**: The destination where their SCIM server will send user and group data
- **Bearer Token**: Authentication credentials for secure communication

Once the organization has configured these values in their SCIM server, your application will be ready to receive real-time user and group synchronization.

---

## (3) Assign users and groups to your application

Now, whenever the organization assigns users or groups to your application in their directory, you’ll receive real-time dashboard updates based on changes in their system.

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

### SAML

Learn how to configure a new custom SAML connection

## Introduction

To set up a SAML connection on behalf of an organization, you'll need the identity provider metadata or manual configuration details from the organization's IT team.

---

## What WorkOS provides

When setting up a SAML connection, WorkOS provides three key pieces of information in the **Service Provider Details** section for an SSO connection within the [WorkOS Dashboard](https://dashboard.workos.com/):

- [SP Entity ID](/glossary/sp-entity-id): A unique identifier that represents your application in SAML communications
- [ACS URL](/glossary/acs-url): The endpoint where identity providers send authentication responses
- [SP Metadata](/glossary/sp-metadata): A configuration file containing all necessary SAML settings

![WorkOS Settings](https://images.workoscdn.com/images/bc0ebb05-e918-4217-8435-bfd1c73dd1f6.png?auto=format&fit=clip&q=80)

These settings are required to configure a SAML integration. The **ACS URL** serves as the destination for authentication responses, while the **SP Entity ID** uniquely identifies your application in SAML requests and responses. The **SP Metadata** URL provides a complete configuration file that simplifies the setup process for the organization.

---

## What you will need

You will need to obtain one of the following from the organization:

- [Identity Provider Metadata URL](/glossary/idp-metadata): Configuration URL containing SAML metadata (preferred)
- Manual configuration details: SSO URL, Entity ID, and X.509 Certificate (if metadata URL is not available)

Typically, the organization's IT team will provide these values when they configure your application in their identity provider admin dashboard. However, if you need to guide them through the process, the following sections will help.

---

## (1) Configure Service Provider Details

For SSO to properly function, the organization needs to create and configure a SAML application in their identity provider.

Copy the **ACS URL** and **SP Entity ID** from the **Service Provider Details** section in the WorkOS Dashboard.

Instruct the organization admin to paste these values into the corresponding fields in their identity provider's admin dashboard. Alternatively, they can use the service provider metadata URL to automatically configure the SAML connection if their identity provider supports metadata-based configuration.

---

## (2) Obtain identity provider metadata

After the organization creates a SAML application, their identity provider will provide either a metadata URL or manual configuration details.

If they have a metadata URL, in the WorkOS Dashboard, navigate to the **Identity Provider Configuration** section. Click **Edit Configuration**.

![Open Identity Provider Configuration in WorkOS Dashboard](https://images.workoscdn.com/images/a33cc226-7167-4450-8879-9f123fc8ffeb.png?auto=format&fit=clip&q=80)

Paste the metadata URL from the organization's IT team into the input field. Your connection will be automatically configured once the metadata is processed.

![Upload identity provider metadata URL to WorkOS Dashboard](https://images.workoscdn.com/images/4d25d1a1-57a0-464d-95d7-a33eb85d2e0f.png?auto=format&fit=clip&q=80)

If the organization's identity provider doesn't provide a metadata URL, you'll need to manually configure the connection by clicking the **Switch to Manual Configuration** option and entering the SSO URL, Entity ID, and X.509 Certificate provided by their IT team.

![Switch to Manual Configuration](https://images.workoscdn.com/images/7384d9b7-b918-4778-ac1f-2b389cf73241.png?auto=format&fit=clip&q=80)

![Manually configure connection in WorkOS Dashboard](https://images.workoscdn.com/images/37eaf62e-dd9f-41b0-9e91-221256318298.png?auto=format&fit=clip&q=80)

---

## (3) Configure attribute mapping

The organization's SAML provider needs to include specific attributes in the SAML response. Instruct them to configure their SAML application to include the following attributes in the Attribute Statement:

- `id`: Maps to the `idp_id` attribute in WorkOS user profiles
- `email`: Maps to the `email` attribute in WorkOS user profiles
- `firstName`: Maps to the `first_name` attribute in WorkOS user profiles
- `lastName`: Maps to the `last_name` attribute in WorkOS user profiles

### Role assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To enable this functionality, instruct the organization to add a `groups` attribute to the SAML response that maps to a list of the user's group memberships.

> Finish role assignment set-up by navigating to the SSO connection page in the **Organizations** section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

### Salesforce SAML

Learn how to configure a connection to Salesforce via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [connection](/glossary/connection). And often, the information required to create a connection will differ by Identity Provider.

To create an Salesforce SAML connection, you’ll need three pieces of information: an [ACS URL](/glossary/acs-url), an [SP Entity ID](/glossary/sp-entity-id), and a [Metadata URL](/glossary/idp-metadata).

---

## What WorkOS provides

WorkOS provides the ACS URL and SP Entity ID. It’s readily available in your Connection Settings in the [WorkOS dashboard](https://dashboard.workos.com/).

![A screenshot showing where to find the ACS URL and SP Entity ID in the WorkOS dashboard.](https://images.workoscdn.com/images/134a9a2e-3409-4969-9048-01be960c7d93.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. In Salesforce’s case, it needs to be set by the organization when configuring Salesforce as an Identity Provider.

The Entity ID is a URI used to identify the issuer of a SAML request, response, or assertion. In this case, the entity ID is used to communicate that WorkOS will be the party performing SAML requests to the organization's Salesforce instance.

Specifically, the ACS URL and SP Entity ID will need to be set in the Connected Apps setup in Salesforce.

![A screenshot showing where to place the WorkOS ACS URL and SP Entity ID in the Salesforce dashboard.](https://images.workoscdn.com/images/98390601-4c8a-42f4-9965-52ddcd28ff45.png?auto=format&fit=clip&q=50)

---

## What you’ll need

In order to integrate you’ll need the Salesforce Metadata URL. Normally, the this will come from the organization's IT Management team when they set up your application’s SAML client in their Salesforce instance. But, should that not be the case during your setup, here’s how to obtain it.

---

## (1) Generate Certificate

Log in to your Salesforce Account, click the Settings cog icon on the top right, and select “Setup”.

Once in setup mode you can use the search bar to easily navigate around between settings pages. The first page to navigate to is the “Certificate and Key Management” page.

![A screenshot showing how to navigate to the "Certificate and Key Management" page in the Salesforce dashboard.](https://images.workoscdn.com/images/769b9580-ffc1-46d6-b382-4b5a83222dd8.png?auto=format&fit=clip&q=50)

Once in setup mode you can use the search bar to easily navigate around between settings pages. The first page to navigate to is the “Certificate and Key Management” page. If a key does not exist that you would like to use, click “Create Self-Signed Certificate” to generate a new one.

![A screenshot showing how to generate a Self-Signed Certificate in the Salesforce dashboard.](https://images.workoscdn.com/images/fc278a8b-3398-46ff-9a58-143dc127d0e6.png?auto=format&fit=clip&q=50)

Give the Certificate a meaningful label and unique name and select the Key Size you’d like to use. It’s not necessary to have an Exportable Private Key, but if you are using a key-certificate store you can choose this option.

![A screenshot showing how to configure the Self-Signed Certificate details in the Salesforce dashboard.](https://images.workoscdn.com/images/936558fc-d9c3-4075-a139-3cea3d3854dc.png?auto=format&fit=clip&q=50)

---

## (2) Enable Salesforce as an IdP

From the setup search bar browse to the “Identity Provider” portal in Salesforce.

If it has not already been done, select “Enable Identity Provider”.

![A screenshot showing how to enable Salesforce as an Identity Provider in the Salesforce dashboard.](https://images.workoscdn.com/images/f890533c-dd88-4b05-9cbe-e47b3a416906.png?auto=format&fit=clip&q=50)

You will need to select the correct certificate from the previous step.

![A screenshot showing how to select the SAML certificate for the Identity Provider setup in the Salesforce dashboard.](https://images.workoscdn.com/images/f332f289-dad3-491d-a1c3-67e14e381cfc.png?auto=format&fit=clip&q=50)

Additionally this page will display the Metadata URL. You will need to copy this URL and in a later step it will be uploaded into WorkOS.

![A screenshot showing where to copy the IdP Metadata URL from in the Salesforce dashboard.](https://images.workoscdn.com/images/e5088944-d7b5-4e3f-8072-d672bbd88f26.png?auto=format&fit=clip&q=50)

---

## (3) Configure SAML Application

Next from the setup search bar browse to the “App Manager” portal. Once here you will want to select the option for “New Connected App”.

![A screenshot showing how to create a new Connected App in the Salesforce dashboard.](https://images.workoscdn.com/images/af73f2b9-6c91-4b45-87aa-b0e15a2d9a0d.png?auto=format&fit=clip&q=50)

Give the App and API a meaningful name and set a contact email that corresponds to who you’d reach out to for support should there be an issue. You can always opt to use `support@workos.com`.

![A screenshot showing how to configure the name and contact email for the new Connected App in the Salesforce dashboard.](https://images.workoscdn.com/images/03a48352-2825-4c6d-aa8d-bfb57f03159f.png?auto=format&fit=clip&q=50)

Scroll down further to the “Web App Settings” and check the box for “Enable SAML”. Enter the Entity ID and ACS URL into their respective places within the Settings.

The “Subject Type” should be set to “User ID” and the “Name ID Format” should be set to `urn:oasis:names:tv:SAML:1.1:nameid-format:emailAddress`. The “Issuer” should populate correctly with your Salesforce subdomain. For the IdP Certificate, select the certificate that matches the one previously used when enabling the Identity Provider, and for the “Signing Algorithm for SAML Messages” choose “SHA256”.

![A screenshot showing how to configure the Connected App's Web App Settings in the Salesforce Dashboard.](https://images.workoscdn.com/images/98390601-4c8a-42f4-9965-52ddcd28ff45.png?auto=format&fit=clip&q=50)

Save the configurations and you should now see the new Connected App listed under “App Manager”.

---

## (4) Configure User Attributes and Claims

In the Setup search bar browse to the “Manage Connected Apps” portal. Click on your application and this will open the view where you can configure the attribute mapping, and later on the user profile access permissions.

![A screenshot showing how to open the configurations for the new Connected App in the Salesforce dashboard.](https://images.workoscdn.com/images/6d1dc5a0-d7a5-4e68-a596-5e69f0cb1d52.png?auto=format&fit=clip&q=50)

Viewing the app, scroll down to the “Custom Attributes” section and select “New”.

![A screenshot showing how to create new Custom Attribute mapping in the Salesforce dashboard.](https://images.workoscdn.com/images/716f679d-907f-42b9-8024-ff74ecff82cc.png?auto=format&fit=clip&q=50)

Salesforce automatically includes email as an Attribute so we will need to add three fields:

- `id`
- `firstName`
- `lastName`

Configure the fields so the mapping matches the following:

![A screenshot showing how to configure SAML attribute mapping in the Salesforce dashboard.](https://images.workoscdn.com/images/0dfb70bf-744f-4021-ae20-c06ade8f792d.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, create a new custom attribute with a key of `groups`. Map this attribute to a value that contains a user’s group membership or role information, such as `$UserRole.Name` in the example below.

![A screenshot showing where to add the groups attribute in the Salesforce dashboard.](https://images.workoscdn.com/images/0f2abfab-25c9-4ce4-aeb4-7f0f3fae8038.png?auto=format&fit=clip&q=50)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (5) Manage Profiles With Application Access

Similarly, viewing the app, there is a “Manage Profiles” section for granting access to control who can log into the application. Select “Manage Profiles” and grant access to the appropriate profiles that should have access to the application in the "Application Profile Assignment" wizard. Select "Save" when complete.

![A screenshot showing how to configure the "Application Profile Assignments" in the Salesforce dashboard.](https://images.workoscdn.com/images/26cdf036-5428-4ccf-b320-f9d1e41250e2.png?auto=format&fit=clip&q=50)

Here is an example of a successfully configured “Connected Application” allowing access to anyone with an “End User” Profile.

![A screenshot showing the completed "Application Profile Assignments" in the Salesforce dashboard.](https://images.workoscdn.com/images/fdc0584a-1350-42d7-8816-c8255e307db6.png?auto=format&fit=clip&q=50)

---

## (6) Obtain Identity Provider Details

Finally, return to the WorkOS dashboard. Within your connection settings, select "Edit Metadata Configuration" under "Identity Provider Configuration" and provide the Metadata URL you obtained from Salesforce. Your connection will then be verified and good to go!

![A screenshot showing where to add the IdP Metadata URL in the WorkOS dashboard.](https://images.workoscdn.com/images/ff29bcdd-a7df-47d3-88fc-f001a3dae23d.png?auto=format&fit=clip&q=50)

### Salesforce OAuth

Learn how to set up OAuth with Salesforce.

## Introduction

The Salesforce OAuth integration allows your users to authenticate using their Salesforce credentials.

The configuration process involves creating an External Client App in Salesforce and configuring the client credentials in the WorkOS Dashboard.

---

## What WorkOS provides

When setting up Salesforce OAuth, WorkOS provides one key piece of information that needs to be configured in your Salesforce External Client App:

- [Redirect URI](/glossary/redirect-uri): The endpoint where Salesforce will send authentication responses after successful login

The Redirect URI is available in the [WorkOS Dashboard](https://dashboard.workos.com/). In the left navigation menu, select the **Authentication** tab and the **OAuth providers** sub-tab. Locate the **Salesforce** section.

![Open the Salesforce configuration dialog](https://images.workoscdn.com/images/27840df3-434d-4fc0-bae3-aa3dee021f2a.png?auto=format&fit=clip&q=50)

Click **Manage**. The **Salesforce OAuth** configuration dialog will open. Locate the **Redirect URI**.

![Salesforce OAuth Redirect URI in the WorkOS Dashboard](https://images.workoscdn.com/images/387b564f-7c4c-4b94-aece-7dc3eb862058.png?auto=format&fit=clip&q=50)

The **Redirect URI** serves as the destination for authentication responses and must be configured in your Salesforce External Client App as the authorization callback URL.

---

## What you'll need

You will need to obtain two pieces of information from a Salesforce External Client App:

- **Salesforce Consumer Key**: Application identifier from Salesforce
- **Salesforce Consumer Secret**: Authentication secret for the application

The following sections will guide you through creating an External Client App in your Salesforce instance and generating these credentials.

---

## (1) Create the Salesforce External Client App

Sign in to Salesforce and navigate to Setup. On the sidebar, select **Apps**, then **External Client Apps**, then **External Client App Manager**. Create a new External Client App.

![The New External Client App button in Salesforce](https://images.workoscdn.com/images/e17fec69-13b5-4281-8311-5854ac1007af.png?auto=format&fit=clip&q=50)

---

## (2) Configure External Client App

Fill out the External Client App form. Expand the **API (Enable OAuth Settings)** section, and check the **Enable OAuth** checkbox. For the **Callback URL** input, enter the **Redirect URI** from the WorkOS Dashboard.

It is also required to add the "Access the identity URL service" and "Access unique user identifiers" scopes to your app.

![The Salesforce form to create a new External Client App](https://images.workoscdn.com/images/f1ce3367-fc4f-4be6-9529-49835431c38e.png?auto=format&fit=clip&q=50)

Under **Security** deselect the **Require Proof Key for Code Exchange (PKCE) extension for Supported Authorization Flows** option, as WorkOS does not currently support PKCE for Salesforce OAuth.

Click **Create**.

![The option to disable the PCKE requirement for a Salesforce External Client App](https://images.workoscdn.com/images/7e9a2bda-0ba4-4d33-a5f4-3ae07909a67e.png?auto=format&fit=clip&q=50)

After creating your External Client App, click the **Settings** tab, and then expand **OAuth Settings**. Click on **Consumer Key and Secret**.

You'll be given the Consumer Key and Secret for your External Client App. Note these values as you'll need them for the WorkOS configuration.

---

## (3) Configure Salesforce credentials in WorkOS

Now that you have the **Salesforce Consumer Key** and **Salesforce Consumer Secret** from the previous step return to the [WorkOS Dashboard](https://dashboard.workos.com/).

In the **Salesforce OAuth** configuration dialog, paste the credentials from Salesforce into the Client ID and Client Secret fields.

![Where to enter the Salesforce Consumer Key and Salesforce Consumer Secret in the WorkOS Dashboard](https://images.workoscdn.com/images/f65f7819-f9c9-4321-9ba5-9365fa51f4e8.png?auto=format&fit=clip&q=50)

Click **Save changes** to complete the configuration.

You're now able to authenticate users with Salesforce OAuth. If you are using AuthKit's [Hosted UI](/authkit/hosted-ui), the Login with Salesforce button will be added to your login page.

If you are building your own authentication flows outside of AuthKit's hosted UI, you will use the `provider` query parameter in the [Get Authorization URL API endpoint](/reference/authkit/authentication/get-authorization-url) to support global Salesforce OAuth for any domain. The `provider` query parameter should be set to `SalesforceOAuth`.

---

## Configure Additional OAuth Scopes (Optional)

WorkOS will request the OAuth scopes that are required for authentication by default. You can optionally configure your integration to request additional OAuth scopes as needed.

When the **Return Salesforce OAuth tokens** option is selected, the access token from Salesforce will be included in the response from the [Authenticate with code API](/reference/authkit/authentication/code).

![A screenshot showing Salesforce OAuth scopes configuration in the WorkOS Dashboard](https://images.workoscdn.com/images/f1a87bc5-71b3-48fb-b2cf-3052ee39d4b4.png?auto=format&fit=clip&q=50)

Any scopes configured here will be included on every Salesforce OAuth request. To specify additional scopes dynamically, use the `provider_scopes` query parameter on the [Get Authorization URL API endpoint](/reference/authkit/authentication/get-authorization-url). You will also have to update your External Client App's configured scopes to include these additional scopes.

For more information, see Salesforce's OAuth scopes [documentation](https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_tokens_scopes.htm).

## Frequently asked questions

### How is the WorkOS Salesforce OAuth integration different from implementing regular Salesforce OAuth flow?

It's the same Salesforce OAuth flow as you could build yourself, but it's encapsulated within WorkOS SSO. This means you don't need to build it yourself. In addition to Salesforce OAuth, you can use WorkOS SSO to support other identity providers, all with a single integration.

### What is the provider query parameter and how is it used in the Salesforce OAuth integration?

You can use the `provider` query parameter in the [Get Authorization URL API endpoint](/reference/authkit/authentication/get-authorization-url) to support global Salesforce OAuth for any domain. The `provider` query parameter should be set to `SalesforceOAuth`.

### What scopes are required for Salesforce OAuth?

The **openid**, **profile**, and **email** scopes are required to allow the application to read user profile information necessary for authentication. These scopes provide access to the user's basic profile data.

### Rippling SCIM

Learn about syncing your user list with Rippling SCIM v2.0.

## Introduction

This guide outlines how to synchronize your application’s Rippling directories using SCIM.

To synchronize an organization’s users and groups provisioned for your application, you’ll need to provide the organization with two pieces of information:

- An [Endpoint](/glossary/endpoint) that Rippling will make requests to.
- A [Bearer Token](/glossary/bearer-token) for Rippling to authenticate its endpoint requests.

Both of these are available in your Endpoint’s Settings in the [WorkOS Dashboard](https://dashboard.workos.com).

> Steps 2, 3, and 4 below will need to be carried out by the organization when configuring your application in their Rippling instance.

---

## (1) Set up your Directory Sync endpoint

Login to your WorkOS Dashboard and select “Organizations” from the left hand navigation bar.

Select the organization you’ll be configuring a new Directory Sync for.

Under “Actions” click “Add Directory”.

![A screenshot showing where to click "Add Directory" in the WorkOS dashboard.](https://images.workoscdn.com/images/0f13d97a-b2a8-4263-ad11-e8e7633f3ae5.png?auto=format&fit=clip&q=50)

Select “Rippling” from the dropdown, and enter the organization name.

Then, click “Create Directory.”

![A screenshot showing where to name and create a Rippling Directory in the WorkOS dashboard.](https://images.workoscdn.com/images/83cd8619-6ccd-4d49-9a69-5c0cd04dd8d6.png?auto=format&fit=clip&q=50)

Your Rippling directory sync has now been created successfully with an Endpoint and Bearer Token.

![A screenshot showing where to locate the Rippling directory details in the WorkOS dashboard.](https://images.workoscdn.com/images/98b1e1f1-b601-4df0-97bc-cfa824a7559e.png?auto=format&fit=clip&q=50)

> We have support for custom URLs for Directory Sync endpoints. [Contact us](mailto:support@workos.com) for more info!

---

## (2) Create your Rippling application

Log in to the Rippling admin dashboard and select the “Custom App” option in the menu under the “Identity Management” category.

![A screenshot showing where to select the "Custom App" option in the "Identity Management" menu in Rippling.](https://images.workoscdn.com/images/2851bbb9-a486-4e51-90c1-6265959cb336.png?auto=format&fit=clip&q=50)

Select “Create New App” in the Custom App page.

![A screenshot showing where to select "Create New App" in Rippling.](https://images.workoscdn.com/images/bd2b1fba-2433-4fc2-b20b-7a0ca712dd20.png?auto=format&fit=clip&q=50)

Fill out the application’s name, select categories, upload an image for the logo, and check the “User Management via SCIM” box. Click “Continue” and the next page will populate more option fields regarding SCIM setup.

![A screenshot showing where to fill in the name, categories, logo, and type of custom app in Rippling.](https://images.workoscdn.com/images/74bf5e11-239e-4cf4-b3ce-af819d3c7b95.png?auto=format&fit=clip&q=50)

## (3) Configure your integration

Set the SCIM version to 2.0.

Fill in the endpoint into the “SCIM Base URL” field.

![A screenshot showing where to set the SCIM version and "SCIM Base URL" in Rippling.](https://images.workoscdn.com/images/a4fce113-4383-42b4-9d46-eac1e2ec6941.png?auto=format&fit=clip&q=50)

Set the SCIM authorization method to “Bearer Token” in the "SCIM Authorization Method" dropdown list. Check off features for groups, pagination, delete groups and PATCH groups.

![A screenshot showing the SCIM authorization method and configuration options in Rippling.](https://images.workoscdn.com/images/9c9c19cc-0836-4aa9-90e0-fb42d751594b.png?auto=format&fit=clip&q=50)

Add SCIM attributes `externalId`, `emails.primary`, `name.givenName`, `name.familyName` to the "Supported SCIM Attributes" input box. If you have additional custom attributes, add the appropriate corresponding Rippling values of the custom attributes. Click “Continue” to move to the next step.

![A screenshot showing the "Supported SCIM Attributes" field in Rippling.](https://images.workoscdn.com/images/566a60cf-044e-423e-b1ee-d1cbee96440b.png?auto=format&fit=clip&q=50)

Rippling will then prompt you to install the app. Click "Install now" and proceed through the next step. Then, copy and paste the Bearer Token into the “Bearer Token” field and click “Continue”.

![A screenshot showing where to enter the Bearer Token in Rippling.](https://images.workoscdn.com/images/bb2ce893-3c9e-4d97-a7f8-4e0bb7128843.png?auto=format&fit=clip&q=50)

## (4) Assign users and groups to your application

After entering the Bearer Token, the following two pages “App Access Rules” and “Provision Time”, can be filled out by your own preference. You should then arrive at the “Account Matching” page.

In order for your users and groups to be synced, you will need to assign them to your Rippling Application. Match the Rippling users to the account, or create a new application account for the user(s).

![A screenshot showing where to match Rippling users to an account in Rippling.](https://images.workoscdn.com/images/c95d76d4-721a-4626-9ee7-6e33c124bf91.png?auto=format&fit=clip&q=50)

Create groups for the application as needed.

![A screenshot showing where to create a group in Rippling.](https://images.workoscdn.com/images/49677af7-9dce-48cb-b32b-94df728644f0.png?auto=format&fit=clip&q=50)

Name the group.

![A screenshot showing where to name a group in Rippling.](https://images.workoscdn.com/images/073ca80c-42c2-4f65-abd2-50e8af89dd2b.png?auto=format&fit=clip&q=50)

Assign Rippling users/groups to the newly created application group.

![A screenshot showing where to assign users and groups to a newly created application in Rippling.](https://images.workoscdn.com/images/aa94731f-f5c3-4517-818f-383a64924dc3.png?auto=format&fit=clip&q=50)

Make sure all attributes previously added are enabled, and that their cadence is set to “On user creation and updates”. Then, click “Save” and “Continue” to finish setup.

![A screenshot showing where to ensure that all attributes are enabled in Rippling.](https://images.workoscdn.com/images/aa067d8d-b62f-459d-b640-e577a2050b67.png?auto=format&fit=clip&q=50)

In your WorkOS dashboard, you should now see the users and groups synced over.

![A screenshot showing a successfully synced user from Rippling in the WorkOS dashboard.](https://images.workoscdn.com/images/c38e1ba8-90e3-4cf0-a008-443f8c77f6a2.png?auto=format&fit=clip&q=50)

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

## Frequently asked questions

### Can I add additional custom fields to this SCIM integration?

Yes, however Rippling allows only a limited set of custom fields in SCIM applications.

- #### Available custom fields
  - `addresses.home.country`
  - `addresses.home.formatted`
  - `addresses.home.locality`
  - `addresses.home.postalCode`
  - `addresses.home.region`
  - `addresses.home.streetAddress`
  - `addresses.work.country`
  - `addresses.work.formatted`
  - `addresses.work.locality`
  - `addresses.work.postalCode`
  - `addresses.work.region`
  - `addresses.work.streetAddress`
  - `department`
  - `displayName`
  - `emails.primary`
  - `employeeNumber`
  - `externalId`
  - `manager.displayName`
  - `manager.email`
  - `manager.managerId`
  - `name.familyName`
  - `name.formatted`
  - `name.givenName`
  - `phoneNumbers.mobile`
  - `phoneNumbers.work`
  - `photos.photo`
  - `title`
  - `userType`

### Rippling SAML

Learn how to configure a connection to Rippling via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and
configure a new [Connection](/glossary/connection). Often, the information required to create
a Connection will differ by Identity Provider.

To create a Rippling SAML Connection, you’ll need the Identity Provider metadata that is available from creating an app within the Rippling instance.

Start by logging in to your WorkOS dashboard and browse to the “Organizations” tab on the left hand navigation bar.

Select the organization you wish to configure a Rippling SAML Connection for, and select “Manually Configure Connection” under “Identity Provider”.

![A screenshot showing where to select "Manually Configure Connection" in the WorkOS dashboard.](https://images.workoscdn.com/images/8fb3c79a-f154-4e74-ac23-0330f36dbb62.png?auto=format&fit=clip&q=80)

Select “Rippling SAML” from the Identity Provider dropdown, enter a descriptive name for the connection, and then select the “Create Connection” button.

![A screenshot showing the "Create Connection" modal with options configured in the WorkOS dashboard.](https://images.workoscdn.com/images/75e3d01e-a653-4ab5-a460-caced555226f.png?auto=format&fit=clip&q=80)

---

## Introduction

WorkOS provides the [ACS URL](/glossary/acs-url) and [SP Entity ID](/glossary/sp-entity-id). They’re readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/)

![A screenshot showing the "ACS URL" and "SP Entity ID" in the WorkOS dashboard.](https://images.workoscdn.com/images/b1d10058-5f92-441f-8f3d-615983e93489.png?auto=format&fit=clip&q=80)

The ACS URL is the location an Identity Provider redirects its authentication response to.

The Entity ID is a URI used to identify the issuer of a SAML request, response, or assertion. In this case, the Entity ID is used to communicate that WorkOS will be the party performing SAML requests to the organization's Rippling instance.

---

## What you’ll need

In order to integrate you’ll need the Rippling IdP metadata.

Normally, this information will come from the organization's IT Management team when they set up your application’s Rippling configuration. But, should that not be the case during your setup, here’s how to obtain them.

---

## (1) Create A New SAML Application In Rippling

Log in to Rippling as an administrator and select “IT Management” then “Custom App” from the left-side navigation bar.

!["A screenshot showing where to select "Custom App" in the Rippling dashboard.](https://images.workoscdn.com/images/a56252d2-4e9a-4839-b540-0239b0360756.png?auto=format&fit=clip&q=80)

Select “Create New App” to begin creating a new SAML application.

![A screenshot showing where to select "Create New App" in the Rippling dashboard.](https://images.workoscdn.com/images/49a2345a-bacc-4332-ad2d-a43f4884279f.png?auto=format&fit=clip&q=80)

Give the app a descriptive name, select a category, and upload a logo file. Make sure to check the box for “Single Sign-On (SAML)”, then click “Continue”.

![A screenshot showing where to configure the new app's "Name", "Categories", and app type in the Rippling dashboard.](https://images.workoscdn.com/images/f2d7947a-81eb-459d-b823-a84fc2e031ed.png?auto=format&fit=clip&q=80)

Select the option confirming that you are the Application Admin. Rippling will display a new page with “SSO Setup Instructions” we will use in the next step.

![A screenshot showing the configuration of the "Who should install the SAML App?" setting in the Rippling dashboard.](https://images.workoscdn.com/images/2a71a48e-3765-4d85-8cb2-a0111ff2c28a.png?auto=format&fit=clip&q=80)

## (2) Download IdP Metadata From Rippling

Rippling will present the SSO Setup instructions which will include the [IdP Metadata](/glossary/idp-metadata) XML file. Click to download the file from Rippling.

![A screenshot showing where to download the IdP Metadata in the Rippling dashboard.](https://images.workoscdn.com/images/b58647d3-283c-4151-b714-9b0c5c8c33b3.png?auto=format&fit=clip&q=80)

Save this file in a memorable place, as we will upload it to the WorkOS dashboard in a later step.

---

## (3) Enter Service Provider Details and Configure App Settings

Scrolling down on the SSO Setup Instructions, Rippling will request the ACS URL and Service Provider Entity ID.

Input the ACS URL and SP Entity ID from the WorkOS dashboard into the respective fields.

Once complete, click the “Move to Next Step Button”.

![A screenshot showing where to input the WorkOS ACS URL and SP Entity ID in the Rippling dashboard.](https://images.workoscdn.com/images/482b6b5e-8c29-4675-8de9-a3bbe1240c3c.png?auto=format&fit=clip&q=80)

Select your desired Access Rules.

![A screenshot showing where to select SSO Access Rules in the Rippling dashboard.](https://images.workoscdn.com/images/f0833317-cb61-4b92-894d-c2c66a0d1af3.png?auto=format&fit=clip&q=80)

Select your desired Provision Time.

![A screenshot showing where to select Provision Time in the Rippling dashboard.](https://images.workoscdn.com/images/98f45313-64ab-4bc5-b1c9-aabfa4ef3478.png?auto=format&fit=clip&q=80)

Configure SSO for Admins if necessary.

![A screenshot showing where to configure Admin SSO in the Rippling dashboard.](https://images.workoscdn.com/images/9b5ac438-7bc6-4e76-92b5-db21ce8e79ba.png?auto=format&fit=clip&q=80)

Configure Group Attributes if necessary.

![A screenshot showing where to configure Group Attributes in the Rippling dashboard.](https://images.workoscdn.com/images/8c0b2600-a5b7-46df-80d1-347daff1840c.png?auto=format&fit=clip&q=80)

Verify your SSO integration if you want to test the connection.

![A screenshot showing where to verify an SSO connection in the Rippling dashboard.](https://images.workoscdn.com/images/0d1c0474-ae85-46a9-982b-0eec7f8ab4e0.png?auto=format&fit=clip&q=80)

Click “Visit the app”. The application settings will be presented, here we will configure the SAML attribute mapping in the next step.

![A screenshot showing where to select "Visit the app" in the Rippling dashboard.](https://images.workoscdn.com/images/f67e94c8-99db-462c-943a-98e58c086fd6.png?auto=format&fit=clip&q=80)

---

## (4) Configure Attribute Mapping

Select the “Settings” tab then on the left navigation select “SAML Attributes” and use the "Create new" button. Add attributes as "Global attributes".

![A screenshot showing where to select "Create New" in the "SAML Attributes" in the Rippling dashboard.](https://images.workoscdn.com/images/8b900811-0089-4e56-a770-06bae8d097b6.png?auto=format&fit=clip&q=80)

Input the attributes as follows:

- `id` → `User’s ID`
- `email` → `User’s email address`
- `firstName` → `User’s Legal first name`
- `lastName` → `User’s Legal last name`

Here is a screenshot showing the proper final configuration:

![A screenshot showing the proper configuration of the "SAML Attributes" in the Rippling dashboard.](https://images.workoscdn.com/images/73bc17dc-fc0f-43f6-901f-a6bcd92caf17.png?auto=format&fit=clip&q=80)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, follow the guidance below.

Create a new SAML attribute and select the "Group attribute" type. Click "Continue".

![A screenshot showing how to add a group attribute in the Rippling dashboard.](https://images.workoscdn.com/images/1d904a73-9e49-4e44-b0fe-e8a2bdb9203d.png?auto=format&fit=clip&q=80)

Enter `groups` for the "Group attribute name".

![A screenshot showing what to name a group attribute in the Rippling dashboard.](https://images.workoscdn.com/images/3bbab635-f5e1-48b0-b39f-11ec75669d68.png?auto=format&fit=clip&q=80)

Select the attribute values to map to the group attribute. The example below shows two values, "Admins" and "Engineers", that map to the "All Admins" user group and the "Engineering Department" user group, respectively.

![A screenshot showing how to map the group attribute for Admins in the Rippling dashboard.](https://images.workoscdn.com/images/5a113ba9-0874-4574-95ab-a7e462dd856a.png?auto=format&fit=clip&q=80)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (5) Disable the 'InResponseTo' Field

In the “Settings” tab, on the left navigation select “Advanced SAML Settings” and use the “Edit” button to set "Disable 'InResponseTo' field in assertions for IdP initiated SSO" to true by checking the box to enable the setting.

![A screenshot showing where to enable the "Disable 'InResponseTo' field in assertions for IdP initiated SSO" setting in the Rippling dashboard.](https://images.workoscdn.com/images/46ec2824-7e3d-4b9f-93c1-56042e268477.png?auto=format&fit=clip&q=80)

The 'InResponseTo' field is primarily used for IdP-initiated SSO and enabling this setting allows WorkOS to accept both SP and IdP initiated SSO from Rippling.

Click the “Save” button to save this setting. In the next step, we will complete the integration by uploading the Metadata XML file to the WorkOS Dashboard.

---

## (6) Update Metadata File

Return to the Rippling connection in the WorkOS dashboard and select “Edit Metadata Configuration”.

![A screenshot showing where to select "Edit Metadata Configuration" in the WorkOS dashboard.](https://images.workoscdn.com/images/418a58ed-1370-4243-8c93-400c5c19d0b0.png?auto=format&fit=clip&q=80)

Upload the XML metadata file from Rippling into the “Metadata File” field and select “Save Metadata Configuration”.

![A screenshot showing where to select “Save Metadata Configuration” in the "XML File Metadata Configuration" modal in the WorkOS dashboard.](https://images.workoscdn.com/images/234fcc8b-e96a-4c66-8f7f-d2750ba337da.png?auto=format&fit=clip&q=80)

Your Connection will then be linked and good to go!

### React Native Expo

Learn how to integrate WorkOS SSO into a React Native Expo app.

## Introduction

When it comes to combining the WorkOS SSO solution with mobile applications, our advice on the general flow tends to go like this:

1. Make an API call to generate an Authorization URL.
2. Send the end user to the generated URL within their mobile browser.
3. Deep-link the end user back into your native application upon successful authentication.

With Expo, you’re able to integrate the WorkOS API with the Expo AuthSession and WebBrowser libraries, which adds web browser based authentication to your app.

---

## (1) Add AuthSession Package

To get started, you’ll want to add the `AuthSession` package to your React Native Expo project using the following:

```bash title="Install Expo’s AuthSession Package"
expo install expo-auth-session expo-random
```

We'll be using the `AuthSession.makeRedirectUri()` method to generate a RedirectUri for us to use.

## (2) Add WebBrowser Package

You’ll also want to add the `WebBrowser` package to your React Native Expo project using the following:

```bash title="Install Expo’s WebBrowser Package"
expo install expo-web-browser
```

For our purposes, we’ll specifically be using the `WebBrowser.openAuthSessionAsync()` method, which you can read more about [here](https://docs.expo.dev/versions/latest/sdk/webbrowser/#webbrowseropenauthsessionasyncurl-redirecturl-options). We will be using two arguments:

- `url`: This will be the Authorization URL we generate using the WorkOS API
- `redirect`: This will be the link back into your native Expo application once authentication is complete

## (3) Get Authorization URL

The first step in the authentication process will be to Get the Authorization URL and use it as the `url` argument in the `openAuthSessionAsync()` method. In the code, it would look something like this:

```js title="Get Authorization URL Call"
// Generate the RedirectUri and save it to a redirect variable
// You will also need to add this redirect URI to the allow list in the WorkOS Dashboard
const redirect = AuthSession.makeRedirectUri().toString();

// Pull Connection ID from environment variables
const connection_id = process.env.WORKOS_CONNECTION_ID;

// Pull Client ID from evnironment variables
const client_id = process.env.WORKOS_CLIENT_ID;

// Format the URL for the Get Authorization URL call and pass in the Client ID, Redirect URI, and Connection ID
const url = `https://api.workos.com/sso/authorize?response_type=code&client_id=${client_id}&redirect_uri=${redirect}&state=&connection=${connection_id}`;

// Call openAuthSessionAsync with the url and redirect from above, and save the returned object to a variable
const result = await WebBrowser.openAuthSessionAsync(url, redirect);

// Pull the code returned in the result stored as a param in the url field. In this case, we are using a regular expression pattern to pull it from the url.
const codeRegex = /code=([^&]+)/;
const matches = result.url.match(codeRegex);
const code = matches ? matches[1] : null;
```

## (4) Exchange OAuth Code for User Profile and Token

Once the above is in place, you will ultimately have a code which you can then exchange in one more API call for the user profile of the authenticating user. You’ll be making a POST request to Get a Profile and Token with the token, as shown here using Axios:

```js title="Exchange OAuth Code for Profile and Token"
// Use the profile returned in response.data as you need!
axios({
  method: 'post',
  url: `https://api.workos.com/sso/token?client_id=${client_id}&client_secret=${apiKey}&grant_type=authorization_code&code=${code}`,
}).then((response) => {});
```

From the end user’s side, they will be sent to the native UI of their Identity Provider in their mobile browser. After they authenticate with their credentials, they will be dropped back into the native application, ready to go.

---

## Conclusion

That’s all there is to it! By combining WorkOS SSO with React Native Expo AuthSession, adding Single Sign-On to your Expo app is a total breeze with minimal code needed.

To test the React Native Expo flow for yourself, head over to the GitHub repository of our example React Native Expo application and give it a whirl for yourself!

### PingOne SAML

Learn how to configure a connection to PingOne via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a PingOne SAML Connection, you’ll need two pieces of information: an [SP Metadata URL](/glossary/sp-metadata) from WorkOS, and an [IdP Metadata URL](/glossary/idp-metadata) from PingOne.

---

## What WorkOS provides

WorkOS provides the SP Metadata URL. It is readily available in your Connection settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot showing where to find the SP Metadata URL in the WorkOS Dashboard.](https://images.workoscdn.com/images/30a33416-afd5-4c8a-b629-392fb4666ef3.png?auto=format&fit=clip&q=50)

The SP Metadata link contains a metadata file the organization can use to set up the SAML integration. In PingOne’s case, the SP Metadata URL needs to be set by the organization when configuring your application in their PingOne instance.

Specifically, the SP Metadata URL will need to be set on the SAML Configuration page:

![A screenshot showing where the SP Metadata URL needs to be set in the PingOne settings.](https://images.workoscdn.com/images/01d0b62a-de8b-426e-a89e-f94a4f4fc721.png?auto=format&fit=clip&q=50)

---

## What you’ll need

Next, provide the PingOne IdP Metadata URL.

Normally, this information will come from the organization's IT Management team when they set up your application’s SAML 2.0 configuration in their PingOne admin dashboard. However, should that not be the case during your setup, here’s how to obtain them:

---

## (1) Log In and Select Your Application

In the PingOne Admin Console, select "Applications" (under "Connections") in the side menu. Then, select your application.

![A screenshot showing where to select a SAML app in PingOne.](https://images.workoscdn.com/images/5eecf339-0475-441c-af8b-4f7bab95d8f4.png?auto=format&fit=clip&q=50)

---

## (2) Configure Attribute Mapping

In the "Attribute Mapping" section of the PingOne SAML app, add the following field-value parameter pairs:

- `email` → `Email Address`
- `firstName` → `Given Name`
- `id` → `User ID`
- `lastName` → `Family Name`

![A screenshot showing where to configure SAML attributes in PingOne.](https://images.workoscdn.com/images/1ad40d3f-dea4-4ebc-af6f-85bfc81cce30.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, follow the guidance below.

Select the `+ Add` button once. To return the names of all groups a user is a member of, add "groups" in the "Attributes" column mapped to the "Group Names" PingOne attribute. Click "Save".

## ![A screenshot showing where to configure SAML groups attribute in PingOne.](https://images.workoscdn.com/images/750a99c5-ac7b-40b2-86fe-bb579c151606.png?auto=format&fit=clip&q=50)

Add a new `groups` attribute mapped to the "Group Names" PingOne attribute.

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (3) Obtain Identity Provider Metadata

In the "Configuration" tab, copy the "IdP Metadata URL". You’ll need this in the next step. Enable the SAML app to allow users to authenticate.

![A screenshot showing where to copy the IdP Metadata URL from in PingOne.](https://images.workoscdn.com/images/e6e6f666-d67e-4a96-b1be-d9bf015e8d62.png?auto=format&fit=clip&q=50)

---

## (4) Upload IdP Metadata URL

Finally, upload the IdP Metadata URL you saved earlier in your WorkOS Connection settings. Your Connection will then be linked and good to go!

![A screenshot showing where to upload the IdP Metadata URL in the WorkOS Dashboard.](https://images.workoscdn.com/images/0eccd480-bbb3-4ee3-8c9a-d0c65934fd15.png?auto=format&fit=clip&q=50)

### PingFederate SCIM

Learn about syncing your user list with PingFederate SCIM.

## Introduction

The PingFederate SCIM Connector can be used to enable a directory sync connection with WorkOS. Follow the steps below to set up this integration.

To synchronize an organization’s users and groups provisioned for your application, you’ll need two pieces of information:

- An [Endpoint](/glossary/endpoint) that PingFederate will make requests to
- A [Bearer Token](/glossary/bearer-token) for PingFederate to authenticate it’s endpoint requests

After completing step 1 below, both of these are available in your Endpoint’s Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

> The rest of the steps after the first will need to be carried out by the organization when configuring your application in their PingFederate instance.

---

## (1) Set up your directory in the WorkOS Dashboard

Login to your WorkOS Dashboard and select “Organizations” from the left hand navigation bar.

Select the organization you’ll be configuring a new Directory Sync with.

Click “Add Directory”.

![A screenshot showing where to add a directory in the WorkOS dashboard.](https://images.workoscdn.com/images/1bb63451-a696-4f69-9707-fa46e0b17f36.png?auto=format&fit=clip&q=50)

Select “PingFederate“ from the dropdown, and give the connection a descriptive name. Click “Create Directory”.

![A screenshot showing where to select PingFederate SCIM v2.0 as the Directory Provider in the WorkOS dashboard.](https://images.workoscdn.com/images/8809c25e-da19-4cca-8947-b92a4105e67c.png?auto=format&fit=clip&q=50)

Save the Endpoint and Bearer Token, you’ll need those in the next section when you configure the SCIM Connector application in PingFederate.

![A screenshot showing where to locate the Endpoint and Bearer Token in the WorkOS dashboard.](https://images.workoscdn.com/images/5de04f00-938d-4b1e-bced-fa342cdb1f6c.png?auto=format&fit=clip&q=50)

> We have support for custom labeled URLs for Directory Sync endpoints. [Contact us](mailto:support@workos.com) for more info!

---

## (2) Install the SCIM Connector in PingFederate

This step will take place in PingFederate. First, download and install the SCIM Connector [following the setup guide from PingFederate](https://docs.pingidentity.com/bundle/pingfederate-scim-connector/page/ulk1563995050657.html).

Next, deploy the SCIM Connector files to your PingFederate directory following [the provider’s documentation](https://docs.pingidentity.com/bundle/pingfederate-scim-connector/page/dcn1563995073633.html).

Finally, enable provisioning in PingFederate using [the documentation from PingFederate](https://docs.pingidentity.com/r/en-us/pingfederate-112/help_spconnectionconfigtasklet_saasprovisioningstate).

Once that setup has been completed, continue on to step 3.

---

## (3) Select or create your PingFederate SCIM Connector Application

Log in as an admin to your PingFederate instance, and select “Applications” → “SP Connections”.

![A screenshot showing where to locate the SP Connections area in PingFederate.](https://images.workoscdn.com/images/a3c7e38f-7184-460e-8405-9d9f7c7883df.png?auto=format&fit=clip&q=50)

Select “Create Connection”.

![A screenshot showing where to create a connection in PingFederate.](https://images.workoscdn.com/images/a5f103e4-f3b5-4808-ac9f-22ad33b3dc35.png?auto=format&fit=clip&q=50)

On the Connection Template page, select “Use a Template for this Connection” and then select “SCIM Connector” from the dropdown list. If you don’t see the SCIM Connector option, go back to the [Install SCIM Connector in PingFederate step](/integrations/pingfederate-scim/2-install-the-scim-connector-in-pingfederate). Click “Next”.

![A screenshot showing how to select the SCIM Connector template in PingFederate.](https://images.workoscdn.com/images/f3f55f2e-6a1c-4727-9c15-5e76abe9dfe7.png?auto=format&fit=clip&q=50)

On the Connection Type page, make sure Outbound Provisioning is checked with the SCIM Connector Type. Click “Next”.

![A screenshot showing where to configure outbound provisioning in PingFederate.](https://images.workoscdn.com/images/68968637-291d-472b-84fa-eb095ddcf13f.png?auto=format&fit=clip&q=50)

On the General Info page, give this connection a descriptive name, and click “Next”.

![A screenshot showing where to give the connection a name in PingFederate.](https://images.workoscdn.com/images/08096d8a-ad68-4682-bbb8-9449b9e57780.png?auto=format&fit=clip&q=50)

---

## (4) Configure Outbound Provisioning for your PingFederate application

On the Outbound Provisioning page, select the “Configure Provisioning” button.

![A screenshot showing where to click "Configure Provisioning" in PingFederate.](https://images.workoscdn.com/images/c390a6e3-bf41-4507-8b31-7d0798cfbbb1.png?auto=format&fit=clip&q=50)

On the Target page, paste in the Endpoint from your WorkOS Directory Sync Connection in the SCIM URL field. Make sure SCIM Version is set as `2.0` and the Authentication Method is set as `OAuth 2 Bearer Token`. Paste in the Bearer Token from your WorkOS Directory Sync Connection in the Access Token field. Select “Next”.

![A screenshot showing where to input provisioning settings in PingFerderate.](https://images.workoscdn.com/images/8c8fdbb5-5ebe-4a40-90b8-8c5820ba2eac.png?auto=format&fit=clip&q=50)

On the Manage Channels page, select “Create”.

![A screenshot showing where to create a channel in PingFederate.](https://images.workoscdn.com/images/a38da71d-4d75-4a43-a1a8-859988ad5cac.png?auto=format&fit=clip&q=50)

On the Channel Info page, add a descriptive name and click “Next”.

![A screenshot showing where to configure the channel name in PingFederate.](https://images.workoscdn.com/images/18896d5c-4499-4f1b-a989-be530b0a3dda.png?auto=format&fit=clip&q=50)

Select an “Active Data Store” from the dropdown menu. In this example, This example uses a PingDirectory LDAP instance, but this may be different depending on the type of data store used in each case. Please refer to the [PingFederate documentation](https://docs.pingidentity.com/bundle/pingfederate-103/page/vbe1564003005413.html) for specific settings on your type of data store. Click “Next”.

![A screenshot showing where to configure the channel source in PingFederate.](https://images.workoscdn.com/images/b7c8af75-69e0-49dd-a094-1ef29c005043.png?auto=format&fit=clip&q=50)

On the Source Settings page, make any modifications needed for your data store. In this example, the default values for the LDAP data store did not need to be modified, so the default settings were used. After configuring the source settings specific to your use case, click “Next” to go to the Source Location page.

![A screenshot showing where to configure the source settings in PingFederate.](https://images.workoscdn.com/images/dc7af973-ceae-449a-831e-f9dd9065a719.png?auto=format&fit=clip&q=50)

On the Source Location page, input a Base DN and either a Group DB or Filter for the Users. This tells your application where to look for the users to sync from your active data store. The setup used in each case may be different depending on the type of data store being used and which users and groups are to be provisioned. Please reference [PingFederate documentation](https://docs.pingidentity.com/bundle/pingfederate-103/page/jqa1564003005539.html) for specific steps. When this is complete, click “Next”.

![A screenshot showing where to configure the source location in PingFederate.](https://images.workoscdn.com/images/fa42db05-c78f-459c-ba6b-49ca4df104bd.png?auto=format&fit=clip&q=50)

---

## (5) Configure attribute mapping in PingFederate

On the Attribute Mapping page, configure the mapping of attributes in the data store to the SCIM attributes. The exact configuration will depend on the specific setup in each unique situation. For this PingDirectory LDAP example, the default settings are used. When finished, Click “Next”.

![A screenshot showing where to configure attribute mapping in PingFederate.](https://images.workoscdn.com/images/081f7d7c-b0fa-4595-adbf-ca6d0270bf8e.png?auto=format&fit=clip&q=50)

On the Activation & Summary page, check that the settings are complete, then toggle the “Channel Status” to “Active” and select “Done”.

![A screenshot showing where to check the settings and set the channel status to active in PingFederate.](https://images.workoscdn.com/images/36d37973-301d-4b36-b408-8e5dd16cc6ec.png?auto=format&fit=clip&q=50)

You are directed back to the Manage Channels page, where you can select “Done”.

![A screenshot showing where to finish the channel setup in PingFederate.](https://images.workoscdn.com/images/67eabbed-36f4-4e95-8312-210f2cb24b65.png?auto=format&fit=clip&q=50)

You’re then directed to the Outbound Provisioning page, where you can select “Next”.

![A screenshot showing where to finish the outbound provisioning setup in PingFederate.](https://images.workoscdn.com/images/8a60ece6-4ac2-4db9-993e-4aa70ac912c8.png?auto=format&fit=clip&q=50)

---

## (6) Activate the SP Connection in PingFederate

On the Activation & Summary page, turn on provisioning with the toggle at the top, and then select “Save”.

![A screenshot showing where to activate the PingFederate app.](https://images.workoscdn.com/images/cc0c979a-1444-4e8b-bd7e-925d3a834333.png?auto=format&fit=clip&q=50)

You’ll now see your SCIM application listed in the SP Connections page.

![A screenshot showing where to view the completed app in PingFederate.](https://images.workoscdn.com/images/88f2b484-d308-45ac-8e5f-64239a40e2be.png?auto=format&fit=clip&q=50)

The provisioning will automatically begin when the connection is activated through outbound requests from Ping Federate. It may take a few minutes for this process to start. Once it is synced, you’ll see a Linked status in the Directory settings in the WorkOS Dashboard.

![A screenshot showing a linked PingFederate SCIM connection in the WorkOS dashboard.](https://images.workoscdn.com/images/70241625-42f1-4a02-ba0e-5fe9f4e843eb.png?auto=format&fit=clip&q=50)

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

### PingFederate SAML

Learn how to configure a connection to PingFederate via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a PingFederate SAML Connection, you’ll need the Identity Provider metadata that is available from your PingFederate instance.

---

## What WorkOS provides

WorkOS provides the [ACS URL](/glossary/acs-url) and [SP Entity ID](/glossary/sp-entity-id). It’s readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/get-started).

![A screenshot showing where to find the ACS URL and SP Entity ID in the WorkOS Dashboard.](https://images.workoscdn.com/images/f0528e51-bb50-438c-b837-f355af202b60.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. In PingFederate’s case, the ACS URL needs to be set by the organization when configuring your application in their PingFederate instance.

Specifically, the ACS URL needs to be set as the “Endpoint URL” when defining the Protocol Settings in the SP Connection for WorkOS.

![A screenshot showing where the ACS URL needs to be set in the PingFederate settings.](https://images.workoscdn.com/images/7c626b2d-59be-489f-9890-4758e287dfbb.png?auto=format&fit=clip&q=50)

The SP Entity ID is a URI used to identify the issuer of a SAML request, response, or assertion. In this case, the entity ID is used to communicate to that WorkOS will be the party performing SAML requests to the organization's PingFederate instance.

Specifically, the SP Entity ID needs to be set as the “Partner’s Entity ID (Connection ID)” when defining the General Info Settings in the SP Connection for WorkOS.

![A screenshot showing where to set the SP Entity ID in the PingFederate settings.](https://images.workoscdn.com/images/09d9fda5-5f4f-4920-ab96-951e0a44d158.png?auto=format&fit=clip&q=50)

---

## What you’ll need

In order to integrate you’ll need the PingFederate IdP metadata.

Normally, this information will come from the organization's IT Management team when they set up your application’s SAML 2.0 configuration in their PingFederate admin dashboard. However, that should not be the case during your setup. Here’s how to obtain them:

---

## (1) Log In and Select Your Application

Log in to your PingFederate instance, go to the admin dashboard, select “Applications” at the top, and select the “SP Connections” menu option.

![A screenshot showing where to find the SP Connections section in the PingFederate admin dashboard.](https://images.workoscdn.com/images/6b0049f8-faf1-45d5-b352-58215cfc3f4a.png?auto=format&fit=clip&q=50)

---

## (2) Obtain Identity Provider Metadata

On the SP Connection list, find your WorkOS SAML 2.0 connection. Click on the “Select Action” menu and then select “Export Metadata” to download the IdP metadata.

![A screenshot showing where to download the IdP metadata file in PingFederate.](https://images.workoscdn.com/images/6fece896-4310-40fc-9b40-be471f5ea85b.png?auto=format&fit=clip&q=50)

Keep in mind where the file was saved, as we’ll be later uploading it to configure the Connection.

---

## (3) Configure Attribute Mapping

In the SP Connections dashboard, click into your desired connection. From there, click into the "Activation & Summary" tab, then click "Attribute Contract". You will need to add `id`, `email`, `firstName`, and `lastName` as attributes. Once configured, click "Next".

![A screenshot showing where to configure attribute mapping in PingFederate.](https://images.workoscdn.com/images/c6568ddb-76f4-4da1-80c4-d0964ae469dc.png?auto=format&fit=clip&q=50)

You will now need to configure an Authentication Policy Contract. To do so, click "Map New Authentication Policy", then click "Manage Policy Contracts" and "Create New Contract". Name your contract, then go to the next step and add the same four attributes we configured above. Continue through the steps, then click "Save".

![A screenshot showing where to extend the Authentication Policy Contract in PingFederate.](https://images.workoscdn.com/images/c6fb23be-81b2-4415-9fb5-655e58e60490.png?auto=format&fit=clip&q=50)

On the "Authentication Policy Mapping" page, select the Authentication Policy Contract you just made and click "Next". In the "Attribute Contract Fulfillment" tab, How you map values to the attributes listed above may differ based on how your PingFederate instance is set up. Below is an example of mapped values from both an Authentication Policy Contract and an LDAP directory. From there, save your settings on the "Summary" tab to lock in the configuration.

![A screenshot showing an example of Authentication Policy Mappings in PingFederate.](https://images.workoscdn.com/images/2141c568-0821-4aa1-899c-3fca01ecf596.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, follow the guidance below.

Navigate back to the "Attribute Contact" page and define a `groups` attribute.

![A screenshot showing where to define a groups attribute in PingFederate.](https://images.workoscdn.com/images/0aa645c4-a588-4044-aaab-a57f3e546bdc.png?auto=format&fit=clip&q=50)

Then, navigate to the "Attribute Contract Fulfillment" page and map the new `groups` attribute to the data in your provider that includes group memberships, such as the `isMemberOf` LDAP attribute in the example below.

![A screenshot showing a mapped groups attribute in the Attribute Contract Fulfillment area in PingFederate.](https://images.workoscdn.com/images/6115e8ae-c34e-4131-9d94-e6adfd94e9c1.png?auto=format&fit=clip&q=50)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (4) Upload Metadata File

In the connection settings of the WorkOS Dashboard, click “Edit Metadata Configuration”.

![A screenshot showing where to edit the Metadata Configuration in the WorkOS Dashboard.](https://images.workoscdn.com/images/2b0764f7-e045-435d-a7ed-05283f7432ac.png?auto=format&fit=clip&q=50)

In the modal, upload the PingFederate Metadata file and then select “Save Metadata Configuration”. Once the file is uploaded into WorkOS, your connection will then be linked and good to go!

![A screenshot showing where to upload the Metadata file in the WorkOS Dashboard.](https://images.workoscdn.com/images/5145a2f5-63d4-43c6-97a5-c86819d0c94b.png?auto=format&fit=clip&q=50)

### Oracle SAML

Learn how to configure a connection to Oracle via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [connection](/glossary/connection). Often, the information required to create a connection will differ by Identity Provider.

To create an Oracle SAML connection, you’ll need the Identity Provider Metadata URL that is available from the organization's Oracle SAML instance.

---

## What WorkOS provides

WorkOS provides the [ACS URL](/glossary/acs-url) and the [SP Entity ID](/glossary/sp-entity-id). They are readily available in your connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot showing where to obtain the SP Entity ID and ACS URL in the WorkOS Dashboard.](https://images.workoscdn.com/images/c1b55179-b848-40c5-b56f-dc15eb325a34.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. The SP Entity ID is a URI used to identify the issuer of a SAML request, response, or assertion.

---

## What you’ll need

In order to integrate you’ll need the IdP Metadata URL.

Normally, this will come from the organization's IT management team when they set up your application’s SAML configuration in their Oracle instance. But, should that not be the case during your setup, here’s how to obtain it.

---

## (1) Configure SAML Application with Service Provider Details

Follow the [Oracle Cloud documentation](https://docs.oracle.com/en/cloud/paas/identity-cloud/uaids/add-saml-application.html) to create a new SAML application.

Copy and paste the ACS URL and SP Entity ID into the corresponding fields for Service Provider details and configuration.

In the Advanced Settings of the SSO Configuration page, ensure that you select Signed SSO for Assertion and Response, and Include Signing Certificate in Signature.

---

## (2) Configure SAML Attributes

Expand the Attribute Configuration section on the SSO Configuration page and add the following 4 required attributes: `firstName`, `lastName`, `email`, and `id`.

Ensure the following attribute mapping is set:

- A user’s first name → `firstName`
- A user’s last name → `lastName`
- A user’s email address → `email`
- A unique identifier representing a user → `id`

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, map the groups in your identity provider to a SAML attribute named `groups`.

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (3) Obtain Identity Provider Metadata

Obtain the IdP Metadata URL following the [instructions from Oracle](https://docs.oracle.com/en/cloud/paas/identity-cloud/uaids/access-saml-metadata.html).

![A screenshot showing where the IdP Metadata URL is entered in the WorkOS Dashboard.](https://images.workoscdn.com/images/52e3e5ff-d0da-481e-8e40-a614a9c964a5.png?auto=format&fit=clip&q=50)

Alternatively, you can manually configure the connection by providing the IdP URI (Entity ID), [IdP SSO URL](/glossary/idp-sso-url) and X.509 Certificate.

![A screenshot showing the manual configuration details in the WorkOS Dashboard](https://images.workoscdn.com/images/94f7c669-02a8-4d30-9e4f-86ae58b0f318.png?auto=format&fit=clip&q=50)

Your connection will then be Active and good to go!

### OneLogin SCIM

Learn about syncing your user list with OneLogin SCIM.

## Introduction

This guide outlines how to synchronize your application’s OneLogin directories using SCIM.

To synchronize an organization’s users and groups provisioned for your application, you’ll need to provide the organization with two pieces of information:

- An [Endpoint](/glossary/endpoint) that OneLogin will make requests to.
- A [Bearer Token](/glossary/bearer-token) for OneLogin to authenticate its endpoint requests.

Both of these are available in your Endpoint’s Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

> Steps 2, 3, and 4 below will need to be carried out by the organization when configuring your application in their OneLogin instance.

---

## (1) Set up your directory sync endpoint

Login to your WorkOS Dashboard and select “Organizations” from the left hand navigation bar.

Select the Organization you’ll be configuring a new Directory Sync for.

Click “Add Directory”.

![A screenshot showing where to find “Add Directory” in the WorkOS Dashboard.](https://images.workoscdn.com/images/2c4f3933-c473-458b-97be-ea22c70f84f0.png?auto=format&fit=clip&q=50)

Select “OneLogin” from the dropdown and enter the organization name.

Then, click “Create Directory.”

![A screenshot showing "Create Directory" details in the WorkOS Dashboard.](https://images.workoscdn.com/images/0e8ef0ef-5030-46c1-a0fa-65540bc67dc5.png?auto=format&fit=clip&q=50)

Your OneLogin directory sync has now been created successfully with an Endpoint and Bearer Token.

![A screenshot showing where to find the "Endpoint" and "Bearer Token" for an organization in the WorkOS Dashboard.](https://images.workoscdn.com/images/7bad6045-0611-4c6d-8d11-754f3d878bbb.png?auto=format&fit=clip&q=50)

> We have support for custom labeled URLs for Directory Sync endpoints. [Contact us](mailto:support@workos.com) for more info!

---

## (2) Select or create your OneLogin application

Log in to the OneLogin admin dashboard, select the “Applications” tab at the top. If the application has already been created, select it and move to step 3. Otherwise, select “Add App”.

![A screenshot showing where to select "Add App" in OneLogin](https://images.workoscdn.com/images/c5f77445-e09f-4e21-8911-a240e6deee26.png?auto=format&fit=clip&q=50)

Search for “SCIM” in the text field and select the Application with type “SCIM Provisioner with SAML (SCIM V2 Enterprise)”.

![A screenshot showing where to search for “SCIM” and select the application “SCIM Provisioner with SAML (SCIM V2 Enterprise)”](https://images.workoscdn.com/images/a47d721e-db6f-490b-b3e0-9ac284bd3464.png?auto=format&fit=clip&q=50)

Give your Application a descriptive Display Name and hit “Save”.

![A screenshot showing where to add a "Display Name" to your App in OneLogin](https://images.workoscdn.com/images/4dd4042a-847e-4fde-b835-750a2f0c5644.png?auto=format&fit=clip&q=50)

---

## (3) Configure your integration

Within the SCIM Application, select the “Configuration” tab on the left.

Copy and paste the Endpoint from your [WorkOS Dashboard](https://dashboard.workos.com/) into the “SCIM Base URL” field.

Then, copy and paste the Bearer Token from your [WorkOS Dashboard](https://dashboard.workos.com/) into the “SCIM Bearer Token” field.

Hit “Enable” under “API Status” and then hit “Save”.

![A screenshot showing where to select the "Configure" tab and input your "SCIM Base URL" and "SCIM Bearer Token" in your SCIM App in OneLogin](https://images.workoscdn.com/images/12411c31-4662-4da1-9e94-7348e46ddc50.png?auto=format&fit=clip&q=50)

Select the “Provisioning” tab on the left. Check the “Enable provisioning” box and hit “Save”.

![A screenshot showing where to select "Provisioning" tab select "Enable Provisioning" in OneLogin](https://images.workoscdn.com/images/94f76ad5-30ad-4d65-a3c7-6a18ec0e0683.png?auto=format&fit=clip&q=50&w=2048)

Select the “Parameters” tab on the left. Then select “Groups”.

![A screenshot showing where to select the "Parameters" then select the "Groups" in OneLogin SCIM App](https://images.workoscdn.com/images/54c10855-69e5-4484-8ccd-44f2fe89baf3.png?auto=format&fit=clip&q=50)

In the modal that pops up, check the box next to “Include in User Provisioning” and hit “Save”.

![A screenshot showing how to select "Include in User Provisioning" in the "Parameters" tab in OneLogin](https://images.workoscdn.com/images/09795f59-f7c0-4b04-97d5-9044fb05d987.png?auto=format&fit=clip&q=50)

---

## (4) Assign users and groups to your application

In order for your users and groups to be synced, you will need to assign them to your OneLogin Application. Select “Users” from the top navigation menu.

Next, find a user you’d like to provision to the SCIM app. Within that user profile, select the “Applications” tab on the left. Then, click the “+” symbol.

![A screenshot showing where to select "+" in the "Applications" tab in OneLogin](https://images.workoscdn.com/images/ee1e01fa-26f3-49e1-8515-3fedfbdee14b.png?auto=format&fit=clip&q=50)

Select the appropriate app and hit “Continue”.

![A screenshot showing how to select SCIM App to assign OneLogin User](https://images.workoscdn.com/images/f00d45d9-7128-43dd-8bdb-cc48e7eebf7b.png?auto=format&fit=clip&q=50)

Select “Save” in the next modal to confirm the change.

![A screenshot showing how to save User Assignment in OneLogin](https://images.workoscdn.com/images/e9e5ef85-5efb-4b71-8283-e8d570f3103e.png?auto=format&fit=clip&q=50)

There are many ways to provision groups in OneLogin. Below is one method that we recommend, but other methods can be used.

In the top navigation, Select “Users” and then “Roles” from the dropdown. Select “New Role”.

![A screenshot showing how to create a "New Role" in OneLogin](https://images.workoscdn.com/images/ecb269b5-bfe0-41f7-b73f-11a152ac0197.png?auto=format&fit=clip&q=50)

Give the Role a name (this will be the name of the group), select the appropriate SCIM application, and hit “Save”.

![A screenshot showing how to configure and save the "Role" in OneLogin](https://images.workoscdn.com/images/9924f509-c60a-47b5-ae30-017c361d1b55.png?auto=format&fit=clip&q=50)

Click the “Users” tab for the role. Search for any users you’d like to assign to that role and hit “Add To Role”. Then hit “Save”.

![A screenshot showing how to add Users to "Role" in OneLogin](https://images.workoscdn.com/images/b4a4be2a-f75f-4dfe-adb9-dea585be0fce.png?auto=format&fit=clip&q=50&w=2048)

Click “Save” in the next modal to confirm.

![A screenshot showing where to click "Save" assignments to "Role" in OneLogin](https://images.workoscdn.com/images/0a6ebdb2-3896-4481-8e11-ca9f1a23ecd0.png?auto=format&fit=clip&q=50&w=2048)

Navigate back to your SCIM app and click on the “Rules” tab on the left. Then, hit “Add Rule”.

![A screenshot showing the "Rule" tab where you can then click "Add Rule" in OneLogin](https://images.workoscdn.com/images/317311e1-4fac-487f-a30e-2aeeb6e0d30a.png?auto=format&fit=clip&q=50&w=2048)

Give your Rule a name. Under “Actions”, select “Set Groups in your-app-name”. Then, set it to “For each role with value that matches your-role-name”. Hit “Save”.

![A screenshot showing how to configure a "New Mapping" in OneLogin](https://images.workoscdn.com/images/02d19425-34e2-45b3-bb64-bc3962714493.png?auto=format&fit=clip&q=50)

Within your SCIM app under the "Users" tab, you may then need to click on any “Pending” notifications to confirm the update for users.

![A screenshot showing how to confirm updates for Users under the "Users" tab in OneLogin](https://images.workoscdn.com/images/3aa55536-48e8-4322-9e5e-7227c4099f9c.png?auto=format&fit=clip&q=50)

Begin provisioning users and groups and witness realtime changes in your [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot showing a linked Directory in the WorkOS Dashboard](https://images.workoscdn.com/images/d33ff319-a791-4ed0-9df4-e7fba02bcce5.png?auto=format&fit=clip&q=50)

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

## Frequently asked questions

### When a group is removed, I don't see a `dsync.group.deleted` or `dsync.group.user_removed` events - is this expected?

It is a known issue with OneLogin SCIM that when a group is removed from the application, any user that is _only_ provisioned through that group will be "inactive" but otherwise no indication is received that the group has changed.

The users of the group must be cleaned up before the group itself is removed from the SCIM application.

### OneLogin SAML

Learn how to configure a connection to OneLogin via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create an OneLogin SAML Connection, you’ll need three pieces of information: an [ACS URL](/glossary/acs-url), an [SP Entity ID](/glossary/sp-entity-id), and the [OneLogin SAML Metadata file](/glossary/idp-metadata).

Start by logging into your [WorkOS Dashboard](https://dashboard.workos.com/) and selecting “Organizations” from the left hand navigation bar.

Click on the organization you’d like to configure a OneLogin SAML connection for and select “Manually Configure Connection”.

![A screenshot showing where to find “Manually Configure Connection” for an Organization in the WorkOS Dashboard.](https://images.workoscdn.com/images/9013d473-bfeb-4078-865b-7d40bc853748.png?auto=format&fit=clip&q=50)

Select “OneLogin SAML” from the Identity Provider dropdown, enter a descriptive name for the connection, and then select the “Create Connection” button.

![A screenshot showing how to create a connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/15df7299-f83b-4f48-be6b-b2ab6bfe228c.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

WorkOS provides the [ACS URL](/glossary/acs-url) and [SP Entity ID](/glossary/sp-entity-id). They are readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

The ACS URL is the location an Identity Provider redirects its authentication response to. In OneLogin’s case, it needs to be set by the organization when configuring your application in their OneLogin instance.

The SP Entity ID is a URI used to identify the issuer of a SAML request and the audience of a SAML response. In this case, the SP Entity ID is used to communicate that WorkOS will be the party performing SAML requests to the organization's OneLogin instance, and that WorkOS is the intended audience of the SAML responses from the OneLogin instance.

![A screenshot showing where to find the ACS URL and SP Entity ID in the WorkOS Dashboard.](https://images.workoscdn.com/images/5b7bc86b-bdcb-4ac5-a76a-a508e2d6ec0a.png?auto=format&fit=clip&q=50)

---

## What you’ll need

Next, provide the [OneLogin SAML Metadata file](/glossary/idp-metadata).

Normally, this will come from the organization's IT Management team when they set up your application’s SAML 2.0 configuration in their OneLogin admin dashboard. But, should that not be the case during your setup, the next steps will show you how to obtain it.

![A screenshot showing the “Edit Metadata Configuration” button in the WorkOS Dashboard.](https://images.workoscdn.com/images/017ac221-c3bf-40bd-8606-a04c1d41c377.png?auto=format&fit=clip&q=50)

---

## (1) Log in

Log in to [OneLogin](https://app.onelogin.com/login), go to the admin dashboard, and select “Applications” in the navigation bar.

![A screenshot showing the "Applications" button in the OneLogin Dashboard.](https://images.workoscdn.com/images/6d7cdbdf-29aa-4076-aeb3-1d055a6e76ce.png?auto=format&fit=clip&q=50)

---

## (2) Select your application

Select your application from the list of applications.

![A screenshot showing your application selection in the OneLogin Dashboard.](https://images.workoscdn.com/images/0d165d03-b73d-4e39-a85d-c81d27affd60.png?auto=format&fit=clip&q=50)

---

## (3) Configure application

Select “Configuration” from the left-hand navigation:

- Enter the SP Entity ID as the Audience (EntityID) e.g. `https://auth.workos.com/wz5SpShhRIcSEyMM`
- Enter the ACS URL as the Recipient e.g. `https://auth.workos.com/sso/saml/acs/wz5SpShhRIcSEyMM`
- Enter your ACS URL Validator e.g. `^https:\/\/auth\.workos\.com\/sso\/saml\/acs\/wz5SpShhRIcSEyMM$`
- Enter your ACS URL e.g. `https://auth.workos.com/sso/saml/acs/wz5SpShhRIcSEyMM`
- Enter your application’s login URL

![A screenshot showing how to configure URLs in your OneLogin SAML Application within the OneLogin Dashboard.](https://images.workoscdn.com/images/c9c6e8c0-fece-49c0-a72f-9bb9e087cb66.png?auto=format&fit=clip&q=50)

- Select “Service Provider” from the “SAML Initiator” dropdown menu
- Select “Assertion” from the “SAML Signature Element” dropdown menu

![A screenshot showing SAML Configuration in the SAML Application within the OneLogin Dashboard.](https://images.workoscdn.com/images/6beae398-67d7-4a3e-91cd-52e669af9ffa.png?auto=format&fit=clip&q=50)

---

## (4) Set up attribute mapping parameters

Select “Parameters” from the left-hand navigation and add the following field-value parameter pairs:

- `email` → `Email`
- `firstName` → `First Name`
- `id` → `UUID`
- `lastName` → `Last Name`

Check the “Include in SAML assertion” flag for each pair.

![A screenshot showing how to configure SAML Attribute Mapping in OneLogin Dashboard.](https://images.workoscdn.com/images/de9efebf-5767-4547-8877-02560c185b5b.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, follow the guidance below.

Add a new parameter, and set the "Field name" to `groups`. Under "Flags", click the checkboxes for both "Include in SAML assertion" and "Multi-value parameter".

![A screenshot showing where to add a groups parameter in the OneLogin Dashboard.](https://images.workoscdn.com/images/c29bb81b-3d04-4adf-8dd9-944f7ccbbc14.png?auto=format&fit=clip&q=50)

Map the `groups` field to the attribute in OneLogin containing a user’s group membership, such as "MemberOf", shown in the example below. For more information on sending group information, refer to the [OneLogin documentation](https://onelogin.service-now.com/support?id=kb_article&sys_id=6561990adb5374101c167e77f496191d).

![A screenshot showing how to map the groups parameter in the OneLogin Dashboard.](https://images.workoscdn.com/images/a70cf3c0-3d41-41d7-9c30-ee81ad497acb.png?auto=format&fit=clip&q=50)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (5) Upload Metadata File

Select “SSO” from the left-hand navigation.

Select the “More Actions” dropdown and click on “SAML Metadata”. This will download an XML metadata file.

![A screenshot showing how to download Metadata File in OneLogin Dashboard.](https://images.workoscdn.com/images/9a6cfe8d-62a7-4d2a-a1af-d57b3c02eb2e.png?auto=format&fit=clip&q=50)

In the Connection Settings of the WorkOS Dashboard, click “Edit Metadata Configuration”.

![A screenshot showing the “Edit Metadata Configuration” button in the WorkOS Dashboard. ](https://images.workoscdn.com/images/017ac221-c3bf-40bd-8606-a04c1d41c377.png?auto=format&fit=clip&q=50)

In the modal that pops up, upload the OneLogin Metadata file and then select “Save Metadata Configuration”.

![A screenshot showing the pop-up after clicking the “Edit Metadata Configuration” button in the WorkOS Dashboard.](https://images.workoscdn.com/images/cb8e0b46-b7e0-47e4-81cf-20601612b31e.png?auto=format&fit=clip&q=50)

Once the file has uploaded, your Connection will then be linked and good to go!

### Okta SCIM

Learn about syncing your user list with Okta SCIM.

## Introduction

This guide outlines how to synchronize your application’s Okta directories using SCIM.

To synchronize an organization’s users and groups provisioned for your application, you’ll need to provide the organization with two pieces of information:

- An [Endpoint](/glossary/endpoint) that Okta will make requests to.
- A [Bearer Token](/glossary/bearer-token) for Okta to authenticate its endpoint requests.

After completing step 1 below, both of these are available in your Endpoint’s Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

> The rest of the steps below will need to be carried out by the organization when configuring your application in their Okta instance.

---

## (1) Set up your Directory Sync endpoint

Login to your WorkOS Dashboard and select “Organizations” from the left hand navigation bar.

Select the organization you’ll be configuring a new Directory Sync with.

Scroll to the “User provisioning“ section. Then, click ”Configure manually“ within the ”Directory Sync” section.

![A screenshot showing where to click "Configure manually" in the WorkOS dashboard.](https://images.workoscdn.com/images/a700462c-afd2-4c12-a6cb-59bfc0d34c13.png?auto=format&fit=clip&q=50)

Select “Okta” from the Directory Provider dropdown and provide the Name for the Directory Sync connection. Then, click “Create Directory”.

![A screenshot showing where to name and create an Okta directory in the WorkOS dashboard.](https://images.workoscdn.com/images/7e564f43-2328-4c0d-a9ab-b7cf3ec7dbeb.png?auto=format&fit=clip&q=50)

You’ll see WorkOS has created the Endpoint and Bearer Token which you will provide to Okta in the steps below.

![A screenshot showing the Okta directory details in the WorkOS dashboard.](https://images.workoscdn.com/images/de45d3de-7ffc-46e0-b61c-4e8b1b9fce2e.png?auto=format&fit=clip&q=50)

> We have support for custom labeled URLs for Directory Sync endpoints. [Contact us](mailto:support@workos.com) for more info!

---

## (2) Select or create your Okta application

Log in to [Okta](https://login.okta.com/), go to the Okta admin dashboard and select “Applications” in the navigation bar.

![A screenshot showing where to select "Applications" in Okta.](https://images.workoscdn.com/images/81f7f92f-9cc1-441d-b270-6a7c794122c1.png?auto=format&fit=clip&q=50)

If your application is already created, select it from the list of applications and move to Step 3.

![A screenshot showing where to select an already created application in Okta.](https://images.workoscdn.com/images/98447a34-3e6a-404d-8419-b9f105657d1d.png?auto=format&fit=clip&q=50)

If you haven’t created a SCIM application in Okta, select “Browse App Catalog”.

![A screenshot showing where to select "Browse App Catalog" in Okta.](https://images.workoscdn.com/images/312382ac-4381-4a9b-9407-3bd5d1655a3e.png?auto=format&fit=clip&q=50)

From your Okta Application dashboard, search for “SCIM 2.0 Test App (OAuth Bearer Token)” and select the corresponding result.

![A screenshot showing where to search for "SCIM 2.0 Test App (OAuth Bearer Token)" in the App Integration Catalog in Okta.](https://images.workoscdn.com/images/12e0e6f9-1de0-49f7-95ba-960c0512387c.png?auto=format&fit=clip&q=50&w=1080)

On the following page, click “Add Integration”.

![A screenshot showing where to click "Add" in the SCIM 2.0 Test App (OAuth Bearer Token) overview page in Okta.](https://images.workoscdn.com/images/553af5dc-242b-4cf5-86e1-fe570f7b7acf.png?auto=format&fit=clip&q=50&w=1200)

Enter a descriptive App name, then click “Next”.

![A screenshot showing where to enter a name in the "Application label" field in Okta.](https://images.workoscdn.com/images/18c46d9e-e177-46b4-a462-c302b284daed.png?auto=format&fit=clip&q=50&w=1080)

Many applications will work with the default configuration that is set on your new application. If you require any additional configuration for your directory such as configuring Attribute Statements, do so on the Sign-On Options page. Click “Done” to complete creating your application.

---

## (3) Configure your Okta provisioning API integration

In your application’s Enterprise Okta admin panel, click the “Provisioning” tab. Then, click “Configure API Integration”.

![A screenshot showing where to navigate to the "Provisioning" tab to click "Configure API Integration" in Okta.](https://images.workoscdn.com/images/b78d814a-b58d-47df-9523-0bff7e7b2a42.png?auto=format&fit=clip&q=50&w=1080)

Check “Enable API Integration”. After that, copy and paste the Endpoint from your [WorkOS Dashboard](https://dashboard.workos.com/) in the SCIM 2.0 Base URL field.

Then, copy and paste the Bearer Token from your [WorkOS Dashboard](https://dashboard.workos.com/) into the OAuth Bearer Token field.

Click “Test API Credentials”, and then click “Save”.

![A screenshot showing where to configure the provisioning credentials in the "Provisioning" tab in Okta.](https://images.workoscdn.com/images/dbeae5e9-e0b8-402a-9330-4a9eaf82f05b.png?auto=format&fit=clip&q=50)

The provisioning tab will now show a new suite of options which we’ll utilize in the next Guide Section to continue provisioning your application.

---

## (4) Select options to provision to your application

In the “To App” navigation section, check to enable:

- Create Users
- Update User Attributes
- Deactivate Users

Click “Save”.

![A screenshot showing where to enable "Create Users", "Update User Attributes", and "Deactivate Users" in the "To App" tab in Okta.](https://images.workoscdn.com/images/a148a5b7-9685-4034-b871-7f0908764617.png?auto=format&fit=clip&q=50&w=1080)

---

## (5) Assign users and groups to your application

To assign users to the SCIM Application, navigate to the “Assignments” tab, from the “Assign” dropdown, select “Assign to People”.

![A screenshot showing where to select "Assign to People" in the "Assign" dropdown in the "Assignments" tab in Okta.](https://images.workoscdn.com/images/ad17bd85-3a0c-4bda-b2af-001c3451ea75.png?auto=format&fit=clip&q=50&w=1080)

Select users you’d like to provision and select “Assign”.

![A screenshot showing where to select "Assign" for specific users in Okta.](https://images.workoscdn.com/images/24edda3d-d8ea-4b4c-8bc4-23ff389baca9.png?auto=format&fit=clip&q=50&w=1080)

When you click “Assign” a lengthy form will open where you can populate all of the user’s metadata. Confirm the metadata fields, scroll down to the bottom, and press “Save and Go Back”. Repeat this for all users and select “Done”.

![A screenshot showing where to select "Save and Go Back" to complete user assignment in Okta.](https://images.workoscdn.com/images/f91bc47f-f734-453a-8bba-f3cf92d13c9e.png?auto=format&fit=clip&q=50&w=1080)

To push groups in order to sync group membership, navigate to the “Push Groups” tab, from the “Push Groups” dropdown, select: “Find groups by name”.



![A screenshot showing where to select "Find groups by name" in the "Push Groups" dropdown in the "Push Groups" tab in Okta.](https://images.workoscdn.com/images/0640cdd8-631e-4f7c-9483-c3f00f93be2f.png?auto=format&fit=clip&q=50&w=1080)

Search for the group you’d like to push and select it. Make sure the box is checked for “Push Immediately” and click “Save”.

![A screenshot showing where to search for groups to push in the "Push Groups" tab in Okta.](https://images.workoscdn.com/images/5ac81a96-1849-4c5b-8833-fa6a110e3da9.png?auto=format&fit=clip&q=50&w=1080)

In the WorkOS dashboard, you should now see the users and groups synced over.

![A screenshot showing a successfully synced user from an Okta directory in the WorkOS dashboard.](https://images.workoscdn.com/images/3bcbe3b4-e17c-40ac-8dcd-f098b52d8e8a.png?auto=format&fit=clip&q=50)

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

---

## Configuring user attribute mappings

For any non-standard attributes used by the application, some configuration may be required in Okta. Below is a guide on configuring user attribute mappings, so they propagate via SCIM.

### (1) Viewing application attributes

From the Okta administrator portal, navigate to Directory → Profile Editor, and find the application for which you'd like to edit mappings.

![Okta profile editor](https://images.workoscdn.com/images/6c58b92b-233c-4329-af2e-d024d7715081.png?auto=format&fit=clip&q=50)

Clicking into the application will bring you to a Profile Editor page:

![Okta application profile editor](https://images.workoscdn.com/images/b68c705c-b08d-4d7c-a923-41e0cf7cbfed.png?auto=format&fit=clip&q=50)

You'll likely see several attributes listed, which are scoped to the application. If you see an attribute listed you're looking to map to an application, there's no need to create a new attribute and you can skip to [step 3](/integrations/okta-scim/configuring-user-attribute-mappings/3-mapping-an-attribute).

### (2) Adding an attribute

If a desired attribute is missing from your application, click the "Add Attribute" button to create a new attribute.

![Okta profile editor add attribute](https://images.workoscdn.com/images/34a7d5da-885c-481a-b44d-60f631c7711c.png?auto=format&fit=clip&q=50)

Enter a display name and variable name of your choosing, and ensure the external name matches the key required by the third-party application. For example, if the third-party application pulls the manager value from `manager.value`, the external name should be `manager.value`.

For attributes included as part of the SCIM enterprise extension, enter the external namespace as `urn:ietf:params:scim:schemas:extension:enterprise:2.0:User`.

![Okta add attribute dialog](https://images.workoscdn.com/images/d4a7cff9-0226-4462-ab11-c086b4b4533e.png?auto=format&fit=clip&q=50)

Once you’ve entered the required information, click "Save".

### (3) Mapping an attribute

To map Okta user profile attributes to your application users, click on the “Mappings” button.

![Okta profile editor mappings](https://images.workoscdn.com/images/542ba367-6147-4ea5-bb18-4d55e13232ea.png?auto=format&fit=clip&q=50)

Mappings can be bidirectional, either from the application to the Okta user or from the Okta user to the application. This guide will focus on mapping from the Okta user to the application. Click the "Okta User to (name of application)" tab.

![Okta to application mapping tab](https://images.workoscdn.com/images/de8218c4-b96b-4761-85e9-6843b200e445.png?auto=format&fit=clip&q=50)

Find the name of the attribute you’d like to map in the right column. In the corresponding row's left column, enter the name of the Okta user profile attribute you’d like to map over. For example, if you’re looking to map manager email in the application, select `managerId` in the left column.

![Okta mapping select attribute](https://images.workoscdn.com/images/97fafcf8-0845-4e09-8699-7ec5560255ce.png?auto=format&fit=clip&q=50)

Ensure the apply mappings setting is set to "Apply mapping on user create and update".

![Okta apply mappings selection](https://images.workoscdn.com/images/d1a3c86a-36e9-49ba-bf5a-7538c0992aa5.png?auto=format&fit=clip&q=50)

Once your mappings are configured, click "Save Mappings" and "Apply updates now". These new attribute mappings will now propagate to the application.

## Frequently asked questions

### When a user is assigned to the SCIM app via a group, I don’t see a user removed webhook if the user is removed from the group – is this expected?

It is a known issue with Okta SCIM that if a user is assigned to a SCIM app via a group, you won’t see a `dsync.group.user_removed` event if the user is removed from the group. This is a limitation in Okta, where group memberships are not updated in this case. The user needs to be assigned directly to the SCIM app, and the group needs to be pushed in the SCIM app. If those two conditions are met, Okta will send the correct group membership updates.

### How often do the Okta SCIM 2.0 directories perform a sync?

The Okta SCIM 2.0 directory syncs events in real time.

### Why is a user suspended in Okta still active in WorkOS?

Suspending a User in Okta will only affect their login and will not alter their status in any connected applications.

Deactivating or Deleting a User in Okta will result in a `inactive` status in connected applications (i.e., WorkOS).

For more details, please refer to Okta's official documentation
[User Suspension](https://help.okta.com/en-us/content/topics/users-groups-profiles/usgp-suspend.htm)
[User Deactivation and Deletion](https://help.okta.com/en-us/content/topics/users-groups-profiles/usgp-deactivate-user-account.htm).

### What is the `idp_id` for directory groups from Okta?

Okta only provides a group display name as a group identifier, so this display name is persisted as the `idp_id` and `name` for [directory groups](/reference/directory-sync/directory-group) in WorkOS.

### Okta SAML

Learn how to configure a connection to Okta via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create an Okta Connection, you’ll need three pieces of information: an [ACS URL](/glossary/acs-url), an [SP Entity ID](/glossary/sp-entity-id), and an [IdP Metadata URL](/glossary/idp-metadata).

Start by logging in to your WorkOS dashboard and browse to the “Organizations” tab on the left hand navigation bar.

Select the organization you’d like to configure an Okta Connection for, and select “Manually Configure Connection” under “Identity Provider”.

![A screenshot showing where to find "Manually Configure Connection" in the WorkOS Dashboard.](https://images.workoscdn.com/images/9270090d-4f59-4b7b-95e9-1132a6bee872.png?auto=format&fit=clip&q=50)

Select “Okta SAML” from the Identity Provider dropdown, enter a descriptive name for the connection, and then select the “Create Connection” button.

![A screenshot showing "Create Connection" details in the WorkOS Dashboard.](https://images.workoscdn.com/images/287303da-4bbd-433b-bdd2-06f5002dd5ca.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

WorkOS provides the ACS URL and the SP Entity ID. It’s readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/get-started).

![A screenshot showing where to find the ACS URL and SP Entity ID in the WorkOS Dashboard.](https://images.workoscdn.com/images/ad4ef355-6ea7-4e27-9762-91309c34dc2d.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. In Okta’s case, it needs to be set by the organization when configuring your application in their Okta instance.

The SP Entity ID is a URI used to identify the issuer of a SAML request, response, or assertion. In this case, the entity ID is used to communicate that WorkOS will be the party performing SAML requests to the organization's Okta instance.

Specifically, the ACS URL will need to be set as the “Single Sign-On URL” and the SP Entity ID will need to be set as the “Audience URI (SP Entity ID)” in the “Configure SAML” step of the Okta “Edit SAML Integration” wizard:

![A screenshot showing where to place the WorkOS Single Sign-On URL and SP Entity ID in the Okta Dashboard.](https://images.workoscdn.com/images/52be9941-9e43-4f70-a65e-d4cd8883579c.png?auto=format&fit=clip&q=50)

## What you’ll need

Next, provide the [IdP Metadata URL](/glossary/idp-metadata). Normally, this information will come from the organization's IT Management team when they set up your application’s SAML 2.0 configuration in their Okta admin dashboard. But, should that not be the case during your setup, the next steps will show you how to obtain it.

---

## (1) Log in

Log in to [Okta](https://login.okta.com), go to the admin dashboard, and select “Applications” in the navigation bar.

![A screenshot showing how to navigate to existing applications in the Okta Dashboard.](https://images.workoscdn.com/images/b4f8bd68-3265-4ef6-8916-1f9e7eb241a1.png?auto=format&fit=clip&q=50)

---

## (2) Select or create your application

If your application is already created, select it from the list of applications and move to Step 7.

![A screenshot showing existing applications in the Okta Dashboard.](https://images.workoscdn.com/images/f763ab3c-0ffc-49b7-8212-f988d0738e94.png?auto=format&fit=clip&q=50)

If you haven’t created a SAML application in Okta, select “Create App Integration”.

![A screenshot showing how to select "Create App Integration" in the Okta Dashboard.](https://images.workoscdn.com/images/cf63d4f1-3929-4426-a0df-959bbd06ce13.png?auto=format&fit=clip&q=50)

---

## (3) Initial SAML Application Setup

Select “Create New App”, then select “SAML 2.0” as a Sign on method, then click “Next”.

![A screenshot showing the sign-in method selection in the Okta Dashboard.](https://images.workoscdn.com/images/036519d9-1d5a-462f-8d36-e87b618a3e94.png?auto=format&fit=clip&q=50)

Enter a descriptive App name, then click “Next”.

![A screenshot showing App name creation in the Okta Dashboard.](https://images.workoscdn.com/images/facbcbea-3ce0-421e-9725-e05e49bc056a.png?auto=format&fit=clip&q=50)

---

## (4) Configure SAML Application

Input the ACS URL from your WorkOS Dashboard as the “Single Sign-On URL” and input the SP Entity ID from your WorkOS Dashboard as the “Audience URI (SP Entity ID)”.

![A screenshot showing where to place the WorkOS Single Sign-On URL and SP Entity ID in the Okta Dashboard.](https://images.workoscdn.com/images/52be9941-9e43-4f70-a65e-d4cd8883579c.png?auto=format&fit=clip&q=50)

Scroll down to the “Attribute Statements” section and use the “Add Another” button to add the following key-value pairs.

- `id` → `user.id`
- `email` → `user.email`
- `firstName` → `user.firstName`
- `lastName` → `user.lastName`

![A screenshot showing the "Attribute Statements" configuration in the Okta Dashboard.](https://images.workoscdn.com/images/93f6811f-9f56-47a2-bfa0-d4babc91f66e.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, follow the guidance below.

Scroll down to the Group Attribute Statements configuration. The Name should be set to `groups`, and you can define a filter to map the necessary Okta groups. To map all groups, filter by matching the regex `.*`, as shown in the screenshot below. You can preview the SAML Assertion to check that all attributes have been mapped correctly. Then, click “Next”.

![A screenshot showing the "Groups Attribute Statement" configuration in the Okta Dashboard.](https://images.workoscdn.com/images/723c0734-a8cc-4903-a90d-273dfe282886.png?auto=format&fit=clip&q=50)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (5) Submit Application Feedback

Select “I’m an Okta customer adding an internal app” from the options menu. Complete the form with any comments and select “Finish”.

![A screenshot showing where to submit application feedback in the Okta Dashboard.](https://images.workoscdn.com/images/734d5229-1913-4cfb-b366-295104da4123.png?auto=format&fit=clip&q=50)

---

## (6) Add Users to SAML Application

To give users permission to authenticate via this SAML app, you will need to assign individual users and/or groups of users to the Okta app.

Click on the “Assignments” tab, and select either “Assign to People” or “Assign to Groups”.

![A screenshot showing the Okta Application "Assignments" tab in the Okta Dashboard.](https://images.workoscdn.com/images/a8380fe9-9e90-48ff-b665-8313311c28d1.png?auto=format&fit=clip&q=50)

Find the individual user(s) and/or group(s) that you would like to assign to the app, and click “Assign” next to them. Click “Done” when you are finished.

![A screenshot showing the selecting of groups to add to the Application in the Okta Dashboard.](https://images.workoscdn.com/images/c4fddfdc-35b2-4a4f-9d84-1a7e94968d24.png?auto=format&fit=clip&q=50)

---

## (7) Upload Metadata URL

Click on the “Sign On” tab of the SAML app you just created.

Click the “Actions” dropdown for the correct certificate and select “View IdP Metadata."

![A screenshot showing the "View IdP Metadata" selection in the Okta Dashboard.](https://images.workoscdn.com/images/e98e855e-6733-4f6e-96da-5c993cebd21b.png?auto=format&fit=clip&q=50&w=2048)

A separate tab will open. Copy the link in the browser.

![A screenshot of the IdP Metadata XML URL in the Okta Dashboard.](https://images.workoscdn.com/images/eab81ff3-8037-4cd6-94ef-b00962084ad0.png?auto=format&fit=clip&q=50)

Back in the WorkOS Dashboard, click on “Edit Metadata Configuration” in the “Identity Provider Configuration” section of the Connection. Input the Metadata URL and click “Save Metadata Configuration”. Your Connection will then be linked and good to go!

![A screenshot showing where to place the Okta IdP Metadata URL in the WorkOS Dashboard.](https://images.workoscdn.com/images/a08a0c17-d510-4410-91cb-4477cfe310c8.png?auto=format&fit=clip&q=50)

### Okta OIDC

Learn how to configure a connection to Okta via OIDC.

## Introduction

Each SSO identity provider requires specific information to create and configure a new [SSO connection](/glossary/connection). Often, the information required to create an SSO connection will differ by identity provider.

To create an Okta OIDC SSO connection, you'll need four pieces of information: a [redirect URI](/glossary/redirect-uri), [client ID](/glossary/client-id), [client secret](/glossary/client-secret), and [discovery endpoint](/glossary/discovery-endpoint).

Start by logging in to your WorkOS dashboard and navigate to the **Organizations** page from the left-hand navigation bar.

Select the organization you'd like to configure an Okta OIDC SSO connection for, and select **Configure manually** under **Single Sign-On**.

![WorkOS Dashboard Organizations tab with "Configure manually" button highlighted](https://images.workoscdn.com/images/d577cfbe-028b-48cf-8cc0-4cd5d3adf853.png?auto=format&fit=clip&q=50)

Select **Okta OIDC** from the identity provider dropdown, enter a descriptive name for the connection, click **Create Connection**.

![Create Connection form with Okta OIDC selected as Identity Provider](https://images.workoscdn.com/images/6e60c859-936e-4894-ac88-0524565ef8c8.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

WorkOS provides the Redirect URI, which can be found in the **Service Provider Details** section on the SSO connection page in the [WorkOS Dashboard](https://dashboard.workos.com/).

- [Redirect URI](/glossary/redirect-uri): The endpoint where identity providers send authentication responses after successful login

![The Redirect URI of a OIDC connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/99a7c7d5-50a9-4bff-a3f3-22dc1cfeca58.png?auto=format&fit=clip&q=50)

The Redirect URI is the location an identity provider redirects its authentication response to. In Okta's case, it needs to be set as the **Sign-in redirect URI** when configuring your OIDC application in their Okta instance.

Specifically, the Redirect URI will need to be added to the **Sign-in redirect URIs** section in the **Create OpenID Connect Integration** wizard, which is outlined in [step 2](/integrations/okta-oidc/2-configure-the-integration).

---

## What you'll need

You will need to obtain three pieces of information from the organization:

- [Client ID](/glossary/client-id): Application identifier from the OIDC provider
- [Client secret](/glossary/client-secret): Authentication secret for the application
- [Discovery endpoint](/glossary/discovery-endpoint): Configuration URL containing OIDC metadata

Normally, this information will come from the organization's IT Management team when they set up your application's OIDC configuration in their Okta admin dashboard. But, should that not be the case during your setup, the next steps will show you how to obtain it.

---

## (1) Create OIDC integration

Log in to the Okta admin console, and select **Applications** in the left-hand sidebar.

![Okta admin console navigation menu with Applications tab highlighted](https://images.workoscdn.com/images/d3e05208-2c35-4cba-a592-62aadf2752a1.png?auto=format&fit=clip&q=50)

Click **Create App Integration**.

![Okta Applications page with "Create App Integration" button](https://images.workoscdn.com/images/8059f5a3-0c46-45fb-a4db-30c13c0fc0de.png?auto=format&fit=clip&q=50)

In the **Create a new app integration** dialog, select **OIDC - OpenID Connect** and **Web Application**.

![Create app integration dialog with OIDC - OpenID Connect and Web Application selected](https://images.workoscdn.com/images/d6b2f9e8-42f4-4279-9adf-6954644a9758.png?auto=format&fit=clip&q=50)

Click **Next**.

---

## (2) Configure the integration

Enter a descriptive App name, then configure the Sign-in redirect URI.

![OIDC app configuration form with app name field and sign-in redirect URI section](https://images.workoscdn.com/images/7ed6bf17-6839-48f2-b796-883b181c1e79.png?auto=format&fit=clip&q=50)

Locate the **Sign-in redirect URIs** section and click **Add URI**. Copy the [Redirect URI](/integrations/okta-oidc/what-workos-provides) from the SSO connection page in your WorkOS Dashboard and paste it into this field.

![Sign-in redirect URIs configuration with WorkOS redirect URI entered](https://images.workoscdn.com/images/fa2cc4f3-a11a-4612-8b58-4739385babac.png?auto=format&fit=clip&q=50)

Scroll down to the **Assignments** section. Select **Limit access to selected groups** and assign the appropriate groups to the application. This can be edited later.

![Assignments section with "Limit access to selected groups" option selected](https://images.workoscdn.com/images/743f90a9-aa9d-48a1-94e4-05b1743f9e81.png?auto=format&fit=clip&q=50)

Click **Save**.

---

## (3) Obtain configuration details

On the **General** tab, locate the **Client ID** and **Client secret**. Back in the WorkOS Dashboard, enter the client ID, and client secret into the respective fields in the **Identity Provider Configuration** section of the SSO connection.

![Okta app General tab showing Client ID and Client secret fields](https://images.workoscdn.com/images/20ac0b30-2575-401c-973d-016c8a18efe9.png?auto=format&fit=clip&q=50)

In the top right-hand navigation, click your user email and locate the **Okta tenant domain** which usually ends with `.okta.com`.

Copy this value and define the discovery endpoint in the format: `https://{tenant-domain}/.well-known/openid-configuration`. Enter this URL in the **Discovery Endpoint** field in the WorkOS dashboard.

![WorkOS Dashboard Identity Provider Configuration with client ID, client secret, and discovery endpoint fields](https://images.workoscdn.com/images/24179b09-b86d-46f8-9375-95b9ff9abd36.png?auto=format&fit=clip&q=50)

Click **Save Configuration**.

---

## (4) Role assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. Users will automatically be granted the assigned roles within your application when they authenticate. To enable this functionality:

### Set groups claim in Okta

Navigate to the **Sign On** tab of your OIDC application, locate the **Claims** section, and click **Edit**.

![Okta app Sign On tab with Claims section and Edit button](https://images.workoscdn.com/images/d699c5cb-c4f1-4299-acbe-7ed4cc1dfee9.png?auto=format&fit=clip&q=50)

Set the **Groups claim type** to **Filter**. Define the **Groups claim filter** as `groups` and set a filter to match the appropriate Okta groups. To match all groups, use the regex `.*` as shown below.

![Groups claim configuration with claim type set to Filter and groups claim filter field](https://images.workoscdn.com/images/4face13e-e7e3-48dd-8a8e-7938c93840d6.png?auto=format&fit=clip&q=50)

### Configure role assignment in WorkOS

In Okta, navigate to the **Assignments** tab in the application. Locate the **Filters** sidebar, click on **Groups** to filter and display all the assigned groups available to map.

![Okta dashboard showing assigned groups](https://images.workoscdn.com/images/17d32c5b-fc4b-458b-98f6-99c774af1522.png?auto=format&fit=clip&q=50)

From the SSO connection page in the [WorkOS Dashboard](https://dashboard.workos.com/), scroll to the **Groups and role assignments** section.

![WorkOS dashboard highlighting create group button](https://images.workoscdn.com/images/c29ef1a7-d873-49f6-ad43-8c945245a033.png?auto=format&fit=clip&q=50)

For each group you want to assign a role, click the **Create group** button and enter the following:

1. Copy the group name from Okta into the **IdP ID** field.
2. Optionally, enter a group name into the **Name** field.
3. Assign the appropriate role to the group.

![WorkOS dashboard with open create group dialog and idp_id, name, and role assignment inputs](https://images.workoscdn.com/images/d542c8c3-e032-41a6-ae72-c8dc586ec88d.png?auto=format&fit=clip&q=50)

> Group members without an explicit role will receive the default role.

---

## Next steps

Your Okta OIDC connection is now configured and ready to use. Users assigned to the application in Okta will be able to authenticate through WorkOS using their Okta credentials.

To start using this connection in your application, refer to the [SSO guide](/sso) for implementation details.

### OpenID Connect

Learn how to configure a new generic OIDC connection

## Introduction

To set up an OpenID Connect (OIDC) connection on behalf of an organization, you'll need the client credentials and the discovery endpoint of their OIDC provider from the organization's IT team.

---

## What WorkOS provides

When setting up an OIDC connection, WorkOS provides one key piece of information in the **Service Provider Details** section for an SSO connection within the [WorkOS Dashboard](https://dashboard.workos.com/):

- [Redirect URI](/glossary/redirect-uri): The endpoint where identity providers send authentication responses after successful login

![The Redirect URI of a OIDC connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/99a7c7d5-50a9-4bff-a3f3-22dc1cfeca58.png?auto=format&fit=clip&q=50)

The **Redirect URI** serves as the destination for authentication responses and must be configured in the organization's identity provider admin dashboard.

---

## What you will need

You will need to obtain three pieces of information from the organization:

- [Client ID](/glossary/client-id): Application identifier from the OIDC provider
- [Client Secret](/glossary/client-secret): Authentication secret for the application
- [Discovery Endpoint](/glossary/discovery-endpoint): Configuration URL containing OIDC metadata

Typically, the organization's IT team will provide these values when they configure your application in their identity provider admin dashboard. However, if you need to guide them through the process, the following sections will help.

---

## (1) Create an application with the identity provider

For SSO to properly function, the organization needs to create and configure an OpenID Connect application in their identity provider that supports the authorization code grant type.

Copy the **Redirect URI** from the WorkOS Dashboard connection settings.

Instruct the organization admin to paste this value as the login redirect URI in their OIDC application configuration. This ensures authentication responses are sent to the correct WorkOS endpoint.

---

## (2) Configure ID token claims

The organization's OIDC provider needs to include specific claims in the user ID token. Instruct them to add the following claims to their OIDC provider settings:

- `sub`: Maps to the `idp_id` attribute in WorkOS user profiles
- `email`: Maps to the `email` attribute in WorkOS user profiles
- `given_name`: Maps to the `first_name` attribute in WorkOS user profiles
- `family_name`: Maps to the `last_name` attribute in WorkOS user profiles

For many providers, these claims are included by default, but some providers require manual configuration.

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To enable this functionality, instruct the organization to add the `groups` claim to the user ID token in their OIDC provider settings. This claim should map to a list of the user's group memberships.

> Finish role assignment set-up by navigating to the SSO connection page in the **Organizations** section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (3) Obtain client credentials and discovery endpoint

After the organization creates an OpenID Connect application, their identity provider will provision client credentials and a discovery endpoint.

The discovery endpoint will always end with `/.well-known/openid-configuration` as described in the [OpenID Provider Configuration Request documentation](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationRequest). You can confirm that the discovery endpoint is correct by entering it in a browser window. If there is a JSON object with metadata about the connection returned, the endpoint is correct.

In the WorkOS Dashboard, navigate to your connection settings. Paste the **Client ID**, **Client Secret**, and **Discovery Endpoint** values from the organization's IT team into their respective input fields. Click **Update connection**.

![Input the Client ID, Client Secret, and Discovery Endpoint in the WorkOS Dashboard](https://images.workoscdn.com/images/ed603b39-a06e-4c2f-b96f-7cadaa793be4.png?auto=format&fit=clip&q=50)

### NextAuth.js

Create a Next.js application with WorkOS SSO and NextAuth.js.

## Introduction

In this guide, you’ll learn how to use WorkOS to add Single Sign-On (SSO) to a Next.js app that uses [NextAuth.js](https://next-auth.js.org/) for handling authentication. You can check out the [complete source code](https://github.com/workos/workos-next-auth) of this guide on GitHub.

## Before getting started

To get the most out of this guide, you’ll need:

- A [WorkOS account](https://dashboard.workos.com/)
- An IdP (e.g. Okta) account

## (1) Install sample application

In your a terminal, browse to the directory of your choice and run the following command to clone the starter project:

```bash title="Clone the Sample App"
git clone -b start-branch https://github.com/workos-inc/workos-next-auth
```

And install the dependencies

```bash title="Install the Dependencies"
npm install
```

This is a basic Next.js app built using TypeScript and styled using TailwindCSS.

## (2) Configuring the environment variables

In the project’s root folder, rename the `.env.example` file to `.env`. You can find down below the values for the WorkOS client ID and API key.

```plain title=".env"
WORKOS_API_KEY='sk_example_123456789'
WORKOS_CLIENT_ID='client_123456789'
```

As a best practice, your WorkOS API key should be kept secret and set as an environment variable on process start. The SDK is able to read the key automatically if you store it in an environment variable named `WORKOS_API_KEY`; otherwise, you will need to set it manually. The [Client ID](/glossary/client-id) should also be set dynamically based on the release environment.

## (3) SSO Setup with WorkOS

The first step is to create an organization, which can be done using the dashboard or [via the API](/reference/organization/create). By default, WorkOS creates a demo organization called “foo-corp.com” which you can use for testing purposes.

Take note of the “Organization ID” which can be found in the organization’s detailed view. You’re going to need it to make SSO work.

![A screenshot highlighting the "Organization ID" in the WorkOS dashboard.](https://images.workoscdn.com/images/af4ef014-f6c4-44b2-b7cc-ccf2db24bde5.png?auto=format&fit=clip&q=50)

## (4) Configure redirect URIs

In the “Configuration” tab in the dashboard, add `http://localhost:3000/api/auth/callback/workos` to the list of redirect URIs to test the SSO login flow locally. You’ll also need to add the domain of your application when deploying to production.

![A screenshot highlighting the redirect URIs in the "Configuration" tab in the WorkOS dashboard.](https://images.workoscdn.com/images/7005a351-b083-4a08-a096-cb227c21caa5.png?auto=format&fit=clip&q=50)

## (5) Create an API endpoint

The next step is to create a `pages/api/auth/[...nextauth].ts` file which will contain all of your NextAuth.js configurations:

```js title="pages/api/auth/[...nextAuth].ts"
;
;

export default NextAuth({
  providers: [
    WorkOSProvider({
      clientId: process.env.WORKOS_CLIENT_ID,
      clientSecret: process.env.WORKOS_API_KEY,
      client: {
        token_endpoint_auth_method: 'client_secret_post',
      },
    }),
  ],
  pages: {
    signIn: '/login',
  },
  debug: true,
  secret: process.env.SECRET,
});
```

You’re first configuring WorkOS by passing the necessary options to the `WorkOSProvider()` function. You’re then defining a custom login page using the pages option which will be located at `/login`.

You then need to wrap the global `App` component with `SessionProvider` from `NextAuth.js`. Add the following code to the `pages/_app.tsx` file:

```js title="pages/_app.tsx"
import '../styles/index.css';
;
;

export default function App({
  Component,
  pageProps: { session, ...pageProps },
}: AppProps) {
  return (
    
  );
}
```

## (6) Creating a custom login page

In this step, you’ll create a custom login page. To do that, create a new file located at `pages/login.tsx` and add the following code to it:

```js title="pages/login.tsx"
;
;
;
;

const Login = () => {
  const {
    register,
    handleSubmit,
    formState: { errors },
  } = useForm();

  const { data: session } = useSession();

  const onSubmit = async ({ team }) => {
    // TODO: send a request to the get-organization endpoint and return the
    // organizationId from your database
    const organization = 'ORGANIZATION_ID';
    signIn('workos', undefined, {
      organization,
    });
  };

  return (
    <>
      
      {session && (
        
          Signed in as {session.user.email}
          
           signOut()}
            className="max-w-sm flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500"
          >
            Sign out
          
        
      )}
      {!session && (
        
          
            
              
            
            
              Continue using enterprise SSO
            </h2>
          

          
            
              
                
                  
                    Team name
                  
                  
                    
                  
                

                
                  
                    Sign in
                  
                
              
            
          
        
      )}
    </>
  );
};

export default Login;
```

Next, start the development server by running the following command:

```bash title="Start Server"
npm run dev
```

The application will be running at `http://localhost:3000/login` and you’ll be able to see the following page:

![A screenshot showing the landing page of the example application.](https://images.workoscdn.com/images/af8ddee4-e7f1-49a1-9e7c-05e190b31d6e.png?auto=format&fit=clip&q=50)

## (7) Testing the Single Sign-On flow

You should persist The Organization ID in your application’s database and associate it with your enterprise customer. Then when a user tries to log in, you first check if they’re an enterprise customer and then use the `signIn()` function from NextAuth.js to start the login flow.

To test the login flow, hardcode the Organization ID in the form submission handler.

```js title="pages/login.tsx"
// code above unchanged

const onSubmit = async ({ team }) => {
  // TODO: create an endpoint that returns the
  // organizationId from your database
  /* +diff-start */
  const organization = 'ORGANIZATION_ID';
  /* +diff-end */
  signIn('workos', undefined, {
    organization,
  });
};

// code below unchanged
```

If you type anything in the login form and click submit, you’ll be redirected to Okta. You’ll then need to use your IdP login credentials.

After you complete the login process you’ll see the logged-in user’s email and a “Sign out” button

![A screenshot showing the example application with a successfully logged in user.](https://images.workoscdn.com/images/7fd5daef-1cd9-401d-9884-3130b7b3a095.png?auto=format&fit=clip&q=50)

If you’re interested in setting up a different Identity Provider, check out the [full list of tutorials](/sso) for setting up an SSO connection.

### NetIQ

Learn how to configure a connection to NetIQ via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a NetIQ SAML Connection, you’ll need the Identity Provider metadata that is available from the organization's NetIQ instance.

Start by logging in to your WorkOS dashboard and browse to the “Organizations” tab on the left hand navigation bar.

Select the organization you’d like to configure an NetIQ SAML Connection for, and select “Manually Configure Connection” under “Identity Provider”.

![A screenshot showing where to find "Manually Configure Connection" in the WorkOS Dashboard.](https://images.workoscdn.com/images/c6f1423d-020f-4560-aed0-ca4895b5fbc1.png?auto=format&fit=clip&q=50)

Select "NetIQ SAML” from the Identity Provider dropdown, enter a descriptive name for the connection, and then select the “Create Connection” button.

![A screenshot showing "Create Connection" details in the WorkOS Dashboard.](https://images.workoscdn.com/images/5c854a7c-0180-45de-aeda-8b52d8275b75.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

WorkOS provides the [ACS URL](/glossary/acs-url), the [SP Metadata](/glossary/sp-metadata) link and the [SP Entity ID](/glossary/sp-entity-id). They are readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot showing where to find the ACS URL and SP Entity ID in the WorkOS Dashboard.](https://images.workoscdn.com/images/e102db99-be9d-4aa5-b250-a690ce57d16e.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. The SP Metadata link contains a metadata file that the organization can use to set up the SAML integration. The SP Entity ID is a URI used to identify the issuer of a SAML request, response, or assertion.

---

## What you’ll need

In order to integrate you’ll need the [IdP Metadata URL](/glossary/idp-metadata).

Normally, this will come from the organization's IT Management team when they set up your application’s SAML 2.0 configuration in their NetIQ instance. But, should that not be the case during your setup, here’s how to obtain it.

---

## (1) Enter Service Provider Details

Copy and paste the “ACS URL” and “SP Entity ID” into the corresponding fields for Service Provider details and configuration. For some setups, you can use the metadata found at the SP Metadata link to configure the SAML connection.

---

## (2) Obtain Identity Provider Metadata

Copy the IdP Metadata URL from your NetIQ SAML settings and upload it to your WorkOS Connection settings. Your Connection will then be linked and good to go!

![A screenshot showing where to place the NetIQ IdP Metadata URL in the WorkOS Dashboard.](https://images.workoscdn.com/images/e26ae490-1f53-4d88-8c0e-50bb8ed2be64.png?auto=format&fit=clip&q=50)

Alternatively, you can manually configure the connection by providing the IdP URI (Entity ID), [IdP SSO URL](/glossary/idp-sso-url) and X.509 Certificate.

![A screenshot showing where to switch to Manual Configuration in the connections detail page.](https://images.workoscdn.com/images/20ea5490-7344-43f4-95bb-129e3aa44595.png?auto=format&fit=clip&q=50)

![A screenshot showing to click "Save Configuration" upon entering the Metadata data.](https://images.workoscdn.com/images/1a39b96e-3564-43b2-82e7-082f74ff4713.png?auto=format&fit=clip&q=50)

---

## (3) Configure Attribute Mapping

At minimum, the Attribute Statement in the SAML Response should include `id`, `email`, `firstName`, and `lastName` attributes.

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, map the groups in your identity provider to a SAML attribute named `groups` to return this information in the attribute statement.

Once your SAML app is configured to return groups, navigate to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

### miniOrange

Learn how to configure a connection to miniOrange via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a miniOrange SAML Connection, you’ll need an IdP Metadata URL.

Start by logging in to your WorkOS dashboard and browse to the “Organizations” tab on the left hand navigation bar.

Select the organization you’d like to configure a miniOrange SAML Connection for, and select “Manually Configure Connection” under “Identity Provider”.

![A screenshot showing the Manual Configure Connection option in the WorkOS Dashboard.](https://images.workoscdn.com/images/24066931-e200-4e59-9996-3e28738a5b48.png?auto=format&fit=clip&q=50)

Select “miniOrange SAML” from the Identity Provider dropdown, enter a descriptive name for the connection, and then select the “Create Connection” button.

![A screenshot showing a miniOrange connection being created in the WorkOS Dashboard.](https://images.workoscdn.com/images/08437cb1-adc7-422e-83d9-4886cba0ece3.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

WorkOS provides the [ACS URL](/glossary/acs-url), [SP Entity ID](/glossary/sp-entity-id) and [SP Metadata URL](/glossary/sp-metadata). They’re readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/). For this configuration, you should only need to use the SP Metadata URL, but other fields are provided should you choose to do a more manual configuration.

![A screenshot showing the Service Provider Details provided by WorkOS for a miniOrange connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/0cf5969a-7cc5-4646-89bb-b19a7c54ec60.png?auto=format&fit=clip&q=50)

---

## What you’ll need

Next, provide the IdP Metadata URL. Normally, this information will come from the organization's IT Management team when they set up your application’s SAML 2.0 configuration in their miniOrange admin dashboard. But, should that not be the case during your setup, the next steps will show you how to obtain it.

---

## (1) Select or create your application

Log in to [miniOrange](https://login.xecurify.com/moas/login), go to the admin dashboard and select “Apps” on the left side navigation. If your application is already created, select it from the list of applications and move to Step 2. Otherwise, select “Add Application”.

![A screenshot showing where to select Add Application in the miniOrange dashboard.](https://images.workoscdn.com/images/d7abb7b9-41ad-4a8a-80e9-9f13fbfe7cc0.png?auto=format&fit=clip&q=50)

Under “SAML/WS-FED”, select “Create App”.

![A screenshot showing where to select Create App in the miniOrange dashboard.](https://images.workoscdn.com/images/036c42e8-fe89-4699-8149-878fa27cc3bb.png?auto=format&fit=clip&q=50)

Search for “custom” in the search box and select “Custom SAML App”.

![A screenshot showing where to select Custom SAML App in the miniOrange dashboard.](https://images.workoscdn.com/images/7b5b3d54-f81b-4c72-a883-8d02f72c742e.png?auto=format&fit=clip&q=50)

---

## (2) Initial SAML Application Setup

Under the “Basic Settings” tab of the SAML app, select “Import SP Metadata”.

![A screenshot highlighting the "Import SP Metadata" button in the miniOrange Dashboard.](https://images.workoscdn.com/images/e162dc6c-3b87-4811-935f-99c6625ac45a.png?auto=format&fit=clip&q=50)

Give the SAML app a descriptive name under “App Name”. Under “SP Metadata”, select “URL” and input the SP Metadata URL from your SSO Connection settings in the WorkOS Dashboard. Then, hit “Import”.

![A screenshot showing how to enter an App name and input a metadata URL in the miniOrange dashboard.](https://images.workoscdn.com/images/fe57d767-efc5-4e64-8a11-cd3b1d939eb5.png?auto=format&fit=clip&q=50)

Make sure that you have the “Sign Assertion” field toggled on.

![A screenshot showing the "Sign Assertion" toggle activated in the miniOrange dashboard.](https://images.workoscdn.com/images/3100fed7-3173-4679-8151-2f30da20a062.png?auto=format&fit=clip&q=50)

Select “Next”.

![A screenshot highlighting the "Next" button in the miniOrange dashboard.](https://images.workoscdn.com/images/91e21543-19e0-4c50-b9e9-dd5f954ef4b7.png?auto=format&fit=clip&q=50)

---

## (3) Configure SAML Application

Under the “Attribute Mapping” section of the SAML app, select “Add Attribute”.

![A screenshot showing where to select "Add Attribute" in the miniOrange dashboard.](https://images.workoscdn.com/images/d72f5337-e2ee-412e-b3b4-153e4e406526.png?auto=format&fit=clip&q=50)

Map the following four attributes as shown below, and the select “Save”.

- `id` → `Username`
- `email` → `E-Mail Address`
- `firstName` → `First Name`
- `lastName` → `Last Name`

![A screenshot showing how to input user attribute mapping in the miniOrange dashboard.](https://images.workoscdn.com/images/66a87e11-ce03-4426-b7b1-044a2c8e9f9a.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, follow the guidance below.

On your SAML app's Settings page, scroll down to "Attributes" and add a new attribute. Set the attribute's name to `groups` and map it to the "User Groups" field. Click "Save".

![A screenshot showing how to add a groups attribute in the miniOrange dashboard.](https://images.workoscdn.com/images/6ca4414d-fc41-455c-812f-353eb4e77459.png?auto=format&fit=clip&q=50)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (4) Upload Metadata URL

Back on the “Apps” tab of the miniOrange Dashboard, click “Select” next to the app you’ve created. From the dropdown, select “Metadata”.

![A screenshot highlighting where to select "Metadata" in the miniOrange dashboard.](https://images.workoscdn.com/images/39c6b33f-f3f3-4728-a70d-27672ae2e9f7.png?auto=format&fit=clip&q=50)

Under the “Information required to set miniOrange as IdP” section, click the icon next to “Metadata URL” to copy it to your clipboard.

![A screenshot showing where to copy the Metadata URL in the miniOrange dashboard.](https://images.workoscdn.com/images/42746ff9-c33a-4c14-85c0-273cb5a1939d.png?auto=format&fit=clip&q=50)

In the Connection settings in the WorkOS Dashboard, click “Edit Metadata Configuration”.

![A screenshot highlighting the "Edit Metadata Configuration" button in a Connection details view in the WorkOS Dashboard.](https://images.workoscdn.com/images/5ad0b7db-f33a-4a06-acf5-83809feaa2ad?auto=format&fit=clip&q=50)

Paste the Metadata URL from miniOrange into the “Metadata URL” field and select “Save Metadata Configuration”.

![A screenshot showing how to input the Metadata URL into the Connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/13ae3b21-964f-471b-972f-f5fc2b570ccd.png?auto=format&fit=clip&q=50)

Your Connection will then be linked and good to go!

### Microsoft OAuth

Learn how to set up OAuth with Microsoft

## Introduction

The Microsoft OAuth integration allows your users to authenticate using their Microsoft credentials through the "Sign in with Microsoft" flow.

The configuration process involves creating or configuring an application in Microsoft Azure and setting up OAuth permissions with the client credentials in the WorkOS Dashboard.

---

## Testing with default credentials in the staging environment

WorkOS provides a default Microsoft Client ID and Client Secret combination, which allows you to quickly enable and test Microsoft OAuth. Use the [WorkOS API to initiate SSO](/sso/1-add-sso-to-your-app/add-an-endpoint-to-initiate-sso), setting the `provider` parameter to `MicrosoftOAuth`, and WorkOS will automatically use the default credentials until you add your own Microsoft Client ID and Client Secret to the configuration in the WorkOS Dashboard.

> The default credentials are only intended for testing and therefore only available in the Staging environment. For your production environment, please follow the steps below to create and specify your own Microsoft Client ID and Client Secret.

Please note that when you are using WorkOS default credentials, Microsoft's authentication flow will display WorkOS' name, logo, and other information to users. Once you register your own application and use its Microsoft Client ID and Client Secret for the OAuth flow, you will have the opportunity to customize the app, including its name, logo, contact email, etc.

---

## What WorkOS provides

When setting up Microsoft OAuth, WorkOS provides one key piece of information that needs to be configured in your Microsoft Azure application:

- [Redirect URI](/glossary/redirect-uri): The endpoint where Microsoft will send authentication responses after successful login

The Redirect URI is available in the [WorkOS Dashboard](https://dashboard.workos.com/). In the left navigation menu, select **Authentication** tab and the **OAuth providers** sub-tab. Locate the **Microsoft** section.

![Open the Microsoft configuration dialog](https://images.workoscdn.com/images/c1518c6e-a765-4101-90eb-0795763aff92.png?auto=format&fit=clip&q=50)

Click **Manage**. The **Microsoft OAuth** configuration dialog will open. Locate the **Redirect URI**.

![Microsoft OAuth Redirect URI in the WorkOS Dashboard.](https://images.workoscdn.com/images/ba067eab-be24-404e-9d15-d1cc87720a57.png?auto=format&fit=clip&q=50)

The **Redirect URI** serves as the destination for authentication responses and must be configured in your Microsoft Azure application's authentication settings.

---

## What you'll need

You will need to obtain two pieces of information from a Microsoft Azure application:

- **Microsoft Client ID**: Application identifier from Microsoft Azure
- **Microsoft Client Secret**: Authentication secret for the application

The following sections will guide you through creating an application in your Microsoft Azure Portal and generating these credentials.

> IMPORTANT: When registering your app, select **Personal Microsoft accounts only** for **Supported Account Types**.

![The "Supported Account Types" setting in the Microsoft Azure Dashboard.](https://images.workoscdn.com/images/67aea66f-d0f3-45f1-a314-06b3ae570e24.png?auto=format&fit=clip&q=50)

---

## (1) Create or access Microsoft Azure application

Sign in to the [Microsoft Azure Portal](https://portal.azure.com/) and navigate to **Microsoft Entra ID** from the left hand navigation.

If you don't already have an application, click **App registrations** and then **New registration** to create one. When registering, you must select **Personal Microsoft accounts only** for **Supported Account Types**.

If you already have an application, select **App registrations** and then select your relevant application.

![Where to select an application in the Azure Portal.](https://images.workoscdn.com/images/334e0a97-80d5-4458-a3d7-6b4ec3f8f584.png?auto=format&fit=clip&q=50)

---

## (2) Configure authentication settings

Select the **Authentication** option for the application. In the **Redirect URIs** section, add the **Redirect URI** from the WorkOS Dashboard. When selecting a platform, choose **Web**.

![Where to enter the Redirect URI in the Azure App Settings.](https://images.workoscdn.com/images/b320ec4d-7dbb-4026-8bdb-7c6235dddb77.png?auto=format&fit=clip&q=50)

---

## (3) Configure token claims

Under **Token configuration**, select **Add optional claim**. Select **email**, **family_name** and **given_name**. If shown, select the **Turn on the Microsoft Graph email, profile permission** checkbox.

In order for the email claim to come through, the **Email** field for the user in Azure needs to be populated.

![Where to add claims in the Azure App Settings.](https://images.workoscdn.com/images/afe439ec-5d81-474f-9877-3657c3d50d1a.png?auto=format&fit=clip&q=50)

---

## (4) Generate client credentials

To get the Microsoft Client Secret, navigate to **Certificates & secrets** and click on **New client secret**. Give the client secret a description and select **Add**.

Microsoft's client secrets have an expiration date, with the highest value being 24 months. You will need to track these and rotate them before the expiration time.

![Where to create a client secret in the Entra ID App Settings.](https://images.workoscdn.com/images/1f7eca0b-700d-42f8-911a-238a3dee3df8.png?auto=format&fit=clip&q=50)

Copy the **value** of the new client secret as you'll need it for the WorkOS configuration.

![Where to copy the Entra ID Client Secret.](https://images.workoscdn.com/images/98510fb9-db6c-43c6-9a79-85284916b169.png?auto=format&fit=clip&q=50)

To obtain the Microsoft Client ID, navigate to the **Overview** tab of your application and copy the **Application (client) ID**.

![Where to copy the Entra ID Client ID.](https://images.workoscdn.com/images/6c79e0bc-9560-4a27-96f3-64569da1aa0e.png?auto=format&fit=clip&q=50)

---

## (5) Configure Microsoft credentials in WorkOS

Now that you have the **Microsoft Client ID** and **Microsoft Client Secret** from the previous steps, return to the [WorkOS Dashboard](https://dashboard.workos.com).

In the **Microsoft OAuth** configuration dialog, select **Your app's credentials**. Paste the credentials from Microsoft into their respective fields in the WorkOS Dashboard.

![Where to enter Microsoft OAuth client credentials into the WorkOS Dashboard.](https://images.workoscdn.com/images/2d7e1ea9-ea44-439c-bbaf-f4c19569b7aa.png?auto=format&fit=clip&q=50)

Click **Save** to complete the configuration.

After that, you're now able to authenticate users with Microsoft OAuth. You will use the `provider` query parameter in the Get Authorization URL API endpoint to support global Microsoft OAuth for any domain. The `provider` query parameter should be set to `MicrosoftOAuth`.

---

## Configure Additional OAuth Scopes (Optional)

WorkOS will request the OAuth scopes that are required for authentication by default. You can optionally configure your integration to request additional OAuth scopes as needed.

When the **Return Microsoft OAuth tokens** option is selected, the access token and refresh token from Microsoft will be included in the response from the [Authenticate with code API](/reference/authkit/authentication/code).

![A screenshot showing Microsoft OAuth scopes configuration in the WorkOS Dashboard](https://images.workoscdn.com/images/af28d982-0bc2-4240-be1a-9f97068d036f.png?auto=format&fit=clip&q=50)

Any scopes configured here will be included on every Microsoft OAuth request. To specify additional scopes dynamically, use the `provider_scopes` query parameter on the [Get Authorization URL API endpoint](/reference/authkit/authentication/get-authorization-url).

Any additional scopes that you plan to request should also be configured as API permissions on your Microsoft Azure application. For more information, see Microsoft's OAuth scopes [documentation](https://learn.microsoft.com/en-us/entra/identity-platform/scopes-oidc).

![A screenshot showing Microsoft OAuth scopes configuration in Azure App Registration](https://images.workoscdn.com/images/537b2f36-cfb0-4c35-83a6-7fee760418d5.png?auto=format&fit=clip&q=50)

> IMPORTANT: Your users may see errors during sign-in if the scopes included on an authorization request are not included in the API permissions configured on your Microsoft Azure application. Changes to scopes should be tested in a staging environment before applying them to production.

---

## Frequently asked questions

### How is the WorkOS Microsoft OAuth integration different from implementing regular Microsoft OAuth flow?

It's the same Microsoft OAuth flow as you could build yourself, but it's encapsulated within WorkOS SSO. This means you don't need to build it yourself. In addition to Microsoft OAuth, you can use WorkOS SSO to support other identity providers, all with a single integration.

### What is the provider query parameter and how is it used in the Microsoft OAuth integration?

You can use the `provider` query parameter in the [Get Authorization URL API endpoint](/reference/sso/get-authorization-url) to support global Microsoft OAuth for any domain. The `provider` query parameter should be set to `MicrosoftOAuth`. This is necessary because Microsoft OAuth does not take a user's domain into account when logging in with a "Sign in with Microsoft" button.

### Why do I need to select "Personal Microsoft accounts only" for account types?

This setting is required for the WorkOS integration to function properly. It ensures that the OAuth flow works with personal Microsoft accounts rather than organizational accounts, which have different authentication requirements.

### How long do Microsoft client secrets last?

Microsoft's client secrets have an expiration date, with the maximum value being 24 months. You will need to track these and rotate them before the expiration time to maintain continuous authentication functionality.

### Microsoft AD FS SAML

Configure a connection to Microsoft Active Directory Federation Services.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create an AD FS SAML Connection, you’ll need two pieces of information: an [SP Metadata](/glossary/sp-metadata) file and an IdP Metadata URL.

---

## (1) Configure a Relying Party Trust

Open the AD FS Management console.

![A screenshot showing the AD FS Management Console.](https://images.workoscdn.com/images/39b62cf2-a830-4cfc-b057-1717cec6e870.png?auto=format&fit=clip&q=50&w=1200)

Click “Relying Party Trusts” on the left sidebar. Click “Add Relying Party Trust...” on the right sidebar to open the “AD FS Relying Party Trust Wizard”.

![A screenshot showing where to add the AD FS Relying Party Trust.](https://images.workoscdn.com/images/b99f15c0-ac9d-4cd4-bd78-38f00cd3cfee.png?auto=format&fit=clip&q=50&w=1200)

Select “Claims aware” and then “Start”.

![A screenshot showing where to select claims in the AD FS Relying Party Trust Wizard.](https://images.workoscdn.com/images/1aaf2490-580f-4930-91b4-258326b751c3.png?auto=format&fit=clip&q=50&w=1200)

Download the provided Metadata file from WorkOS by heading to the SP Metadata link in the Dashboard. Select “Import data about the relying party from a file” then select the SP Metadata file you downloaded, and click “Next”.

![A screenshot showing where to import the WorkOS Metadata File.](https://images.workoscdn.com/images/9cf7ee4f-09d8-4dcc-ab92-29732ca3c691.png?auto=format&fit=clip&q=50&w=1200)

Select “Permit everyone” and then “Next”.

![A screenshot showing where to configure access control permissions in the AD FS Relying Party Trust Wizard.](https://images.workoscdn.com/images/94d90815-ef73-4cf5-9a8e-9b85108163d3.png?auto=format&fit=clip&q=50&w=1200)

---

## (2) Choose Access Policy

Click the “Endpoints” tab and confirm that the “SAML Assertion Consumer Endpoints” matches the SAML Assertion Consumer Endpoint `https://auth.workos.com/sso/saml/acs/:id` and click “Next”.

![A screenshot showing where to check the ACS URL in AD FS.](https://images.workoscdn.com/images/c0c58966-3656-4079-b9c4-1ed01e2d2412.png?auto=format&fit=clip&q=50&w=1200)

Select “Configure claims issuance policy for this application” and “Close”.

![A screenshot showing where to configure the AD FS claims.](https://images.workoscdn.com/images/a786ee79-750e-464f-ad4c-bdf685a7aec0.png?auto=format&fit=clip&q=50&w=1200)

---

## (3) Configure Claims Issuance Policy

Click “Add Rule” in the “Edit Claims Issuance Policy” window.

![A screenshot showing where to add a rule in the Edit Claims Issuance Policy window.](https://images.workoscdn.com/images/b0ce3aa1-5a5c-498a-8b40-f9297ed03a29.png?auto=format&fit=clip&q=50&w=1200)

Select “Send LDAP Attributes as Claims” and then “Next”.

![A screenshot showing where to select a rule template in the Transform Claim Rule Wizard.](https://images.workoscdn.com/images/753196aa-ebd0-4456-a961-4faacbfddbd2.png?auto=format&fit=clip&q=50)

Submit “Attributes” as “Claim rule name”, then select “Active Directory” as “Attribute Store”, and configure the following attribute mappings. Then click “OK”.

- `E-Mail-Addresses` → `E-Mail Address`
- `Given-Name` → `Given Name`
- `Surname` → `Surname`
- `User-Principal-Name` → `UPN`

![A screenshot showing where to map attributes in the Transform Claim Rule Wizard.](https://images.workoscdn.com/images/e835b332-47de-43e5-a34d-0031395dee9c.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, follow the guidance below.

Select "Group" as the "Outgoing Claim Type" and map an LDAP Attribute to send groups. For example, to send all groups, map the "Token-Groups - Unqualified Names" attribute.

![A screenshot showing how to map the Group claim.](https://images.workoscdn.com/images/72de6a78-46cc-4499-8ef6-f7c05fa0a087.png?auto=format&fit=clip&q=50)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (4) Upload Metadata URL

Next you will want to obtain the Metadata URL from your AD FS server. AD FS publishes its metadata to a standard URL by default: `https://SERVER/federationmetadata/2007-06/federationmetadata.xml` where “SERVER” is your federation service FQDN. You can also find your ADFS Federation Metadata URL through the AD FS Management in “AD FS → Service → Endpoints” and navigate to the Metadata section.

![A screenshot showing where to find the AD FS Metadata URL.](https://images.workoscdn.com/images/f9c91a23-847c-4032-9bbb-888d071db27d.png?auto=format&fit=clip&q=50)

Once you have obtained the Metadata URL you will then navigate to the connection settings in WorkOS, click “Edit Metadata configuration”, and upload the Metadata URL.

![A screenshot showing where to upload the AD FS Metadata URL in the WorkOS Dashboard.](https://images.workoscdn.com/images/0ab739ca-8edd-436d-b6a6-4efe3cf598fc.png?auto=format&fit=clip&q=50)

Once uploaded the connection will be verified and linked!

### Login.gov OpenID Connect

Learn how to configure a connection to Login.gov via OIDC.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

> Note: [Login.gov](http://login.gov/) is used for government agencies. You will need to go through Login.gov to obtain a test account and get your application cleared for production. Please reference [Login.gov’s developer documentation](https://developers.login.gov/testing/) for more information.

To create a Login.gov OpenID Connect (OIDC) Connection, you’ll need four pieces of information: a [Redirect URI](/glossary/redirect-uri), a Public Certificate, a [Client ID](/glossary/client-id), and a Discovery Endpoint.

Start by logging in to your WorkOS dashboard and browse to the “Organizations” tab on the left-hand navigation bar.

Select the organization you’d like to configure a Login.gov OIDC Connection for, and select “Manually Configure Connection” under “Identity Provider”.

![A screenshot showing where to find "Manually Configure Connection" in the WorkOS Dashboard.](https://images.workoscdn.com/images/32e5ff2f-4756-48ab-8c01-9ea6c04a0162.png?auto=format&fit=clip&q=50)

Select “Login.gov OpenID Connect” from the Identity Provider dropdown, enter a descriptive name for the connection, and then select the “Create Connection” button.

![A screenshot showing "Create Connection" details in the WorkOS Dashboard.](https://images.workoscdn.com/images/59b7ae81-487d-4e3b-a1d7-d6e293452d1b.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

WorkOS provides the Redirect URI and the Public Certificate. They are readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/get-started).

![A screenshot showing where to find the Redirect URI and Public Certificate in the WorkOS Dashboard.](https://images.workoscdn.com/images/cabe8cea-016e-4070-abe9-43b19b86699d.png?auto=format&fit=clip&q=50)

The Redirect URI is the location Login.gov redirects its authentication and token responses to, and the Public Certificate is used by Login.gov to verify the signed request from WorkOS.

Specifically, the Redirect URI will need to be set as one of the “Redirect URIs” and the Public Certificate will need to be set as one of the “Public Certificates” in the Login.gov application settings:

![A screenshot showing where to upload the Public Certificate and Redirect URI within the Login.gov dashboard.](https://images.workoscdn.com/images/2c615ec0-e266-492f-a32b-07d55c04b0ad.png)

## What you’ll need

In order to integrate you’ll need the [Client ID](/glossary/client-id) and the Discovery Endpoint.

Normally, this information will come from the organization's IT Management team when they set up your application’s Login.gov OpenID Connect configuration in their Identity Provider admin dashboard. But, should that not be the case during your setup, here’s how to obtain them.

---

## (1) Access the Login.gov Developer Sandbox

Login to your [Login.gov sandbox dashboard](https://dashboard.int.identitysandbox.gov), and select “Apps” from the top menu.

![A screenshot showing the Login.gov sandbox dashboard and how to select the App menu option.](https://images.workoscdn.com/images/21a33031-818d-4b44-8646-648a45fc4e5a.png)

> Note: Login.gov is used exclusively by government agencies. If you don’t have dashboard access for your Sandbox account, please reach out to the government agency you’re working with to get access to their sandbox dashboard. Please reference [Login.gov’s developer documentation](https://developers.login.gov/testing/) for more information.

---

## (2) Select or create your application

If your application is already created, select it from the list of applications and move to Step 4. If you haven’t created an application, select “Create a new test app.”

![A screenshot showing where to find the “Create a new test app” button in Login.gov "My app" listing.](https://images.workoscdn.com/images/96e14854-9acc-4ddd-8339-4312b80f7883.png)

---

## (3) Application Setup

On the New test app page, select “Yes” under the Production configuration setting. Then, add an App name, Friendly name, and Description for the app. Next, assign an agency team to this client.

![A screenshot showing where to select “Yes” under the Production configuration setting as well as the add an App name, Friendly name, Description, and Team for the Login.gov app during setup.](https://images.workoscdn.com/images/ac9a9962-4058-4876-8fd8-4542f2b93711.png)

Select "OpenID Connect Private Key JWT" as the Authentication protocol. Select the appropriate Level of Service, Default Authentication Assurance Level (AAL), and Attribute bundle for your application.

![A screenshot showing where to setup the Application protocol, Level of Service, Default Authentication Assurance Level, and Attributes Bundle during Login.gov application setup.](https://images.workoscdn.com/images/42b994de-61ac-4856-b954-12503cc3e45f.png)

Next, you’ll need to define an Issuer - something like `urn:gov:gsa:openidconnect.profiles:sp:sso:agency_name:app_name` - replacing your agency and app name. Then, upload a logo and the public certificate file you downloaded from the WorkOS dashboard.

![A screenshot showing where to set the Issuer and upload a Logo and Public Certificate during Login.gov application setup.](https://images.workoscdn.com/images/f20e0870-1ec9-41d4-be5c-76103d177400.png)

Finally, you’ll need to add the Redirect URIs. The first one you’ll need to add is the Redirect URI you copied from the WorkOS Dashboard. You’ll also need to add the [Redirect URI for your application](/sso/redirect-uris). There is a Content Security Policy (CSP) check from Login.gov, so all URIs that could potentially be redirected to the authentication flow should be listed here.

![A screenshot showing where to upload the Redirect URI during Login.gov application setup.](https://images.workoscdn.com/images/2fd99552-43e3-4a74-b211-97619af4f7de.png)

Scroll down to the bottom of the page and select “Create test app” to finish the setup.

---

## (4) Provide the Client ID and Discovery Endpoint

Enter the Issuer you created in the previous step as the Client ID in the WorkOS Dashboard. Additionally, add the discovery endpoint, which for production accounts in Login.gov is: `https://secure.login.gov/.well-known/openid-configuration`.

Click “Update connection".

![A screenshot showing where to add the Client ID and Discovery Endpoint and Update Connection within the WorkOS Dashboard.](https://images.workoscdn.com/images/986718f3-0007-4894-9bd2-29892ff955d5.png?auto=format&fit=clip&q=50)

---

## (5) Request Production Deployment

Please follow the [Login.gov docs to request a production deployment](https://developers.login.gov/production/) and finish your Login.gov application.

### LinkedIn OAuth

Learn how to set up OAuth with LinkedIn

## Introduction

The LinkedIn OAuth integration allows your users to authenticate using their LinkedIn credentials.

The configuration process involves creating an OAuth application in LinkedIn and configuring the client credentials in your WorkOS Dashboard.

---

## What WorkOS provides

When setting up LinkedIn OAuth, WorkOS provides one key piece of information that needs to be configured in your LinkedIn OAuth application:

- [Redirect URI](/glossary/redirect-uri): The endpoint where LinkedIn will send authentication responses after successful login

The Redirect URI is available in the [WorkOS Dashboard](https://dashboard.workos.com/). In the left navigation menu, select the **Authentication** tab and the **OAuth providers** sub-tab. Locate the **LinkedIn** section.

![The LinkedIn OAuth section in the WorkOS Dashboard.](https://images.workoscdn.com/images/d9cc3fce-75fc-410e-91d4-5706c88c609f.png?auto=format&fit=clip&q=50)

Click **Enable**. The **LinkedIn OAuth** configuration dialog will open. Locate the **Redirect URI**.

![The LinkedIn OAuth configuration modal in the WorkOS Dashboard.](https://images.workoscdn.com/images/3b7a3d3e-391d-401f-92a4-74bfd57b0dc5.png?auto=format&fit=clip&q=50)

The **Redirect URI** serves as the destination for authentication responses and must be configured in your LinkedIn OAuth application as an authorized redirect URL.

---

## What you'll need

You will need to obtain two pieces of information from a LinkedIn Developer application:

- **LinkedIn Client ID**: Application identifier from LinkedIn
- **LinkedIn Client Secret**: Authentication secret for the application (called Primary Client Secret in LinkedIn)

The following sections will guide you through creating an OAuth application in your LinkedIn Developer account and generating these credentials.

---

## (1) Create the LinkedIn OAuth application

Log in to your LinkedIn account and navigate to the [LinkedIn Developer Portal](https://developer.linkedin.com). Click **Create app**.

![The LinkedIn page to register a new OAuth application.](https://images.workoscdn.com/images/75a8bb4c-8df2-4c9d-b205-5e9e07d31501.png?auto=format&fit=clip&q=80)

Fill out the form with the required details about your application, including the application name, LinkedIn page, and app logo.

![The LinkedIn form to create a new OAuth application.](https://images.workoscdn.com/images/7da6ffdf-adda-4218-ac93-c2b211bfb12e.png?auto=format&fit=clip&q=80)

Click **Create app** to create the application.

---

## (2) Configure OAuth settings and obtain client credentials

On the application page, click the **Auth** tab. Copy the **Client ID** and **Primary Client Secret** as you'll need them for the WorkOS configuration.

![OAuth client credentials in the LinkedIn developer settings.](https://images.workoscdn.com/images/da63c1b4-44d3-43ca-a962-a1f7e641dc0e.png?auto=format&fit=clip&q=80)

Click the pencil button next to **OAuth 2.0 settings** > **Authorized redirect URLs for your app**. Click **Add redirect URL** and paste the **Redirect URI** from the WorkOS Dashboard. Click **Update**.

![OAuth redirect URL in the LinkedIn developer settings.](https://images.workoscdn.com/images/9e838b55-e2c7-4b30-bf68-8531e7bf376a.png?auto=format&fit=clip&q=80)

---

## (3) Add OIDC support

Click the **Products** tab and add the **Sign In with LinkedIn using OpenID Connect** product to enable OIDC authentication capabilities.

![The LinkedIn OIDC configuration dashboard.](https://images.workoscdn.com/images/f629579e-0ff1-42da-b1fc-40f577ae6723.png?auto=format&fit=clip&q=80)

---

## (4) Configure LinkedIn credentials in WorkOS

Now that you have the **LinkedIn Client ID** and **LinkedIn Client Secret** (Primary Client Secret) from the previous steps, return to the [WorkOS Dashboard](https://dashboard.workos.com).

In the **LinkedIn OAuth** configuration dialog, enable the integration. Paste the credentials from LinkedIn into their respective fields in the WorkOS Dashboard.

![The LinkedIn OAuth configuration modal in the WorkOS Dashboard.](https://images.workoscdn.com/images/053443da-9ab9-45a3-b345-4bc1cf0c6fd6.png?auto=format&fit=clip&q=50)

Click **Save** to complete the configuration.

You are now ready to start authenticating with LinkedIn OAuth. You will use the `provider` query parameter in the Get Authorization URL API endpoint to support global LinkedIn OAuth for any domain. The `provider` query parameter should be set to `LinkedInOAuth`.

---

## Frequently asked questions

### How is the WorkOS LinkedIn OAuth integration different from implementing regular LinkedIn OAuth flow?

It's the same LinkedIn OAuth flow as you could build yourself, but it's encapsulated within WorkOS SSO. This means you don't need to build it yourself. In addition to LinkedIn OAuth, you can use WorkOS SSO to support other identity providers, all with a single integration.

### What is the provider query parameter and how is it used in the LinkedIn OAuth integration?

You can use the `provider` query parameter in the [Get Authorization URL API endpoint](/reference/sso/get-authorization-url) to support global LinkedIn OAuth for any domain. The `provider` query parameter should be set to `LinkedInOAuth`.

### Do I need a LinkedIn Company Page to create an OAuth application?

Yes, LinkedIn requires that OAuth applications be associated with a LinkedIn Company Page. This is a requirement from LinkedIn to ensure applications are associated with legitimate businesses or organizations.

### What is the difference between Client ID and Primary Client Secret in LinkedIn?

The **Client ID** is the public identifier for your LinkedIn application, while the **Primary Client Secret** is the private authentication key that must be kept secure. The Primary Client Secret is what WorkOS refers to as the LinkedIn Client Secret.

### Why do I need to add the "Sign In with LinkedIn using OpenID Connect" product?

This product enables OIDC (OpenID Connect) authentication capabilities for your LinkedIn application, which is required for the WorkOS integration to function properly. Without this product, the OAuth flow will not work correctly.

### LastPass

Learn how to configure a connection to LastPass via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a LastPass SAML Connection, you’ll need an IdP Metadata XML file.

Start by logging in to your WorkOS dashboard and browse to the “Organizations” tab on the left hand navigation bar.

Select the organization you’d like to configure a LastPass SAML Connection for, and select “Manually Configure Connection” under “Identity Provider”.

![A screenshot showing where to find "Manually Configure Connection" in the WorkOS Dashboard.](https://images.workoscdn.com/images/ff2ce096-00e1-4d34-8523-23a01ebf4642.png?auto=format&fit=clip&q=50)

Select “LastPass SAML” from the Identity Provider dropdown, enter a descriptive name for the connection, and then select the “Create Connection” button.

![A screenshot showing "Create Connection" details in the WorkOS Dashboard.](https://images.workoscdn.com/images/5866a365-5f51-4f58-9124-a4c0653831a5.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

WorkOS provides the [ACS URL](/glossary/acs-url), [SP Entity ID](/glossary/sp-entity-id), and [SP Metadata URL](/glossary/sp-metadata). They’re readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot showing where to find the ACS URL, SP Metadata, and SP Entity ID in the WorkOS Dashboard.](https://images.workoscdn.com/images/93089510-e362-47c9-9844-4eefd70e18ca.png?auto=format&fit=clip&q=50)

---

## What you’ll need

Next, provide the [IdP Metadata](/glossary/idp-metadata) file. Normally, this information will come from your enterprise customer’s IT Management team when they set up your application’s SAML 2.0 configuration in their LastPass admin console. But, should that not be the case during your setup, the next steps will show you how to obtain it.

---

## (1) Select or create your application

Log in to [LastPass](https://admin.lastpass.com/applications/saml), go to the admin console and select “Applications” on the top navigation. Then select “SSO apps” from the left side navigation. If your application is already created, select it from the list of applications and move to Step 2. Otherwise, select “Add app”.

![A screenshot showing "Add app" in the "SSO apps" section of the Applications tab in the LastPass admin dashboard.](https://images.workoscdn.com/images/e6cc5fbc-e802-4cd4-b3d6-786c31ee7db2.png?auto=format&fit=clip&q=50)

In the modal that pops up, click on “Add an unlisted app”.

![A screenshot showing the selection of "Add an Unlisted App" for the creation of a new SSO app.](https://images.workoscdn.com/images/fad2dc44-73a1-4b98-b8bb-ee02e7293dfd.png?auto=format&fit=clip&q=50)

Give your SAML App a descriptive name and select “Continue”.

![A screenshot showing how to add the name for a new SSO app.](https://images.workoscdn.com/images/839575b4-8b1c-45e5-ab10-8fcc509fc1be.png?auto=format&fit=clip&q=50)

---

## (2) Initial SAML Application Setup

Under the “Set up LastPass” section of the “Configure app” modal, input the ACS URL from the WorkOS Dashboard Connection details under “ACS”. Then click on “Advanced Settings”.

![A screenshot showing where to add the ACS URL during the configuration app step in LastPass SAML Settings.](https://images.workoscdn.com/images/01e69cb0-8c93-474f-ad15-6cde111ac699.png?auto=format&fit=clip&q=50)

Under “Entity ID”, input the SP Entity ID from the WorkOS Dashboard Connection details. Next, under “SAML signature method”, select “SHA256”.

![A screenshot showing where to add the Entity ID during the configuration app step in LastPass SAML Settings.](https://images.workoscdn.com/images/4b80975b-c0bb-4efd-80dd-3a3c52836ec5.png?auto=format&fit=clip&q=50)

Under “Signing and encryption”, ensure that you have at least selected “Sign assertion”. Then, click on “Add SAML attribute”.

![A screenshot showing to select "Sign assertion" checkbox option for "Signing and encryption" in LastPass SAML Settings.](https://images.workoscdn.com/images/0e2a022f-444b-468b-91ad-cb2078142425.png?auto=format&fit=clip&q=50)

---

## (3) Configure SAML Application

Map the following four attributes as shown below, and select “Save & assign users”.

- First Name → `firstName`
- Last Name → `lastName`
- Email → `email`
- User ID → `id`

![A screenshot showing hot to add Attribute Mapping for a LastPass SAML app.](https://images.workoscdn.com/images/3e75c892-a7cc-4167-9e45-c046232c1231.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, add a new SAML attribute for the "Groups" field and input `groups` as the attribute name, as shown below. Then, select "Save & assign users".

![A screenshot showing how to add a groups attribute to a LastPass SAML app.](https://images.workoscdn.com/images/611cd4d7-715b-423c-b110-323f00d7ad8c.png?auto=format&fit=clip&q=50)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (4) Add Users and Groups to SAML Application

On the “Users, groups & roles” page, click on “Assign users, groups & roles”.

![A screenshot showing to select "Assign users, groups & roles" for your LastPass SAML app.](https://images.workoscdn.com/images/cec59ee3-85f1-45cd-8ed5-03dfef194de9.png?auto=format&fit=clip&q=50)

Search and select any users or groups that you would like to provision to this SAML app. Then, click “Assign”.

![A screenshot showing to select Users and Groups in LastPass.](https://images.workoscdn.com/images/fc3fd859-1092-45a8-922f-38b4619863d8.png?auto=format&fit=clip&q=50)

Click on “Save & continue”.

![A screenshot showing where to save and move to next steps in LastPass.](https://images.workoscdn.com/images/4b775f48-9045-4122-8c9c-4770370edd4b.png?auto=format&fit=clip&q=50)

---

## (5) Upload Metadata file

Back on the “SSO apps” tab of the LastPass admin console, select the SAML app that you just created.

!A screenshot showing where how to select SAML App in LastPass.](https://images.workoscdn.com/images/99a9a771-02bc-4817-b576-414bafa2d6f2.png?auto=format&fit=clip&q=50)

On the “Configure app” modal, click on “Expand” to the right of “Set up app”.

![A screenshot showing how to expand Set Up App in LastPass.](https://images.workoscdn.com/images/e717af8d-f5aa-4629-ae38-d5d0376d57dd.png?auto=format&fit=clip&q=50)

At the bottom of the “Set up app” section, click on “Download metadata (XML)”. Save the downloaded XML metadata somewhere accessible.

![A screenshot showing where to download Metadata File in LastPass.](https://images.workoscdn.com/images/bbd5f4bc-8386-4650-9559-f072b265d71b.png?auto=format&fit=clip&q=50)

In the Connection settings in the WorkOS Dashboard, click “Edit Metadata Configuration”.

![A screenshot showing where to edit Metadata Configuration in WorkOS Dashboard.](https://images.workoscdn.com/images/c485258c-6762-4ea7-9999-a2a43767de23.png?auto=format&fit=clip&q=50)

Upload the XML metadata file from LastPass into the “Metadata File” field and select “Save Metadata Configuration”.

![A screenshot showing a successful upload of the Metadata File in WorkOS Dashboard.](https://images.workoscdn.com/images/dd796b97-442e-4b74-a6ae-c5f2642b717a.png?auto=format&fit=clip&q=50)

Your Connection will then be linked and good to go!

### Keycloak

Learn how to configure a connection to Keycloak via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). And often, the information required to create a Connection will differ by Identity Provider.

To create an Keycloak SAML Connection, you’ll need three pieces of information: an [ACS URL](/glossary/acs-url), an Identity Provider Issuer (also known as an Entity ID), and a Metadata URL.

---

## What WorkOS provides

WorkOS provides the ACS URL and [IdP URI (Entity ID)](/glossary/idp-uri-entity-id). It’s readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot highlighting the "Service Provider Details" generated by WorkOS in the WorkOS Dashboard.](https://images.workoscdn.com/images/1ee74820-5075-4f2b-a1da-25f2c86204d4.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. In Keycloak’s case, it needs to be set by the organization when configuring your application in their Keycloak instance.

Specifically, the ACS URL will need to be set as the “Valid Redirect URI” and "Master SAML Processing URL" in the SAML client setup in Keycloak.

The Entity ID is a URI used to identify the issuer of a SAML request, response, or assertion. In this case, the entity ID is used to communicate that WorkOS will be the party performing SAML requests to the organization's Keycloak instance.

Specifically, the Entity ID will need to be set as the “Client ID” when creating a SAML client in Keycloak.

---

## What you’ll need

In order to integrate you’ll need the Keycloak Metadata URL. Normally, the this will come from the organization's IT Management team when they set up your application’s SAML client in their Keycloak instance. But, should that not be the case during your setup, here’s how to obtain it.

---

## (1) Log in

Log in to your Keycloak Admin Console, and navigate to the Realm you want to set up the SAML client in. Select “Clients” from the side menu. If your client is already created, select it from the list of and move to Step 4. If you haven’t created a SAML client in Keycloak, select “Create client”.

![A screenshot highlighting the "Create client" button in the Keycloak dashboard.](https://images.workoscdn.com/images/ab144a33-174d-4699-83ad-fa5e59b9b31d.png?auto=format&fit=clip&q=50)

---

## (2) Initial SAML Application Setup

On the Create Client setup step, select `SAML` as the "Client type", input the IdP URI (Entity ID) from your WorkOS Dashboard as the “Client ID”, and set a name for your Client. Click "Save".

![A screenshot highlighting the input fields "Client type", "Client ID" and "Name" in the Keycloak dashboard.](https://images.workoscdn.com/images/9365694a-b125-47e0-8d2e-1e49425e157b.png?auto=format&fit=clip&q=50)

---

## (3) Configure SAML Application

On the Settings page, scroll down and input the ACS URL from your WorkOS Dashboard in the “Valid Redirect URIs” and "Master SAML Processing URL" boxes.

![A screenshot highlighting the fields "Valid redirect URIs" and "Master SAML Processing URL in the Keycloak dashboard.](https://images.workoscdn.com/images/a1dea2f2-ea25-44c9-b88e-39b689a37de2.png?auto=format&fit=clip&q=50)

Scroll down further on the Settings page to "Signature and Encryption", and make sure that "Sign assertions" is toggled `On`. Click “Save”.

![A screenshot highlighting the "Sign documents" and "Sign assertions" toggles switched on in the Keycloak dashboard.](https://images.workoscdn.com/images/dfd9fc38-79b8-4c7d-8ca7-17d1925e8fa2.png?auto=format&fit=clip&q=50)

---

## (4) Configure User Attributes and Claims

Click the “Client scopes” top menu option and click into your Client.

![A screenshot highlighting the "Client scopes" tab and "Assigned client scope" field in the Keycloak dashboard.](https://images.workoscdn.com/images/cc6c1ce7-229f-4d1e-90b2-ecf060649018.png?auto=format&fit=clip&q=50)

Click "Configure a new mapper".

![A screenshot highlighting the "Configure a new mapper" button in the Keycloak dashboard.](https://images.workoscdn.com/images/3ed96fbb-d089-49ed-979b-2b360a498db0.png?auto=format&fit=clip&q=50&w=2048)

Then select "User Property".

![A screenshot highlighting the "User Property" field in the Keycloak dashboard.](https://images.workoscdn.com/images/6f82859d-a433-4e3c-bde4-10b4700e5ba0.png?auto=format&fit=clip&q=50&w=2048)

You’ll need to create a “User Property” mapper for the following four attributes:

- `id`
- `email`
- `firstName`
- `lastName`

This is an example of how to fill out the fields for `id`:

![A screenshot showing the proper mapping for the "id" property in the Keycloak dashboard.](https://images.workoscdn.com/images/1d966f7c-358b-46a6-b8d5-cbcb6f80c192.png?auto=format&fit=clip&q=50&w=2048)

Also do this for the `email`, `firstName`, and `lastName` attributes:

![A screenshot showing the proper mapping for the "email" property in the Keycloak dashboard.](https://images.workoscdn.com/images/7f753d8c-a7f3-4250-a772-0fb31bddfb03.png?auto=format&fit=clip&q=50&w=2048)

![A screenshot showing the proper mapping for the first name property in the Keycloak dashboard.](https://images.workoscdn.com/images/d037d45f-9d80-4594-b0d2-4ec65dd76d96.png?auto=format&fit=clip&q=50&w=2048)

![A screenshot showing the proper mapping for the last name property in the Keycloak dashboard.](https://images.workoscdn.com/images/0df763a9-7ca9-4bfb-870b-472bc3ef4b8b.png?auto=format&fit=clip&q=50&w=2048)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, follow the guidance below.

On the "Dedicated scopes" page, select "Add mapper" and then "By configuration".

![A screenshot showing how to add a new groups attribute mapper.](https://images.workoscdn.com/images/6475d3b7-33b2-47f5-a55e-efd13600b1e0.png?auto=format&fit=clip&q=50)

You can choose either "Group list" or "Role list", whichever option best fits your use case. The example below uses "Group list". For more information on sending group information, refer to the [Keycloak documentation](https://www.keycloak.org/docs/latest/server_admin/#assigning-permissions-using-roles-and-groups).

![A screenshot showing what type of mapper to choose for a groups attribute.](https://images.workoscdn.com/images/42a1cfbd-2499-46a7-bc3c-39b284f25e74.png?auto=format&fit=clip&q=50)

Set the Name and the Group attribute name to "groups", and make sure the Single Group Attribute toggle is On. Select "Save".

![A screenshot showing how to configure the groups attribute mapper.](https://images.workoscdn.com/images/d95229b8-a5e1-4543-8047-077a38570b01.png?auto=format&fit=clip&q=50)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

## (5) Obtain Identity Provider Details

Select “Realm Settings” in the left sidebar navigation menu, and copy the “SAML 2.0 Identity Provider Metadata” link on the General page.

![A screenshot highlighting the "SAML 2.0 Identity Provider Metadata" button in the Keycloak dashboard.](https://images.workoscdn.com/images/166ae678-b776-470e-bf66-62bf202207e1.png?auto=format&fit=clip&q=50)

Next, within your connection settings, edit the Metadata Configuration and provide the Metadata URL you obtained from Keycloak. Your Connection will then be verified and good to go!

![A screenshot highlight the "URL Metadata Configuration" input in the WorkOS Dashboard.](https://images.workoscdn.com/images/2579b65a-3d39-4344-8df4-6cdf80506c34.png?auto=format&fit=clip&q=50)

### JumpCloud SCIM

Learn about syncing your user list with JumpCloud SCIM.

## Introduction

This guide outlines how to synchronize your application’s JumpCloud directories using SCIM.

To synchronize an organization’s users and groups provisioned for your application, you’ll need to provide the organization with two pieces of information:

- An [Endpoint](/glossary/endpoint) that JumpCloud will make requests to.
- A [Bearer Token](/glossary/bearer-token) for JumpCloud to authenticate its endpoint requests.

Both of these are available in your Endpoint’s Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

> Steps 2, 3, and 4 below will need to be carried out by the organization when configuring your application in their JumpCloud instance.

---

## (1) Set up your Directory Sync endpoint

Login to your WorkOS Dashboard and select “Organizations” from the left hand navigation bar.

Select the organization you’ll be configuring a new Directory Sync for.

Under “Actions” click “Add Directory”.

![A screenshot highlighting the "Add Directory" option within an Organization in the WorkOS Dashboard.](https://images.workoscdn.com/images/5411a8c2-cc56-4593-bc7c-c21c84443dfc.png?auto=format&fit=clip&q=50)

Select “JumpCloud” from the dropdown, and enter the organization name.

Then, click “Create Directory.”

![A screenshot highlighting the "Create Directory" modal for creating a JumpCloud directory in the WorkOS Dashboard.](https://images.workoscdn.com/images/6aaf218c-8d81-4ed6-aa8f-682dd3235dc2.png?auto=format&fit=clip&q=50)

Your JumpCloud directory sync has now been created successfully with an Endpoint and Bearer Token.

![A screenshot highlighting the "Directory Details" for a JumpCloud directory in the WorkOS Dashboard.](https://images.workoscdn.com/images/eaad1aef-522e-4f01-a298-3a6b093aa8a1.png?auto=format&fit=clip&q=50)

> We have support for custom labeled URLs for Directory Sync endpoints. [Contact us](mailto:support@workos.com) for more info!

---

## (2) Select or create your JumpCloud application

Log in to the JumpCloud admin dashboard, select “SSO” on the left and select your Application.

![Select or Create JumpCloud App](https://images.workoscdn.com/images/26901dbc-8236-46b4-a46f-8c828152fe60.png?auto=format&fit=clip&q=50)

If you haven’t created an application, you’ll need to first create a custom SAML application in JumpCloud. JumpCloud only supports configuring SCIM provisioning in an existing SAML application. You can use our JumpCloud SAML documentation to configure your SAML application before moving on to SCIM provisioning.

---

## (3) Configure your integration

Select “Identity Management” from the top navigation menu.

![A screenshot highlighting the "SSO" tab and app selection in the JumpCloud admin dashboard.](https://images.workoscdn.com/images/58194668-19eb-4b3b-b07d-a5023d05e766.png?auto=format&fit=clip&q=50)

Scroll down to the “Configuration settings” section. Make sure SCIM 2.0 is selected as the SCIM version.

Copy and paste the Endpoint from your [WorkOS Dashboard](https://dashboard.workos.com/) in the “Base URL” field.

Then, copy and paste the Bearer Token from your [WorkOS Dashboard](https://dashboard.workos.com/) into the “Token Key” field.

Next, test the connection to confirm the configuration settings.

![A screenshot highlighting the "Base URL" and "Token Key" input fields in the JumpCloud admin dashboard.](https://images.workoscdn.com/images/6096c0db-b7f6-45ea-aa44-b1f53f167d12.png?auto=format&fit=clip&q=50)

After you receive a success message for the configuration, make sure the Group Management toggle is “On”, and then activate the settings.

![A screenshot highlight the "Group Management" field toggled on in the JumpCloud admin dashboard.](https://images.workoscdn.com/images/aa71e757-ec72-4f72-9551-cd43e72cf44b.png?auto=format&fit=clip&q=50)

After the activation step is successful, save the configuration.

![A screenshot highlighting the "Save" button in the JumpCloud admin dashboard.](https://images.workoscdn.com/images/3a8a81bc-e204-4368-b281-6aec5666b817.png?auto=format&fit=clip&q=50)

---

## (4) Assign users and groups to your application

In order for your users and groups to be synced, you will need to assign them to your JumpCloud Application. Select “User Groups” from the top navigation menu.

Select the groups of users you would like to sync and save your changes.

![A screenshot highlighting the User Groups tab in the JumpCloud admin dashboard.](https://images.workoscdn.com/images/505e3ec4-0f83-4e68-a384-1d056f674b23.png?auto=format&fit=clip&q=50)

Begin provisioning users and groups and witness realtime changes in your [WorkOS Dashboard](https://dashboard.workos.com/).

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

## Frequently asked questions

### When a group is disconnected from the SCIM application in JumpCloud, I still see users that are a part of that disconnected group in WorkOS and my application – is this expected?

Instead of individually assigning users to a SCIM application, JumpCloud SCIM requires that users are assigned to the application through group membership.

To reflect valid user membership in your application, users should be removed from a group while the group is connected to the SCIM application rather than removing them directly from the application.

To remove an entire group, the group can be deleted from the JumpCloud User Management area while it is connected to the SCIM application.

### What is the `idp_id` for directory groups from JumpCloud?

JumpCloud provides a unique identifier for each group through the SCIM `externalId` field. This is persisted as the `idp_id` for [directory groups](/reference/directory-sync/directory-group) in WorkOS.

### JumpCloud SAML

Learn how to configure a connection to JumpCloud via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a JumpCloud SAML Connection, you’ll need to upload a JumpCloud Metadata file.

---

## What WorkOS provides

WorkOS provides the [ACS URL](/glossary/acs-url) and [SP Entity ID](/glossary/sp-entity-id). They’re readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot of the "Service Provider Details" of a JumpCloud Connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/77d299b3-4e00-4259-9580-3a5d47518f7a.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. In JumpCloud’s case, the ACS URL and Entity ID need to be set by the organization when configuring your application in their JumpCloud instance.

Specifically, the ACS URL and Entity ID will need to be set in the “Single Sign-On Configuration” section of the SAML app. You will input the ACS URL for “ACS URL” and the Entity ID as both “IdP Entity ID” and “SP Entity ID”:

![A screenshot highlighting the fields "IdP Entity ID", "SP Entity ID" and "ACS URL" in the JumpCloud dashboard.](https://images.workoscdn.com/images/5897416a-465f-4e71-a2f8-2c12329338b9.png?auto=format&fit=clip&q=50)

---

## What you’ll need

In order to integrate you’ll need the JumpCloud Metadata file. Here’s how to obtain it:

---

## (1) Log in

Log in to the JumpCloud admin dashboard, select “SSO” on the left and select your Application.

![A screenshot highlighting the SSO tab and app selection in the JumpCloud dashboard.](https://images.workoscdn.com/images/e144fd63-e8a0-40e3-9d6d-db113396b7f8.png?auto=format&fit=clip&q=50)

---

## (2) Configure Attribute Mapping

In the “User Attributes” section of the Single Sign-On Configuration page for the SAML app, add the following field-value parameter pairs:

- `id` → `email`
- `email` → `email`
- `firstName` → `firstname`
- `lastName` → `lastname`

![A screenshot showing user attribute mapping in the JumpCloud dashboard.](https://images.workoscdn.com/images/47100088-c7b5-4352-96e1-9709f7808b6b.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, follow the guidance below.

In the "Group Attributes" section, select the checkbox to "include group attribute", and then set the attribute name to `groups`.

![A screenshot showing 'Group Attributes' in the JumpCloud Admin Console.](https://images.workoscdn.com/images/b6f9fdc0-c660-41ce-8f8e-a99a8c5a4cf0.png?auto=format&fit=clip&q=50)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

### Check "Sign Assertion"

Be sure to check the “Sign Assertion” box shown below.

![A screenshot highlighting the checked "Sign Assertion" box in the JumpCloud dashboard.](https://images.workoscdn.com/images/e4cca1f9-3f24-45d6-80f7-3ef318eb4ba2.png?auto=format&fit=clip&q=50)

---

## (3) Upload Metadata File

Be sure to check “Declare Redirect Endpoint”.

![A screenshot highlighting the checked "Declare Redirect Endpoint" box in the JumpCloud dashboard.](https://images.workoscdn.com/images/3a24425c-dd94-4b86-8b3a-f476b6f55665.png?auto=format&fit=clip&q=50)

> NOTE: The "Declare Redirect Endpoint" setting needs to be enabled prior to exporting the IdP metadata below as this will alter the metadata.

Click the “Export Metadata” button under “JumpCloud Metadata”. This will download an XML metadata file.

![A screenshot highlighting the "Export Metadata" button in the JumpCloud dashboard.](https://images.workoscdn.com/images/abd1a6ff-ec7b-427b-b7d5-0813af0107ee.png?auto=format&fit=clip&q=50)

In the Connection Settings of the WorkOS Dashboard, click “Edit Metadata Configuration”.

![A screenshot highlighting the "Edit Metadata Configuration" button in the WorkOS Dashboard.](https://images.workoscdn.com/images/ead92f35-be05-431f-a987-e4a71745eb3f.png?auto=format&fit=clip&q=50)

In the modal that pops up, upload the JumpCloud Metadata file and then select “Save Metadata Configuration”.

![A screenshot showing the "XML File Metadata Configuration" modal in the WorkOS Dashboard.](https://images.workoscdn.com/images/060d5353-64ca-426a-a4f2-1b9290aad3f5.png?auto=format&fit=clip&q=50)

Once the file has uploaded, your Connection will then be linked and good to go!

### HiBob

Learn about syncing your user list with HiBob.

## Introduction

This guide outlines how to synchronize your application’s HiBob directories.

To synchronize an organization’s users and groups provisioned for your application, you’ll need the enterprise IT admin to provide you:

- A HiBob Service User ID.
- The HiBob Service User’s Token.

We will provide instructions below on the process in HiBob to create a Service User and collect those parameters.

> Note: The HiBob integration isn't enabled by default in the WorkOS Dashboard or Admin Portal. Please reach out to [support@workos.com](mailto:support@workos.com) or via your team’s WorkOS Slack channel if you would like HiBob enabled.

---

## (1) Set up your Directory

Login to your WorkOS dashboard and select “Organizations” from the left hand Navigation bar

Select the Organization you’d like to enable a HiBob Directory Sync connection for.

On the Organization’s page click “Manually Configure Directory”.

![A screenshot highlighting the "Manually Configure Directory" button in the Organization view of the WorkOS Dashboard.](https://images.workoscdn.com/images/66f8d2e8-6337-4e67-97cf-1fcf9ae0a8cb.png?auto=format&fit=clip&q=50)

You’ll be prompted to select “HiBob” from the “Directory Type Dropdown”, as well as enter the name of the directory.

Then click “Create Directory”.

![A screenshot highlighting the "Create Directory" modal for creating a HiBob directory in the WorkOS Dashboard.](https://images.workoscdn.com/images/0b8c4bdb-e745-4285-a208-3463631766c0.png?auto=format&fit=clip&q=50)

WorkOS will create a Directory Sync Connection where you will input a “Service User ID” and an “API Token”. The next step will walk you through how an organization IT admin can generate and gather these details.

![A screenshot highlighting the "Update Directory" button in a HiBob directory in the WorkOS Dashboard.](https://images.workoscdn.com/images/f47caea6-5218-4957-b8a1-3c3512ec52f0.png?auto=format&fit=clip&q=50)

---

## (2) Create a Service User in HiBob

HiBob uses a system called Service Users to utilize API actions. These steps walkthrough creating a Service User and obtaining the credentials needed by WorkOS to link with HiBob successfully.

Login to HiBob and navigate to “Settings” and then selecting the “Integrations” tab.

There will be a tile called Service Users, click on that.

![A screenshot highlighting the "Integrations" tab in the HiBob dashboard.](https://images.workoscdn.com/images/e240994a-4968-40ce-a75b-e3951ce0ac81.png?auto=format&fit=clip&q=50)

Press on the New Service user Button

The user will be prompted to enter a name (and display name, these can be the same) for the new service user, we recommend something like “WorkOS SCIM User”.

![A screenshot showing the "Create a new Service User" modal in the HiBob dashboard.](https://images.workoscdn.com/images/03b23b02-f8d2-4b33-b7f3-02db9dfaee15.png?auto=format&fit=clip&q=50)

HiBob will then present you with an ID and a Token, which will be populated into WorkOS, so make sure to inform the customer to provide these.

![A screenshot highlighting the "ID" and "Token" fields for a Service User in the HiBob dashboard.](https://images.workoscdn.com/images/81d6408a-0f04-4486-8864-cf9c08928d86.png?auto=format&fit=clip&q=50&w=2048)

The enterprise IT admin should make sure that the Service User has permissions to “View selected employees lifecycle sections”.

---

## (3) Input the HiBob Service User details in WorkOS

Back in the connection that was created in your WorkOS dashboard, enter these two fields and press “Save Directory Details.”

![A screenshot highlighting the Directory Details modal of a HiBob directory in the WorkOS Dashboard.](https://images.workoscdn.com/images/8bd8dd85-864f-4712-98ac-788821b3b705.png?auto=format&fit=clip&q=50)

You should see the connection now displays “Linked” in green.

---

## (4) View users and groups in your dashboard

You will now see updates to the users in the directory under the “Users” tab in the HiBob Directory Sync page in WorkOS.

![A screenshot showing the "Users" view of a HiBob directory in the WorkOS Dashboard.](https://images.workoscdn.com/images/8474708e-dd99-472e-aba4-337c8463551d.png?auto=format&fit=clip&q=50)

---

## Frequently asked questions

### What if the directory user profiles from HiBob aren't showing all of the expected user attributes, such as the user address?

If some user attributes are not being sent along in the profile, you’ll want to start by checking the permissions of the Service User you created in step 2. You can see more about accessing Service User permissions [here](https://apidocs.hibob.com/docs/api-service-users) and some relevant FAQs from HiBob [here](https://help.hibob.com/hc/en-us/articles/4409776408209#how-to-review-permission-group-changes-0-4).

### How often do HiBob directories perform a sync?

HiBob directories poll every 30 minutes starting from the time of the initial sync.

### Google SAML

Learn how to configure a connection to Google Workspace via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [connection](/glossary/connection). Often, the information required to create a connection will differ by Identity Provider.

To create a Google SAML connection, you’ll need three pieces of information: an [ACS URL](/glossary/acs-url), a [SP Entity ID](/glossary/sp-entity-id), and an [IdP Metadata URL](/glossary/idp-metadata).

Start by logging into your [WorkOS Dashboard](https://dashboard.workos.com/) and selecting “Organizations” from the left hand navigation bar.

Click on the organization you’d like to configure a Google SAML connection for and select “Manually Configure Connection”.

![A screenshot showing where to find “Manually Configure Connection” for an Organization in the WorkOS Dashboard.](https://images.workoscdn.com/images/26e7f2ca-7d61-4f02-9a67-f3bfbc254ba3.png?auto=format&fit=clip&q=50)

Select “Google Workspace SAML” from the Identity Provider dropdown, enter a descriptive name for the connection, and then select the “Create Connection” button.

![A screenshot showing how to create a connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/7f2f8f2b-22d1-443c-a692-5eb7fa506042.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

WorkOS provides the ACS URL and the SP Entity ID. It’s readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot showing where to find the ACS URL and SP Entity ID in the WorkOS Dashboard.](https://images.workoscdn.com/images/1d07cb61-b23a-4894-ab9b-fd97d5bc6d6b.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. In Google’s case, it needs to be set by the organization when configuring your application in their Google admin dashboard.

The SP Entity ID is a URI used to identify the issuer of a SAML request, response, or assertion. In this case, the entity ID is used to communicate that WorkOS will be the party performing SAML requests to the organization's Google instance.

Specifically, the ACS URL will need to be set as the “ACS URL” and the SP Entity ID will need to be set as the “Entity ID” in the “Service Provider Details” step of the Google SAML setup.

---

## What you’ll need

In order to integrate you’ll need the metadata XML file from Google.

Normally, this information will come from the organization's IT Management team when they set up your application’s SAML 2.0 configuration in their Google admin dashboard. But, should that not be the case during your setup, here’s how to obtain it.

---

## (1) Log in

Log in to the Google Admin dashboard, select “Apps” from the sidebar menu, and then select “Web and Mobile Apps” from the following list. If your application is already created, select it from the list of applications and move to Step 7. If you haven’t created a SAML application, select “Add App” and then “Add custom SAML app”.

![A screenshot showing where to find "Add custom SAML app" in the Google Dashboard.](https://images.workoscdn.com/images/1a0abd99-4e2c-403f-89b9-a3fd11d6fb9a.png?auto=format&fit=clip&q=50)

---

## (2) Enter Your App’s Information

Give the app a descriptive name and upload an icon, if applicable. Click “Continue”.

![A screenshot showing where to add app name in the Google Dashboard.](https://images.workoscdn.com/images/89ae0c9e-becf-4076-8178-7d4535eac778.png?auto=format&fit=clip&q=50)

---

## (3) Obtain Identity Provider Details

Select the “Download Metadata” button to download the metadata file. Save this file, as you’ll upload it to the WorkOS Dashboard in Step 7. Click “Continue”.

![A screenshot showing where to find "Download Metadata" in the Google Dashboard.](https://images.workoscdn.com/images/92b16c09-8b06-4b8b-b4a0-2f441fd3d878.png?auto=format&fit=clip&q=50)

---

## (4) Enter Service Provider Details

Copy and the “ACS URL” from your WorkOS Dashboard and paste it into the “ACS URL” field, and copy the “SP Entity ID” from your WorkOS Dashboard and paste it into the “Entity ID” field in the Google SAML “Service provider details” modal. Select “Continue.”

![A screenshot showing where to enter "Entity ID" and "ACS URL" in the Google Dashboard.](https://images.workoscdn.com/images/946113dc-812e-446d-b466-32eec2b27629.png?auto=format&fit=clip&q=50)

---

## (5) Configure Attribute Mapping

Provide the following Attribute Mappings and select “Finish”.

Google SAML does not provide the option to map a user’s id attribute claim.

![A screenshot showing completed Attribute Mappings in the Google Dashboard.](https://images.workoscdn.com/images/dcf0968a-346c-4a58-bd76-8e0a87d92d66.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, follow the guidance below.

Scroll down to the "Group membership" section. Add any groups you'd like to send under "Google groups", and set the "App attribute" to "groups". Then, select "Finish".

![A screenshot showing how to add a group attribute in the Google dashboard.](https://images.workoscdn.com/images/b7a6e5f7-aaf1-4756-9fc9-04f70f1c8a67.png?auto=format&fit=clip&q=50)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (6) Configure User Access

In the created SAML app’s landing page, select the “User Access Section”.

![A screenshot showing where to find the "User Access Section" in the Google Dashboard.](https://images.workoscdn.com/images/57080072-5a42-4463-897b-2382c643082a.png?auto=format&fit=clip&q=50)

Turn this service ON for the correct organizational units in your Google Directory setup. Save any changes.

Google may take up to 24 hours to propagate these changes. The connection in WorkOS will be inactive until then.

---

## (7) Upload Metadata File

If you haven’t already downloaded the metadata file, select your SAML application, and click “Download Metadata”. In the modal, again click “Download Metadata”.

![A screenshot showing where to find "Download Metadata" in the Google Dashboard.](https://images.workoscdn.com/images/7e1a8f1f-fb44-435d-961a-d71eff48d207.png?auto=format&fit=clip&q=50)

In the connection Settings of the WorkOS Dashboard, click “Edit Metadata Configuration”.

![A screenshot showing the “Edit Metadata Configuration” button in the WorkOS Dashboard.](https://images.workoscdn.com/images/afe34aca-df4f-4005-b71e-bf528916a491.png?auto=format&fit=clip&q=50)

In the modal, upload the Google Metadata file and then select “Save Metadata Configuration”. Once the file is uploaded into WorkOS, your connection will then be linked and good to go!

![A screenshot showing a linked Google SAML connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/9c497a05-f823-4c51-ab54-e5b6feed53fa.png?auto=format&fit=clip&q=50)

---

## Frequently asked questions

### Where is the Relay State in Google SAML?

Within the Google SAML setup, there will be a field called “Start URL” which is referred to as the Relay State.

### Google OIDC

Learn how to configure a connection to Google via OIDC.

## Introduction

Each SSO identity provider requires specific information to create and configure a new [SSO connection](/glossary/connection). Often, the information required to create an SSO connection will differ by identity provider.

To create a Google OIDC SSO connection, you'll need three pieces of information: a [redirect URI](/glossary/redirect-uri), [client ID](/glossary/client-id), and [client secret](/glossary/client-secret).

Start by logging in to your WorkOS dashboard and navigate to the **Organizations** page from the left-hand navigation bar.

Select the organization you'd like to configure a Google OIDC SSO connection for, and select **Configure manually** under **Single Sign-On**.

![WorkOS Dashboard Organizations tab with "Configure manually" button highlighted](https://images.workoscdn.com/images/d577cfbe-028b-48cf-8cc0-4cd5d3adf853.png?auto=format&fit=clip&q=50)

Select **Google OIDC** from the identity provider dropdown, click **Create Connection**.

![Create Connection form with Google OIDC selected as Identity Provider](https://images.workoscdn.com/images/35cfe8ab-1825-4f0d-ab93-7c0eb6e0d742.png?auto=format&fit=clip&q=50)

> Google OIDC is not available when [SSO group role assignment](/sso/identity-provider-role-assignment) is enabled due to [a limitation](https://issuetracker.google.com/issues/133774835?pli=1) with the groups claim.

---

## What WorkOS provides

WorkOS provides the Redirect URI, which can be found in the **Service Provider Details** section on the SSO connection page in the [WorkOS Dashboard](https://dashboard.workos.com/).

- [Redirect URI](/glossary/redirect-uri): The endpoint where identity providers send authentication responses after successful login

![The Redirect URI of a OIDC connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/99a7c7d5-50a9-4bff-a3f3-22dc1cfeca58.png?auto=format&fit=clip&q=50)

The Redirect URI is the location an identity provider redirects its authentication response to. In Google's case, it needs to be set as an **Authorized redirect URI** when configuring your OAuth client in the Google Cloud Console.

Specifically, the Redirect URI will need to be added to the **Authorized redirect URIs** section when creating your OAuth client, which is outlined in [step 3](/integrations/google-oidc/3-create-oauth-client) below.

---

## What you'll need

You will need to obtain two pieces of information from the organization:

- [Client ID](/glossary/client-id): Application identifier from the OIDC provider
- [Client secret](/glossary/client-secret): Authentication secret for the application

Normally, this information will come from the organization's IT management team when they set up your application's OAuth configuration in their Google Cloud Console. But, should that not be the case during your setup, the next steps will show you how to obtain it.

---

## (1) Create a Google Cloud project (optional)

> If you already have a Google Cloud project, skip this step.

Sign in to the [Google Cloud Console](https://console.cloud.google.com).

From the top left navigation, click **Select a project**. Select an organization and then click **Create project**.

![Google Cloud Console project selector with "Create project" option](https://images.workoscdn.com/images/941eaf2f-b6a3-4c86-83aa-4cb005dbc1e4.png?auto=format&fit=clip&q=50)

Enter a project name. Update the project organization and location if needed. Click **Create**.

![Google Cloud project creation form with project name, organization, and location fields](https://images.workoscdn.com/images/b7cd689d-0e89-4eee-8f32-f6b93522fed1.png?auto=format&fit=clip&q=50)

---

## (2) Configure OAuth app

From the top left navigation, click **Select a project**. Select the project you created in the previous step or one that is already set up.

![Google Cloud Console project selector dropdown with available projects](https://images.workoscdn.com/images/675794e5-9a6d-42cc-8d68-46e58a29caab.png?auto=format&fit=clip&q=50)

Search for **Google Auth Platform** and select it from the results list.

![Google Cloud Console search results showing Google Auth Platform service](https://images.workoscdn.com/images/ef574ce6-3402-4dbe-9e3e-4d3d00d82212.png?auto=format&fit=clip&q=50)

Click **Get started**.

![Google Cloud OAuth App dashboard with highlighted get started button](https://images.workoscdn.com/images/2e35fd83-74db-45b4-ad13-510fb52b57b0.png?auto=format&fit=clip&q=50)

On the **App Information** step, enter an app name, such as your organization name. Select a user support email from the dropdown. Click **Next**.

![OAuth consent screen App Information step with app name and user support email fields](https://images.workoscdn.com/images/2365ee0a-497b-4235-9d08-e9e740a140f0.png?auto=format&fit=clip&q=50)

On the **Audience** step, select **Internal** and click **Next**.

![OAuth consent screen Audience step with Internal option selected](https://images.workoscdn.com/images/e3689b48-4ada-43a6-818f-244cfebf0393.png?auto=format&fit=clip&q=50)

On the **Contact Information** step, enter a contact email and click **Next**.

![OAuth app information screen with contact information field highlighted and demo@foo-corp.com email filled in, next button is highlighted](https://images.workoscdn.com/images/7ef6519e-dc76-473b-901f-388e69762433.png?auto=format&fit=clip&q=50)

Agree to the terms of service, click **Continue** and then **Create**.

![OAuth consent screen terms of service acceptance and Create button](https://images.workoscdn.com/images/e211e959-1325-4dfc-8a8c-96d4ee0030cf.png?auto=format&fit=clip&q=50)

---

## (3) Create OAuth client

From the left-hand sidebar navigation, click **Clients** and then click **Create client**.

![Google Auth Platform Clients page with "Create client" button](https://images.workoscdn.com/images/24e008c1-4a8e-4bfe-8603-1074453a815b.png?auto=format&fit=clip&q=50)

From the **Application type** dropdown, select **Web application**.

![OAuth client creation form with Web application selected as application type](https://images.workoscdn.com/images/17bc8607-23be-457f-9cf1-995730748d55.png?auto=format&fit=clip&q=50)

Under the **Authorized redirect URIs** section, click **Add URI**. Copy the Redirect URI from your WorkOS Dashboard and paste it into the new redirect URI field.

![Authorized redirect URIs section with Add URI button and WorkOS redirect URI field](https://images.workoscdn.com/images/b98e091f-9005-4a1f-bfb9-56eb26a88844.png?auto=format&fit=clip&q=50)

Click **Create**.

---

## (4) Add organization settings

From the **OAuth client created** modal, copy the **Client ID** and **Client Secret** values.

![OAuth client created modal displaying Client ID and client secret](https://images.workoscdn.com/images/51a44c08-a559-456b-926f-33334d7cb755.png?auto=format&fit=clip&q=50)

Back in the WorkOS Dashboard, enter the client ID, and client secret you obtained from Google into the respective fields in the **Identity Provider Configuration** section of the SSO connection.

Enter `https://accounts.google.com/.well-known/openid-configuration` in the **Discovery Endpoint** field, this is the same value for all Google Cloud Console projects.

![WorkOS Dashboard Identity Provider Configuration with Client ID, Client Secret, and Discovery Endpoint fields](https://images.workoscdn.com/images/d3305808-a772-4f2a-a7e1-c862b9274975.png?auto=format&fit=clip&q=50)

Click **Save Configuration**.

---

## Next steps

Your Google OIDC connection is now configured and ready to use. Users within your organization will be able to authenticate through WorkOS using their Google credentials.

To start using this connection in your application, refer to the [SSO guide](/sso) for implementation details.

### Google OAuth

Learn how to set up OAuth with Google Workspace

## Introduction

The Google OAuth integration allows your users to authenticate using their Google Workspace credentials.

The configuration process involves obtaining client credentials from your Google Cloud Platform Console and configuring them in the WorkOS Dashboard.

---

## Testing with default credentials in the staging environment

WorkOS provides a default Google Client ID and Client Secret combination, which allows you to quickly enable and test Google OAuth. Use the [WorkOS API to initiate SSO](/sso/1-add-sso-to-your-app/add-an-endpoint-to-initiate-sso), setting the `provider` parameter to `GoogleOAuth`, and WorkOS will automatically use the default credentials until you add your own Google Client ID and Client Secret to the configuration in the WorkOS Dashboard.

> The default credentials are only intended for testing and therefore only available in the Staging environment. For your production environment, please follow the steps below to create and specify your own Google Client ID and Client Secret.

Please note that when you are using WorkOS default credentials, Google's authentication flow will display WorkOS' name, logo, and other information to users. Once you register your own application and use its Google Client ID and Client Secret for the OAuth flow, you will have the opportunity to customize the app, including its name, logo, contact email, etc.

---

## What WorkOS provides

When setting up Google OAuth, WorkOS provides one key piece of information that needs to be configured in your Google Cloud Platform project:

- [Redirect URI](/glossary/redirect-uri): The endpoint where Google will send authentication responses after successful login

The Redirect URI is available in the [WorkOS Dashboard](https://dashboard.workos.com/). In the left navigation menu, select the **Authentication** tab and the **OAuth providers** sub-tab. Locate the **Google** section.

![Open the Google configuration dialog](https://images.workoscdn.com/images/1e400f3e-1885-481f-8840-4a3a9f8c7f97.png?auto=format&fit=clip&q=50)

Click **Manage**. The **Google OAuth** configuration dialog will open. Locate the **Redirect URI**.

![Google OAuth Redirect URI in the WorkOS Dashboard.](https://images.workoscdn.com/images/020273f1-d216-4aca-8ddd-8963accd7517.png?auto=format&fit=clip&q=50)

The **Redirect URI** serves as the destination for authentication responses and must be configured in your Google Cloud Platform project as an authorized redirect URI.

---

## What you'll need

You will need to obtain two pieces of information from a Google Cloud Platform project:

- **Google Client ID**: Application identifier from Google Cloud Platform
- **Google Client Secret**: Authentication secret for the application

The following sections will guide you through generating these credentials in your Google Cloud Platform Console.

---

## (1) Access Google Cloud Platform Console

Sign in to the [Google Cloud Platform Console Dashboard](https://console.cloud.google.com/) and select your application's project from the project selection dropdown menu in the navigation bar.

![How to select your application in the Google Cloud Platform Console Dashboard.](https://images.workoscdn.com/images/45adf7cf-78e0-4c5a-a6c1-7b3eee62c723.png?auto=format&fit=clip&q=50)

---

## (2) Configure OAuth consent screen

In the left navigation menu, select **APIs & Services** and then **OAuth Consent Screen**.

![Where to find the OAuth Consent Screen option in the Google Cloud Platform Console Dashboard.](https://images.workoscdn.com/images/c37375e2-6ef2-41ba-9b65-a125501bfd5a.png?auto=format&fit=clip&q=50)

Now within the **Google Auth Platform**, in the left navigation menu, select **Clients**. Click **Create client**.

![How to create a new client in the Google Cloud Platform Console Dashboard.](https://images.workoscdn.com/images/c5ffe36c-e471-4b27-a6b9-936d26837e93.png?auto=format&fit=clip&q=50)

In the **Application type** dropdown, select **Web application**. Provide an appropriate name for your OAuth client ID.

> As a best practice, your OAuth client ID's name should be different from your application's name. It will not be shown to end users.

Under the **Authorized redirect URIs** section, click **Add URI**. Add the **Redirect URI** from the WorkOS Dashboard.

![Where to enter your WorkOS Redirect URI in the Google Cloud Platform Console Dashboard.](https://images.workoscdn.com/images/e18673f7-e490-46a7-ad0c-f71d5ddcb08a.png?auto=format&fit=clip&q=50)

Scroll down and click **Create**. It may take up to 5 minutes, but once your OAuth client is created, you'll be presented with your application's client ID and client secret. Be sure to copy these values as they may not be available after closing the dialog.

![The client ID and client secret in the Google Cloud Platform Console Dashboard.](https://images.workoscdn.com/images/13a05048-c45c-43c5-9d56-39faf53ab479.png?auto=format&fit=clip&q=50)

---

## (4) Configure Google credentials in WorkOS

Now that you have the **Google Client ID** and **Google Client Secret** from the previous step return to the [WorkOS Dashboard](https://dashboard.workos.com).

In the **Google OAuth** configuration dialog, select **Your app's credentials**. Paste the credentials from Google into their respective fields in the WorkOS Dashboard.

![Where to enter the Google Client ID and Google Client Secret in the WorkOS Dashboard.](https://images.workoscdn.com/images/6c209570-926d-49bf-9189-0e2f705e70ee.png?auto=format&fit=clip&q=50)

Click **Save** to complete the configuration.

---

## (5) Publish the Google OAuth application

In the left navigation menu of the Google Cloud Platform Console, select the **Audience** tab. If your application is not **In production**, click **Publish app**. In the **Push to Production?** dialog that opens, click **Confirm**. If your application is still in testing mode, users will likely get an "Access Blocked" error when attempting to log into your app.

![The publishing status of your Google OAuth application](https://images.workoscdn.com/images/564bc12f-0abb-4866-8a48-eb9451b851fb.png?auto=format&fit=clip&q=50)

After that, you're now able to authenticate users with Google OAuth. You will use the `provider` query parameter in the Get Authorization URL API endpoint to support global Google OAuth for any domain. The `provider` query parameter should be set to `GoogleOAuth`.

---

## Customize Google OAuth Domain (Optional)

This optional process requires access to your Google Cloud Console and your domain's DNS settings.

After implementing the steps above, you'll notice that the Google OAuth sign in form displays "Choose an account to continue to workos.com". This is based on the Authorized Redirect URI in Google. To set this to a domain other than workos.com, Google will ask for proof of ownership of your domain. To help guide you through this process we have a self-service flow.

### (1) Add your custom Google OAuth domain

In the **Authentication** tab of the WorkOS Dashboard, find the **Google OAuth** section. Depending on which WorkOS products have been enabled, the **Google OAuth** section may be under the **Methods** or **OAuth providers** sub-tabs in the left navigation menu.

Click **Setup Custom Domain**.

> Note: This button will only appear if your environment has a valid Google OAuth configuration and a custom domain has not already been configured.

![Where to find the Set Up Custom Domain button in the WorkOS Dashboard.](https://images.workoscdn.com/images/9ba10d03-c0af-41e6-b090-884ba1cddca4.png?auto=format&fit=clip&q=50)

Under **Add Custom Domain**, input the domain that you wish to use in place of `auth.workos.com`. This is often a subdomain such as `auth.example.com`. Click on **Set Domain**.

![Where to add a custom domain in the WorkOS Dashboard.](https://images.workoscdn.com/images/d233701c-74c5-4a42-a063-9eaa680dc7c9.png?auto=format&fit=clip&q=50)

### (2) Add CNAME target

Add a new CNAME target inside your domain's DNS settings. Set the host to match the domain you set in the previous step and set the value to `cname.workosdns.com`.

Once the above is complete, click **Verify DNS**. This verification often takes less than a minute, but is dependent on how long your DNS record takes to propagate. The page will continue polling to check the status of your verification until it is successful.

![The CNAME target of cname.workosdns.com in the WorkOS Dashboard.](https://images.workoscdn.com/images/feebf1a1-1f42-4c0b-b1fc-67d37745b948.png?auto=format&fit=clip&q=50)

### (3) Add new redirect URI to Google

Once the DNS has been successfully verified, WorkOS will provide a URI starting with your subdomain in the **Add redirect URI to Google** section. Click on the clipboard icon to copy the URL.

![The clipboard icon in the WorkOS Dashboard.](https://images.workoscdn.com/images/95060659-da91-40d8-849b-9718ef7b00fc.png?auto=format&fit=clip&q=50)

In the Google Cloud Platform Console, under your project's **APIs & Services** → **Clients** section, add the URL copied above in the **Authorized redirect URIs** section. To ensure your Google OAuth integration continues to work without any gaps in service, leave your existing redirect URI in place for now.

![Where to enter the redirect URI in the Google Cloud Platform Console.](https://images.workoscdn.com/images/548b4e3e-164e-4358-ab1d-58c5d3071731.png?auto=format&fit=clip&q=50)

### (4) Test Google redirect URI

Once the URL has been added and saved on the Google side, navigate back to the WorkOS Dashboard and click on **Test Google Redirect URI**.

![The Test Google Redirect URI button in the WorkOS Dashboard.](https://images.workoscdn.com/images/1e191eb9-a316-407e-ae63-69be88ac3665.png?auto=format&fit=clip&q=50)

If the test is successful, you will see a **Successfully tested** message displayed. Click **Save custom Google OAuth settings**.

Once these updates have been saved, test out your Google OAuth sign in flow to ensure everything is working properly and your domain is displayed on the form. If everything is looking good, it is safe to remove the old `auth.workos.com` URL from your Google Authorized redirect URIs, and `workos.com` from your Google Authorized domains.

---

## Configure Additional OAuth Scopes (Optional)

WorkOS will request the OAuth scopes that are required for authentication by default. You can optionally configure your integration to request additional OAuth scopes as needed.

When the **Return Google OAuth tokens** option is selected, the access token and refresh token from Google will be included in the response from the [Authenticate with code API](/reference/authkit/authentication/code).

![A screenshot showing Google OAuth scopes configuration in the WorkOS Dashboard](https://images.workoscdn.com/images/53f64aa3-fbd1-4371-9fba-2e2ff9eb0823.png?auto=format&fit=clip&q=50)

Any scopes configured here will be included on every Google OAuth request. To specify additional scopes dynamically, use the `provider_scopes` query parameter on the [Get Authorization URL API endpoint](/reference/authkit/authentication/get-authorization-url).

Any additional scopes that you plan to request must also be configured on your OAuth consent screen in the Google Cloud Platform Console.

Google considers some scopes to be sensitive or restricted. If requesting any of these sensitive or restricted scopes, your application will need to be verified by Google. For more information, see Google's OAuth scopes [documentation](https://developers.google.com/identity/protocols/oauth2/scopes).

![A screenshot showing Google OAuth scopes configuration in the Google Cloud Console](https://images.workoscdn.com/images/c9f2cc5d-ca3c-466f-9db8-9138ad60cc43.png?auto=format&fit=clip&q=50)

> IMPORTANT: Your users will see an "unverified app" screen from Google and may see errors during sign-in if the scopes included on an authorization request differ from the scopes configured on your OAuth consent screen, or if you request sensitive or restricted scopes without going through Google's app verification process. Changes to scopes should be tested in a staging environment before applying them to production.

---

## Frequently asked questions

### How is the WorkOS Google OAuth integration different from implementing regular Google OAuth flow?

It's the same Google OAuth flow as you could build yourself, but it's encapsulated within WorkOS SSO. This means you don't need to build it yourself. In addition to Google OAuth, you can use WorkOS SSO to support other identity providers, all with a single integration.

### What is the provider query parameter and how is it used in the Google OAuth integration?

You can use the `provider` query parameter in the [Get Authorization URL API endpoint](/reference/sso/get-authorization-url) to support global Google OAuth for any domain. The `provider` query parameter should be set to `GoogleOAuth`.

### Google Directory Sync

Learn about syncing your user list with Google Workspace.

## Introduction

This guide outlines how to synchronize your application’s Google Workspace directories.

---

## (1) Select environment

Login to your WorkOS dashboard and ensure you have the desired environment selected.

![Select the desired WorkOS environment from the navigation.](https://images.workoscdn.com/images/8f30c9d7-8569-4cb2-8fbe-1d8fc46be717.png?auto=format&fit=clip&q=50)

## (2) Send an admin invite link

Select “Organizations” in the navigation.

Select the organization that'd like to enable a Google Directory Sync connection.

On the Organization page, under “Invite an admin to set up this organization,” select “Invite Admin.”

![Select “Invite Admin” from the organization page.](https://images.workoscdn.com/images/f879b479-24e6-4c86-acb8-8abb05f2a2ff.png?auto=format&fit=clip&q=50)

Select “Directory Sync” and any other features you'd like the organization to be able to onboard.

![Select “Directory Sync” and any other features you'd like the organization to be able to onboard.](https://images.workoscdn.com/images/2ff61c68-3709-4b35-ac0d-f2b5b6333d9b.png?auto=format&fit=clip&q=50)

Enter the email address of the organization admin, or copy the setup link and send it to the organization admin.

![Enter the email address of the organization admin, or copy the setup link.](https://images.workoscdn.com/images/a3414089-79a1-4137-8687-3e803a6f364a.png?auto=format&fit=clip&q=50)

---

## (3) Authenticate with admin credentials

Have the organization choose Google as a provider and follow the Google prompts to authenticate with admin credentials.

![A screenshot showing the requested permissions in the Google modal.](https://images.workoscdn.com/images/1809508c-e153-47f7-a9b7-5b243ff95c7c.png?auto=format&fit=clip&q=50)

---

## (4) Select which groups to sync to Your Application

The organization admin can then select to filter which groups and memberships are synced to the directory. If groups are being filtered, then only users with a membership within one of the synced groups will be synced.

![A screenshot showing the setup screen with how to filter groups to sync.](https://images.workoscdn.com/images/43942f32-e228-4745-89a6-fa6ff3e6f4dc.png?auto=format&fit=clip&q=50)

---

## (5) Sync users and groups to Your Application

Changes will appear live in the Directory Sync portal under the "Users" tab:

![A screenshot showing users in the "Users" tab of the WorkOS Dashboard.](https://images.workoscdn.com/images/268ff490-71bd-4aa4-9f7d-c01f3548b198.png?auto=format&fit=clip&q=50)

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

## Frequently asked questions

### Can you selectively sync users and groups from Google Workspace?

Yes, you can select to sync certain groups during setup within the Admin Portal as seen in [Step 4](/integrations/google-directory-sync/4-select-which-groups-to-sync-to-your-application).

### When do users get removed from a directory?

There are 2 ways a user can be deleted from a Google Workspace directory.

1. The user is removed or archived on Google and no longer returned by their API.
2. When the directory is [filtering specific groups](/integrations/google-directory-sync/4-select-which-groups-to-sync-to-your-application), if a user is removed from all groups that are being filtered in, the user is removed from the directory as well.

### How often do Google Workspace directories perform a sync?

Google Workspace directories are synced approximately every 30 minutes starting from the time of the initial sync

### Does Google Directory Sync support nested groups?

Yes, nested groups (groups within groups) are supported in Google Directory Sync. This feature is currently available in a restricted preview. Contact [WorkOS support](mailto:support@workos.com) for additional details.

### What is the `idp_id` for directory groups from Google Workspace?

Google Workspace provides a unique identifier for each group, which is persisted as the `idp_id` for [directory groups](/reference/directory-sync/directory-group) in WorkOS.

### GitLab OAuth

Learn how to set up OAuth with GitLab

## Introduction

The GitLab OAuth integration allows your users to authenticate using their GitLab credentials.

The configuration process involves creating an OAuth application in GitLab and configuring the client credentials in your WorkOS Dashboard.

---

## What WorkOS provides

When setting up GitLab OAuth, WorkOS provides one key piece of information that needs to be configured in your GitLab OAuth application:

- [Redirect URI](/glossary/redirect-uri): The endpoint where GitLab will send authentication responses after successful login

The Redirect URI is available in the [WorkOS Dashboard](https://dashboard.workos.com/). In the left navigation menu, select the **Authentication** tab and the **OAuth providers** sub-tab. Locate the **GitLab** section.

![The GitLab OAuth section in the WorkOS Dashboard](https://images.workoscdn.com/images/37e84a18-3d18-4fc9-a122-63589ab4ddf0.png?auto=format&fit=clip&q=50)

Click **Enable**. The **GitLab OAuth** configuration dialog will open. Locate the **Redirect URI**.

![The GitLab OAuth configuration modal in the WorkOS Dashboard](https://images.workoscdn.com/images/3ec9c4c3-1fc1-4ef6-a2fb-eeca07701d33.png?auto=format&fit=clip&q=50)

The **Redirect URI** serves as the destination for authentication responses and must be configured in your GitLab OAuth application as the redirect URI.

---

## What you'll need

You will need to obtain two pieces of information from a GitLab OAuth application:

- **GitLab Client ID**: Application identifier from GitLab (called Application ID in GitLab)
- **GitLab Client Secret**: Authentication secret for the application (called Secret in GitLab)

The following sections will guide you through creating an OAuth application in your GitLab account and generating these credentials.

---

## (1) Create the GitLab OAuth application

Log in to your [GitLab account](https://gitlab.com) and navigate to your user settings.

In the left navigation menu, select your avatar. Click **Edit profile**. Select **Applications**. Click **Add new application**.

![GitLab page to register a new OAuth application.](https://images.workoscdn.com/images/ad782ab8-74ad-4787-91fe-685e0f466509.png?auto=format&fit=clip&q=80)

> You can also register a new application under a group, which may be more appropriate if it is maintained by a team of developers, or instance-wide if you have a dedicated GitLab instance. For more on this see the [GitLab docs](https://docs.gitlab.com/integration/oauth_provider/).

---

## (2) Configure the GitLab OAuth application

Fill out the form with relevant details about your application, including the application name.

For **Redirect URI**, enter the **Redirect URI** from the GitLab OAuth configuration in the WorkOS Dashboard.

![GitLab form to create a new OAuth application.](https://images.workoscdn.com/images/7c86fdf4-c635-46c5-977c-965b85a322fd.png?auto=format&fit=clip&q=80)

The **Confidential** flag is enabled by default. It should be exclusively used by a trusted backend server that can securely store the client secret. For native-mobile, single-page, or other JavaScript applications, disable this flag.

Select the **openid**, **profile**, and **email** scopes for this app to allow the application to read user profile information, then click **Save application**.

---

## (3) Generate client credentials

On the next page, you will see the GitLab **Application ID** and **Secret** for your new OAuth application.

![OAuth client credentials in the GitLab application settings.](https://images.workoscdn.com/images/b7ce3a64-673a-476f-8a3c-cf63c76bf88e.png?auto=format&fit=clip&q=80)

Note the **Application ID** and **Secret** values as you'll need them for the WorkOS configuration.

---

## (4) Configure GitLab credentials in WorkOS

Now that you have the **GitLab Client ID** (Application ID) and **GitLab Client Secret** (Secret) from the previous step, return to the [WorkOS Dashboard](https://dashboard.workos.com).

In the **GitLab OAuth** configuration dialog, enable the integration. Paste the credentials from GitLab into their respective fields in the WorkOS Dashboard.

![Where to enter GitLab client credentials in the WorkOS dashboard.](https://images.workoscdn.com/images/6e9b410d-33bf-485f-b1c4-6a16fbeaa946.png?auto=format&fit=clip&q=80)

Click **Save** to complete the configuration.

You are now ready to start authenticating with GitLab OAuth. You will use the `provider` query parameter in the Get Authorization URL API endpoint to support global GitLab OAuth for any domain. The `provider` query parameter should be set to `GitLabOAuth`.

---

## Configure Additional OAuth Scopes (Optional)

WorkOS will request the OAuth scopes that are required for authentication by default. You can optionally configure your integration to request additional OAuth scopes as needed.

When the **Return GitLab OAuth tokens** option is selected, the access token and refresh token from GitLab will be included in the response from the [Authenticate with code API](/reference/authkit/authentication/code).

![A screenshot showing GitLab OAuth scopes configuration in the WorkOS Dashboard](https://images.workoscdn.com/images/8d4803a8-f436-45cb-974e-eaa79522181e.png?auto=format&fit=clip&q=50)

Any scopes configured here will be included on every GitLab OAuth request. To specify additional scopes dynamically, use the `provider_scopes` query parameter on the [Get Authorization URL API endpoint](/reference/authkit/authentication/get-authorization-url).

Any additional scopes that you plan to request must also be configured on the Application settings page in GitLab. For more information, see GitLab's OAuth scopes [documentation](https://docs.gitlab.com/integration/oauth_provider).

![A screenshot showing GitLab OAuth scopes configuration in GitLab Application Settings](https://images.workoscdn.com/images/25d9971d-55b1-473b-9d7d-d8e42e893725.png?auto=format&fit=clip&q=50)

> IMPORTANT: Your users will see an error during sign-in if the scopes included on an authorization request are not included in the scopes configured on the Application settings page in GitLab. Changes to scopes should be tested in a staging environment before applying them to production.

---

## Frequently asked questions

### How is the WorkOS GitLab OAuth integration different from implementing regular GitLab OAuth flow?

It's the same GitLab OAuth flow as you could build yourself, but it's encapsulated within WorkOS SSO. This means you don't need to build it yourself. In addition to GitLab OAuth, you can use WorkOS SSO to support other identity providers, all with a single integration.

### What is the provider query parameter and how is it used in the GitLab OAuth integration?

You can use the `provider` query parameter in the [Get Authorization URL API endpoint](/reference/sso/get-authorization-url) to support global GitLab OAuth for any domain. The `provider` query parameter should be set to `GitLabOAuth`.

### What scopes are required for GitLab OAuth?

The **openid**, **profile**, and **email** scopes are required to allow the application to read user profile information necessary for authentication. This scope provides access to the user's basic profile data.

### Can I register the GitLab OAuth application under a group or organization?

Yes, you can register a new application under a GitLab group, which may be more appropriate if it is maintained by a team of developers. You can also register it instance-wide if you have a dedicated GitLab instance. See the [GitLab documentation](https://docs.gitlab.com/integration/oauth_provider/) for more details.

### What is the difference between Confidential and non-Confidential applications in GitLab?

The **Confidential** flag should be used for applications that can securely store the client secret, typically backend servers. For native mobile apps, single-page applications, or other JavaScript applications that cannot securely store secrets, you should disable this flag.

### GitHub OAuth

Learn how to set up OAuth with GitHub

## Introduction

The GitHub OAuth integration allows your users to authenticate using their GitHub credentials.

The configuration process involves creating an OAuth application in GitHub and configuring the client credentials in the WorkOS Dashboard.

---

## Testing with default credentials in the staging environment

WorkOS provides a default GitHub Client ID and Client Secret combination, which allows you to quickly enable and test GitHub OAuth. Use the [WorkOS API to initiate SSO](/sso/1-add-sso-to-your-app/add-an-endpoint-to-initiate-sso), setting the `provider` parameter to `GitHubOAuth`, and WorkOS will automatically use the default credentials until you add your own GitHub Client ID and Client Secret to the configuration in the WorkOS Dashboard.

> The default credentials are only intended for testing and therefore only available in the Staging environment. For your production environment, please follow the steps below to create and specify your own GitHub Client ID and Client Secret.

Please note that when you are using WorkOS default credentials, GitHub's authentication flow will display WorkOS' name, logo, and other information to users. Once you register your own application and use its GitHub Client ID and Client Secret for the OAuth flow, you will have the opportunity to customize the app, including its name, logo, contact email, etc.

---

## What WorkOS provides

When setting up GitHub OAuth, WorkOS provides one key piece of information that needs to be configured in your GitHub OAuth application:

- [Redirect URI](/glossary/redirect-uri): The endpoint where GitHub will send authentication responses after successful login

The Redirect URI is available in the [WorkOS Dashboard](https://dashboard.workos.com/). In the left navigation menu, select the **Authentication** tab and the **OAuth providers** sub-tab. Locate the **GitHub** section.

![Open the GitHub configuration dialog](https://images.workoscdn.com/images/b4ddb4d0-39f2-4e58-bc15-f3857f63415b.png?auto=format&fit=clip&q=50)

Click **Manage**. The **GitHub OAuth** configuration dialog will open. Locate the **Redirect URI**.

![GitHub OAuth Redirect URI in the WorkOS Dashboard](https://images.workoscdn.com/images/18629339-63d6-4b60-b5d5-7e75f7745de5.png?auto=format&fit=clip&q=50)

The **Redirect URI** serves as the destination for authentication responses and must be configured in your GitHub OAuth application as the authorization callback URL.

---

## What you'll need

You will need to obtain two pieces of information from a GitHub OAuth application:

- **GitHub Client ID**: Application identifier from GitHub
- **GitHub Client Secret**: Authentication secret for the application

The following sections will guide you through creating an OAuth application in your GitHub account and generating these credentials.

---

## (1) Create the GitHub OAuth Application

Sign in to GitHub and navigate to [**Developer settings**](https://github.com/settings/developers). Select **OAuth Apps**. Create a new OAuth app.

![The New OAuth App button in GitHub](https://images.workoscdn.com/images/d8991483-a60e-4bc6-985f-2053d8b3c2c9.png?auto=format&fit=clip&q=80)

> You can also register a new application under a GitHub Organization, which may be more appropriate if it is maintained by a team of developers. You can also [transfer ownership](https://docs.github.com/en/apps/oauth-apps/maintaining-oauth-apps/transferring-ownership-of-an-oauth-app) of your GitHub OAuth application to a GitHub organization later.

---

## (2) Configure OAuth application

Fill out the OAuth application form. For the **Authorization callback URL** input, enter the **Redirect URI** from the WorkOS Dashboard.

Click **Register application**.

![The GitHub form to create a new OAuth application.](https://images.workoscdn.com/images/6282967b-eee8-4937-8ec8-a1f25d7ec873.png?auto=format&fit=clip&q=80)

You'll be given a Client ID. Note this value as you'll need it for the WorkOS configuration.

Click **Generate a new client secret** to generate a new GitHub Client Secret. Note that this value is only temporarily available, so make sure to save it before proceeding.

![The Client ID and Client Secret in GitHub](https://images.workoscdn.com/images/ba3c133b-3492-4b5b-b10c-69717ca3e50c.png?auto=format&fit=clip&q=80)

---

## (3) Configure GitHub credentials in WorkOS

Now that you have the **GitHub Client ID** and **GitHub Client Secret** from the previous step return to the [WorkOS Dashboard](https://dashboard.workos.com/).

In the **GitHub OAuth** configuration dialog, select **Your app's credentials**. Paste the credentials from GitHub into their respective fields in the WorkOS Dashboard.

![Where to enter the GitHub Client ID and GitHub Client Secret in the WorkOS Dashboard](https://images.workoscdn.com/images/01d06b09-d622-4815-8757-c3b6825b790b.png?auto=format&fit=clip&q=50)

Click **Save** to complete the configuration.

You're now able to authenticate users with GitHub OAuth. You will use the `provider` query parameter in the Get Authorization URL API endpoint to support global GitHub OAuth for any domain. The `provider` query parameter should be set to `GitHubOAuth`.

---

## Configure Additional OAuth Scopes (Optional)

WorkOS will request the OAuth scopes that are required for authentication by default. You can optionally configure your integration to request additional OAuth scopes as needed.

When the **Return GitHub OAuth tokens** option is selected, the access token from GitHub will be included in the response from the [Authenticate with code API](/reference/authkit/authentication/code).

![A screenshot showing GitHub OAuth scopes configuration in the WorkOS Dashboard](https://images.workoscdn.com/images/9cfbd37c-f1cc-436d-8e61-0ccce2612bc6.png?auto=format&fit=clip&q=50)

Any scopes configured here will be included on every GitHub OAuth request. To specify additional scopes dynamically, use the `provider_scopes` query parameter on the [Get Authorization URL API endpoint](/reference/authkit/authentication/get-authorization-url).

For more information, see GitHub's OAuth scopes [documentation](https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps).

---

## Frequently asked questions

### How is the WorkOS GitHub OAuth integration different from implementing regular GitHub OAuth flow?

It's the same GitHub OAuth flow as you could build yourself, but it's encapsulated within WorkOS SSO. This means you don't need to build it yourself. In addition to GitHub OAuth, you can use WorkOS SSO to support other identity providers, all with a single integration.

### What is the provider query parameter and how is it used in the GitHub OAuth integration?

You can use the `provider` query parameter in the [Get Authorization URL API endpoint](/reference/sso/get-authorization-url) to support global GitHub OAuth for any domain. The `provider` query parameter should be set to `GitHubOAuth`.

### Fourth

Learn about syncing your user list with Fourth.

## Introduction

This guide outlines how to synchronize your application’s Fourth directories.

To synchronize an organization’s users and groups provisioned for your application, you’ll need the following information from the organization:

- Fourth Organization ID
- Fourth username and password

> Note: The Fourth integration isn't enabled by default in the WorkOS Dashboard or Admin Portal. Please reach out to [support@workos.com](mailto:support@workos.com) or via your team’s WorkOS Slack channel if you would like Fourth enabled.

---

## (1) Set up your directory sync integration

Sign in into your WorkOS Dashboard and select “Organizations” from the left hand navigation bar.

Select the organization you’ll be configuring a new Directory Sync connection with.

Click “Manually Configure Directory”.

![A screenshot showing where to find "Manually Configure Directory" button for an organization in the WorkOS dashboard.](https://images.workoscdn.com/images/0a0fa511-08ae-4fd9-9cfc-0301b7041b3f.png?auto=format&fit=clip&q=50)

Input the Name, and select "Fourth” as the directory type. Click the “Create Directory” button.

![A screenshot showing "Create Directory" details in the WorkOS dashboard.](https://images.workoscdn.com/images/ba13b740-7cbf-42e5-a511-b0c5a9f384e0.png?auto=format&fit=clip&q=50)

You will now see your Fourth directory sync has been created successfully with an input for the Organization ID, username, and password.

## (2) Obtain and update directory details

Retrieve the Fourth Organization ID from the organization's IT admin, as well as the username and password that will be used for authentication.

Click “Update Directory” in the WorkOS Dashboard.

![A screenshot showing where to find the "Update Directory" button in the WorkOS dashboard.](https://images.workoscdn.com/images/9c641325-3703-4c17-955e-d6b0fc898996.png?auto=format&fit=clip&q=50)

Enter the Organization ID, the username and the password.

---

## (3) View users and groups in your dashboard

When the connection is successfully made, you will see the green “Linked” icon appear. Now, whenever the organization assigns users or groups to your application, you’ll receive Dashboard updates based on changes in their directory.

Click on the “Users” tab in the Dashboard to view synced users.

![A screenshot showing where to find the "Users" tab in the WorkOS directory.](https://images.workoscdn.com/images/0784ded9-3fcd-45f1-87cc-44bb41e2031c.png?auto=format&fit=clip&q=50)

---

## Frequently asked questions

### How often do Fourth directories perform a sync?

Fourth directories poll every 30 minutes starting from the time of the initial sync.

### Firebase

Add Single Sign-On to your Firebase application with WorkOS.

## Introduction

In this guide, you’ll learn how to use WorkOS to add Single Sign-On (SSO) to a Firebase application. This will allow users to sign in to an existing Firebase application using WorkOS SSO Connections.

## What WorkOS provides

WorkOS will provide the following pieces of information: API key, Client ID, and the Issuer URL.

- The API key can be found in your WorkOS dashboard under **API Keys**.
- The Client ID can be found in your WorkOS dashboard under **Configuration**.
- The Issuer URL is constructed with the Client ID. `https://auth.workos.com/sso/`.

## What you’ll need

- An existing Firebase project

---

## (1) Configure Authentication for your Firebase project

Log into Firebase and navigate to your project. Click on the Authentication tile to set up a new Authentication method for your project.

![A screenshot showing where to find the Authentication tile in Firebase.](https://images.workoscdn.com/images/612ce59a-a1c8-4eb9-a209-9d0f6b6c5086.png?auto=format&fit=clip&q=50)

Next, click **Get started**.

![A screenshot showing where to find the Get started button in Firebase](https://images.workoscdn.com/images/bd877730-1e9a-487d-8938-10782c912d45.png?auto=format&fit=clip&q=50)

Click on the Sign-in method tab and then select the OpenID Connect custom provider.

![A screenshot showing where to find the OpenID Connect custom provider in Firebase](https://images.workoscdn.com/images/ee3fbc76-d94b-491e-842a-5f74eb4a2d62.png?auto=format&fit=clip&q=50)

Enter the configuration details for the connection between WorkOS and Firebase.

You will need the following pieces of information:

- **WorkOS Client ID**: Found on the **Configuration** tab of the WorkOS Dashboard
- **WorkOS API Key**: Located on the **API Keys** tab of the WorkOS Dashboard
- **Issuer (URL)**: This will be `https://auth.workos.com/sso/` appended with your client ID, ex: `https://auth.workos.com/sso/client_123`
- **Provider ID**: This is found in Firebase under the Name of your OIDC provider. This will be important for a later step.

![A screenshot showing the authentication provider configuration details in Firebase](https://images.workoscdn.com/images/5eb66fe3-8cad-4555-9417-ab38924d1288.png?auto=format&fit=clip&q=50)

---

## (2) Configure the Redirect URI in WorkOS

Click Next, then copy the **Callback URL** provided by Firebase.

![A screenshot showing where to obtain the Callback URL in Firebase.](https://images.workoscdn.com/images/a33d3b63-e6f9-4a43-8108-012f54d7c7db.png?auto=format&fit=clip&q=50)

Paste the Callback URL in the list of Redirect URI’s in the configuration tab of your WorkOS dashboard.

![A screenshot showing where to enter the Redirect URI in WorkOS.](https://images.workoscdn.com/images/c2c6ef52-e61e-41af-9c37-1e2187bf1744.png?auto=format&fit=clip&q=50)

---

## (3) Create a Firebase web app and get configuration details

On the Firebase Project Overview page, click the web icon above **Add an app to get started**, or navigate to your project settings page if your project is already set up.

![A screenshot showing where to create a web app in Firebase.](https://images.workoscdn.com/images/777e0c57-2c9d-4516-9e3e-985460ed38b6.png?auto=format&fit=clip&q=50)

Choose a name for your application, and then take note of the firebaseConfig from the Add Firebase SDK step.

![A screenshot showing where to obtain the firebaseConfig details in Firebase.](https://images.workoscdn.com/images/64b62bc6-4891-4627-9a2a-9440e0d27aa7.png?auto=format&fit=clip&q=50)

---

## (4) Configure Firebase login in your application

Your Firebase configuration and Provider ID can now be used along with any Organization ID from an Active WorkOS SSO connection to log users in to your Firebase app. Here is a basic example showing how this can be set up.

Replace the `firebaseConfig` variable value with the config from your Firebase app, the `OAuthProvider` value with your Provider ID, and the organization under `provider.setCustomParameters` with the organization to target. This organization should have an active SSO connection already set up.

> The `connection` parameter may be used in place of the `organization` parameter to target a connection.

Finally, run the app and click the sign-in button.



You will now see the user signed in on the Authentication section’s user tab in Firebase. You can also view the user information by decoding the access token which is logged to the console.

![A screenshot showing a successfully authenticated user in Firebase.](https://images.workoscdn.com/images/a4d521f9-3765-4d2d-909c-5340a462ba3e.png?auto=format&fit=clip&q=50)

### Entra ID SCIM (formerly Azure AD)

Learn about syncing your user list with Entra ID SCIM.

## Introduction

This guide outlines how to synchronize your application’s Entra ID directories using SCIM.

To synchronize an organization’s users and groups provisioned for your application, you’ll need to provide the organization with two pieces of information:

- An [Endpoint](/glossary/endpoint) that Entra ID will make requests to.
- A [Bearer Token](/glossary/bearer-token) for Entra ID to authenticate its endpoint requests.

Both of these are available in your Endpoint’s Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

> Steps 2, 3, and 4 below will need to be carried out by the organization admin when configuring your application in their Entra ID instance.

---

## (1) Set up your Directory Sync endpoint

Sign in to your WorkOS Dashboard and select “Organizations” from the left hand navigation bar.

Select the organization you’ll be configuring a new Directory Sync for.

Click “Add Directory”.

![A screenshot showing where to add a new directory in the WorkOS dashboard.](https://images.workoscdn.com/images/cf3a5ae2-4add-47ca-887e-d4d78c33d786.png?auto=format&fit=clip&q=50)

Select “Entra ID” from the dropdown, and enter the organization name.

Then, click “Create Directory.”

![A screenshot showing the "Create Directory" menu in the WorkOS dashboard.](https://images.workoscdn.com/images/6244ecf4-65a0-4421-b984-d513704ef882.png?auto=format&fit=clip&q=50)

> We have support for whitelabeled URLs for Directory Sync endpoints. [Contact us](mailto:support@workos.com) for more info!

Your Entra ID directory sync has now been created successfully with an Endpoint and Bearer Token.

![A screenshot showing the Azure SCIM endpoint and bearer token in the WorkOS dashboard.](https://images.workoscdn.com/images/38a98a55-96fa-403d-86f8-cfb313cd51e5.png?auto=format&fit=clip&q=50)

---

## (2) Select or create your Azure application

Sign in to the Entra ID Admin Center Dashboard. Select “Enterprise applications” from the list of Azure services.

![A screenshot showing where to select "Enterprise applications" in the Azure Active Directory Admin Center Dashboard](https://images.workoscdn.com/images/25d08d2e-48b8-49b0-b8e9-d57641606b57.png?auto=format&fit=clip&q=50)

If your application is already created, select it from the list of applications and move to Step 3.

![A screenshot showing where to select the application of choice in the All Applications menu in Azure.](https://images.workoscdn.com/images/7430b6b1-2d16-4df1-b11a-a51d51bc4725.png?auto=format&fit=clip&q=50)

If you haven’t created a SCIM application in Azure, select “New Application”.

![A screenshot showing where to select a new application in the All Applications menu in Azure.](https://images.workoscdn.com/images/8e9587aa-e259-4175-952c-bebe476457a2.png?auto=format&fit=clip&q=50)

Select “Create your own application” and continue.

![A screenshot showing where to select "Create your own application" in the All Applications menu in Azure.](https://images.workoscdn.com/images/ef501e51-ca06-47ef-a731-f509960fbf70.png?auto=format&fit=clip&q=50)

Give your application a descriptive name, and select the “Integrate any other application you don’t find in the gallery (Non-gallery)” option, then click “Create”.

![A screenshot showing where to configure the name of a new application in Azure.](https://images.workoscdn.com/images/cbd435b0-2313-4922-9fa3-87de57b39de8.png?auto=format&fit=clip&q=50)

---

## (3) Configure your integration

Select “Provisioning” from the “Manage” section found in the navigation menu.

![A screenshot showing where to select "Provisioning" from the "Manage" section in Azure.](https://images.workoscdn.com/images/39c18ede-837f-4735-8fa7-6cc3eb855776.png?auto=format&fit=clip&q=50)

Click the “Get Started” button.

![A screenshot showing where to select "Get Started" in the "Provisioning" menu in Azure.](https://images.workoscdn.com/images/e7d7e41f-1dec-4119-a3c4-fcc349a39eb5.png?auto=format&fit=clip&q=50)

Select the “Automatic” Provisioning Mode from the dropdown menu.

In the “Admin Credentials” section, copy and paste the Endpoint from your [WorkOS Dashboard](https://dashboard.workos.com/) in the “Tenant URL” field.

Then, copy and paste the Bearer Token from your [WorkOS Dashboard](https://dashboard.workos.com/) into the Secret Token field.

Click “Test Connection” to receive confirmation that your connection has been set up correctly. Then, select “Save” to persist the credentials.

![A screenshot showing where to configure the provisioning mode and credentials in Azure.](https://images.workoscdn.com/images/22d127dc-6834-4a84-b579-c7ae045cd339.png?auto=format&fit=clip&q=50)

---

## (4) Set and enable Attribute mappings

Expand the “Mappings” section.

![A screenshot showing where to expand "Mappings" in Azure.](https://images.workoscdn.com/images/f78bb399-3ab3-4822-a6bf-e8e96db93cdd.png?auto=format&fit=clip&q=50)

Make sure the group and user attribute mappings are enabled, and are mapping the correct fields. The default mapping should work, but your specific Azure setup may require you to add a custom mapping.

![A screenshot showing where to ensure User attribute mappings are enabled in Azure.](https://images.workoscdn.com/images/ab0daea3-dda3-4e3d-9199-9d30a710fdb2.png?auto=format&fit=clip&q=50)

Make sure that you are mapping `objectId` to `externalId` within the Attribute Mapping section.

![A screenshot showing where to ensure object ID is mapped to external ID in the Attribute Mapping section in Azure.](https://images.workoscdn.com/images/389cb8cc-9bfd-4f0b-b623-1304cf863c64.png?auto=format&fit=clip&q=50)

---

## (5) Assign users and groups to your application

In order for your users and groups to be synced, you will need to assign them to your Entra ID SCIM Application. Select “Users and groups” from the “Manage” section of the navigation menu.

![A screenshot showing where to navigate to "Users and groups" from the "Manage" section in Azure.](https://images.workoscdn.com/images/d4f01d7f-6dc4-46c6-a524-a6c5fe47cf7a.png?auto=format&fit=clip&q=50)

Select “Add user/group” from the top menu.

![A screenshot showing where to select "Add user/group" in the Users and groups menu in Azure.](https://images.workoscdn.com/images/68717808-6ca4-47ff-8bc0-690f3bfffe0e.png?auto=format&fit=clip&q=50)

Select “None selected” under the “Users and Groups”. In the menu, select the users and groups that you want to add to the SCIM application, and click “Select”.

![A screenshot showing where to select users for a SCIM application in Azure.](https://images.workoscdn.com/images/b6e2c4f6-ef9b-4881-8d9c-a23ae55a1490.png?auto=format&fit=clip&q=50)

Select “Assign” to add the selected users and groups to your SCIM application.

![A screenshot showing where to assign the selected users for the SCIM application in Azure.](https://images.workoscdn.com/images/e2f7221f-9789-4288-bd66-5450d150db0b.png?auto=format&fit=clip&q=50)

---

## (6) Turn on provisioning for your SCIM application

In the Provisioning menu, confirm the “Provisioning Status” is set to “On” and that the “Scope” is set to “Sync only assigned users and groups”.

![A screenshot showing where to ensure that the "Provisioning Status" is "On" and "Scope" is set to "Sync only assigned users and groups" in Azure.](https://images.workoscdn.com/images/67041f59-27dc-4026-b6a2-c43568c59dfd.png?auto=format&fit=clip&q=50)

Begin provisioning users and groups and witness realtime changes in your [WorkOS Dashboard](https://dashboard.workos.com/).

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

---

## Configuring user attribute mappings

For any non-standard attributes used by the application, some configuration may be required in Microsoft Entra. Below is a guide on configuring user attribute mappings, so they propagate via SCIM.

### (1) Viewing application attributes

From your Microsoft Entra SCIM application, navigate to the Manage → Provisioning page. Expand the Mappings section and click "Provision Microsoft Entra ID Users".

![Microsoft Entra enterprise application provisioning tab](https://images.workoscdn.com/images/cb7b0eb7-8ff7-452e-b3c5-14eede22c4da.png?auto=format&fit=clip&q=50)

This will display a list of attribute mappings and settings:

![Microsoft Entra attribute mapping settings](https://images.workoscdn.com/images/472657ed-812c-4f3a-b57d-601e573adf48.png?auto=format&fit=clip&q=50)

### (2) Adding or editing an attribute

To add a missing attribute, click the "Add New Mapping" button at the bottom left of the mappings list. To edit an existing attribute, click the "Edit" button next to the existing attribute you'd like to edit.

![Microsoft Entra add new mapping button](https://images.workoscdn.com/images/2319dab9-6392-4a7f-9988-fe8cf5260301.png?auto=format&fit=clip&q=50)

To configure the mapping, select the source and target attribute from the dropdowns, and ensure "Apply this mapping" is set to "Always".

For example, to map division, the source attribute has been selected as `employeeOrgData.division` and the target attribute has been selected as `urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:division`.

![Microsoft Entra configure mapping dialog](https://images.workoscdn.com/images/984c0ffe-0d18-4f04-a69b-d4e09b4a51d3.png?auto=format&fit=clip&q=50)

These new attribute mappings will now propagate to your application when the next SCIM push occurs.

---

## Provisioning on demand

By default, Entra ID SCIM 2.0 directories sync changes on a scheduled time interval, typically every 40 minutes. For use cases where more immediate provisioning or deprovisioning of users, groups, or group memberships is needed, Entra ID provides [provisioning on demand](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/provision-on-demand?pivots=app-provisioning).

To provision on demand, from the enterprise application navigate to the "Provisioning" tab and click "Provision on demand".

![Entra ID provision on demand button](https://images.workoscdn.com/images/de50df7b-4088-4e95-a711-ad04e43474c5.png?auto=format&fit=clip&q=50)

To provision a user, select the user from the dropdown and click "Provision".

![Entra ID provision user on demand](https://images.workoscdn.com/images/121aaa24-d160-40a4-824f-44cc2a5ff84d.png?auto=format&fit=clip&q=50)

To provision a group or group membership, select the group from the dropdown, and select "View members only". Then select the group memberships to provision and click "Provision".

![Entra ID provision group memberships on demand](https://images.workoscdn.com/images/34167704-985a-4b0b-b110-89e19d618b37.png?auto=format&fit=clip&q=50)

Upon clicking "Provision", SCIM requests will immediately be sent to the application. To deprovision a user, group, or group membership, remove it from the Entra application and follow the above provisioning on demand steps.

---

## Frequently asked questions

### No email addresses are coming through for users from Entra. How do I get emails for my Entra users?

For cloud-managed users, Entra ID pulls the email from the `mail` attribute in Exchange. If your customer doesn’t have this set up, they will need to configure attribute mapping in their SCIM app in Entra in order to provision users with WorkOS. They can use [this tutorial from Microsoft](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/customize-application-attributes). They’ll want to map a known email attribute, such as UPN, to the `emails[type eq “work”].value` SCIM attribute. For directories with synchronized-users, they will need to map the `userPrincipalName` attribute into the `emails[type eq “work”].value` SCIM attribute.

### Sometimes, reactivating "suspended" users does not re-add them to their Entra groups. Why is that and how can I fix it?

When a user is deleted from the entire directory, instead of only being deprovisioned from the SCIM app, the user may be soft-deleted (their state is set as "suspended"). Reactivating these suspended users will not send SCIM requests to re-add the user to the groups. To do so, the IT admin will need to select the "Restart Provisioning" button for the SCIM app in Azure.

![A screenshot showing where to restart provisioning in Entra.](https://images.workoscdn.com/images/757f8920-da4b-46ac-90b0-9780b150eb62.png?auto=format&fit=clip&q=50)

### Can profile images be accessed with Entra ID SCIM?

Entra ID's SCIM provisioning does not support transmitting image.

### Why do I receive a `dsync.user.updated` event after `dsync.user.created`?

Entra ID sends a newly provisioned user over to WorkOS in two separate actions. WorkOS will then send these actions as two individual events to your app. This is expected behavior.

### How often do Entra ID SCIM 2.0 directories perform a sync?

By default, Entra ID SCIM 2.0 directories sync changes on a scheduled time interval, typically every 40 minutes. For more details, please refer to Entra ID's [official documentation](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/application-provisioning-when-will-provisioning-finish-specific-user#how-long-will-it-take-to-provision-users).

[Provisioning on demand](/integrations/entra-id-scim/provisioning-on-demand) is also available, which can sync select users, groups, or group memberships in real-time.

### What is the `idp_id` for directory groups from Entra ID?

Entra ID provides a unique object identifier for each group through the SCIM `externalId` field. This is persisted as the `idp_id` for [directory groups](/reference/directory-sync/directory-group) in WorkOS.

### Entra ID SAML (formerly Azure AD)

Learn how to configure a connection to Entra ID via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). And often, the information required to create a Connection will differ by Identity Provider.

To create an Entra ID SAML Connection, you’ll need the Identity Provider Metadata URL that is available from the organization's Entra ID instance.

---

## What WorkOS Provides

WorkOS provides the [ACS URL](/glossary/acs-url) and [IdP URI (Entity ID)](/glossary/idp-uri-entity-id). It’s readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/get-started).

![A screenshot showing the ACS URL and Entity ID in the WorkOS dashboard.](https://images.workoscdn.com/images/736aee3b-9a67-4abd-9905-f091d20fe48e.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. In Entra ID’s case, it needs to be set by the organization when configuring your application in their Entra ID instance.

Specifically, the ACS URL will need to be set as the “Reply URL (Assertion Consumer Service URL)” in the “Basic SAML Configuration” step of the Entra ID “Set up Single Sign-On with SAML” wizard:

![A screenshot showing the location to place the WorkOS ACS URL in the Azure Dashboard.](https://images.workoscdn.com/images/ea398d8e-71a8-4f54-9b85-3c092f325bf8.png?auto=format&fit=clip&q=50)

The [Entity ID](/glossary/idp-uri-entity-id) is a URI used to identify the issuer of a SAML request, response, or assertion. In this case, the entity ID is used to communicate that WorkOS will be the party performing SAML requests to the organization's Entra ID instance.

Specifically, the Entity ID will need to be set as the “Identifier (Entity ID)” in the “Basic SAML Configuration” step of the Entra ID “Set up Single Sign-On with SAML” wizard:

![A screenshot showing the location to place the WorkOS Entity ID in the Azure Dashboard.](https://images.workoscdn.com/images/55860959-b322-4098-b3d4-66d48ee73dd1.png?auto=format&fit=clip&q=50)

---

## What you’ll need

In order to integrate you’ll need the Entra ID IdP Metadata URL.

Normally, this information will come from the organization's IT Management team when they set up your application’s SAML 2.0 configuration in their Azure admin dashboard. Here’s how to obtain them:

---

## (1) Log in

Log in to the [Entra ID Active Directory Admin dashboard](https://portal.azure.com/). Select “Enterprise Applications” from the list of Azure services.

![A screenshot showing where to select "Enterprise Applications" in the Azure dashboard.](https://images.workoscdn.com/images/37f3b3d2-fcdb-4a5f-8d93-970ec0239446.png?auto=format&fit=clip&q=50)

---

## (2) Select or create your application

If your application is already created, select it from the list of Enterprise applications and move to Step 7.

![A screenshot showing where to select an existing application in the Azure dashboard.](https://images.workoscdn.com/images/a61ca1b9-4e06-4dc6-80de-eac3fea212cd.png?auto=format&fit=clip&q=50)

If you haven’t created a SAML Application in Azure, select “New Application”.

![A screenshot showing where to select "New Application" in the Azure dashboard.](https://images.workoscdn.com/images/3c26fec7-f77a-4757-8a04-6998ff7beb26.png?auto=format&fit=clip&q=50)

---

## (3) Initial SAML Application Setup

Select “Create your own application”, then enter a descriptive app name. Under “What are you looking to do with your application?”, select “Integrate any other application you don’t find in the gallery (Non-gallery)”, then select “Create”.

![A screenshot showing where to input the name of the new application in the Azure dashboard.](https://images.workoscdn.com/images/9f998b1b-87b4-4f1d-a50c-0a17f8bb3f98.png?auto=format&fit=clip&q=50)

Select “Single Sign-On” from the “Manage” section in the left sidebar navigation menu, and then “SAML”.

![A screenshot showing how to select "SAML" as the Single Sign-On method of the Azure application in the Azure dashboard.](https://images.workoscdn.com/images/f90c0d1a-ed45-4bee-b77f-dcf37a63a6bd.png?auto=format&fit=clip&q=50)

---

## (4) Configure SAML Application

Click the Edit icon in the top right corner of the first step "Basic SAML Configuration".

![A screenshot showing where to select "Edit" for the "Basic SAML Configuration" step in the Azure dashboard.](https://images.workoscdn.com/images/e7a4397c-8120-43c6-9b66-e6a2251cd5bd.png?auto=format&fit=clip&q=50)

Input the IdP URI (Entity ID) from your WorkOS Dashboard as the “Identifier (Entity ID)”. Input the ACS URL from your WorkOS Dashboard as the “Reply URL (Assertion Consumer Service URL)”.

![A screenshot showing where to input the WorkOS ACS URL and WorkOS Entity ID in the Azure dashboard.](https://images.workoscdn.com/images/8bf326a6-f394-4894-9630-d86cdf9b574f.png?auto=format&fit=clip&q=50)

---

## (5) Configure User Attributes and Claims

Click the Edit icon in the top right corner of the second step "Attributes & Claims".

![A screenshot showing where to select "Edit" for the "Attributes & Claims" step in the Azure dashboard.](https://images.workoscdn.com/images/6155597f-a4b8-4a3c-a7f3-a6e8d4e0865d.png?auto=format&fit=clip&q=50)

Make sure the following attribute mapping is set:

- `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress` → `user.mail`
- `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname` → `user.givenname`
- `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name` → `user.userprincipalname`
- `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname` → `user.surname`

Below is an example of how to format your claim within the Azure claim editor. Make sure the 'Namespace' value ends in `/claims`.

![A screenshot showing the "Manage Claim" configuration in the Azure dashboard.](https://images.workoscdn.com/images/93ec5d1b-9ecd-49f5-8d2a-a718b5ea58b2.png?auto=format&fit=clip&q=50)

![A screenshot showing the "Attribute & Claims" configuration in the Azure dashboard.](https://images.workoscdn.com/images/f41b5a7c-1842-4567-9f46-85caa7309176.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, follow the guidance below.

Select "Add a group claim" from the top menu. Next, select which groups you'd like to return in the Group Claims settings. For example, in Entra ID, you could select "Groups assigned to the application" to only send groups assigned to the SAML app. Finally, select "Save" once finished configuring the groups.

![A screenshot showing how to add a groups claim to your SAML app in the Azure dashboard.](https://images.workoscdn.com/images/4e33755c-945f-4164-873f-33482e3a2c43.png?auto=format&fit=clip&q=50)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (6) Add Users to SAML Application

In order for your users or groups of users to be authenticated, you will need to assign them to your Entra ID SAML application. Select “Users and groups” from the “Manage” section of the navigation menu.

![A screenshot showing where to select "Users and groups" in the Azure dashboard.](https://images.workoscdn.com/images/7fe69c75-311e-409b-905a-dbd6b6087394.png?auto=format&fit=clip&q=50)

Select “Add user/group” from the top menu.

![A screenshot showing where to select "Add user/group" in the Azure dashboard.](https://images.workoscdn.com/images/817e4d3d-7470-4e20-b9f1-af74ea8adc73.png?auto=format&fit=clip&q=50)

Select “None selected” under the “Users and Groups”. In the menu, select the users and groups of users that you want to add to the SAML application, and click “Select”.

![A screenshot showing where to select "None Selected" under "Users and Groups" and add a user in the Azure dashboard.](https://images.workoscdn.com/images/85f005d7-3655-46ac-9554-77fda2c44747.png?auto=format&fit=clip&q=50)

Select “Assign” to add the selected users and groups of users to your SAML application.

![A screenshot showing where to select "Assign" in the Azure dashboard.](https://images.workoscdn.com/images/5420b145-6086-4141-b096-9ae9f6ea8529.png?auto=format&fit=clip&q=50)

---

## (7) Obtain Identity Provider Details

Select “Single Sign-On” from the “Manage” section in the left sidebar navigation menu.

Navigate down to Section 3 of the “Single Sign-On” page, to “SAML Signing Certificate”. Copy the URL provided in “App Federation Metadata URL”.

![A screenshot showing where to select the "App Federation Metadata URL" in the Azure dashboard.](https://images.workoscdn.com/images/c4ee0b27-ddd7-4aab-96c0-ced1019b4cd7.png?auto=format&fit=clip&q=50)

Next, within your connection settings under "Identity Provider Configuration", select "Edit Metadata Configuration" and enter the Azure metadata URL.

![A screenshot showing where to select "Edit Metadata Configuration" on the "SSO Connection" page in the WorkOS dashboard.](https://images.workoscdn.com/images/2ad55b55-e44f-48a6-93db-8699dcd98af6.png?auto=format&fit=clip&q=50)

Your Connection will then be verified and good to go!

![A screenshot showing an active Azure SAML connection in the WorkOS dashboard.](https://images.workoscdn.com/images/2116ac59-3868-4c55-aa3d-43cdefd01f1f.png?auto=format&fit=clip&q=50)

### Entra ID OIDC (formerly Azure AD)

Learn how to configure a connection to Entra ID via OIDC.

## Introduction

Each SSO identity provider requires specific information to create and configure a new [SSO connection](/glossary/connection). Often, the information required to create an SSO connection will differ by identity provider.

To create an Entra ID OIDC SSO connection, you'll need four pieces of information: a [redirect URI](/glossary/redirect-uri), [application (client) ID](/glossary/client-id), [client secret](/glossary/client-secret) and [discovery endpoint](/glossary/discovery-endpoint).

Start by logging in to your WorkOS dashboard and navigate to the **Organizations** page from the left-hand navigation bar.

Select the organization you'd like to configure an Entra ID OIDC SSO connection for, and select **Configure manually** under **Single Sign-On**.

![WorkOS Dashboard Organizations tab with "Configure manually" button highlighted](https://images.workoscdn.com/images/d577cfbe-028b-48cf-8cc0-4cd5d3adf853.png?auto=format&fit=clip&q=50)

Select **Entra ID (Azure AD) OIDC** from the identity provider dropdown, enter a descriptive name for the connection, click **Create Connection**.

![Create Connection form with Entra ID (Azure AD) OIDC selected as Identity Provider](https://images.workoscdn.com/images/90fe747d-88e3-40da-a028-161132401a5c.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

WorkOS provides the Redirect URI, which can be found in the **Service Provider Details** section on the SSO connection page in the [WorkOS Dashboard](https://dashboard.workos.com/).

- [Redirect URI](/glossary/redirect-uri): The endpoint where identity providers send authentication responses after successful login

![The Redirect URI of a OIDC connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/99a7c7d5-50a9-4bff-a3f3-22dc1cfeca58.png?auto=format&fit=clip&q=50)

The Redirect URI is the location an identity provider redirects its authentication response to. In Entra ID’s case, it needs to be set during application registration when configuring your OIDC application, which is outlined in [step 1](/integrations/entra-id-oidc/1-register-an-application) below.

---

## What you’ll need

You will need to obtain three pieces of information from the organization:

- [Application (Client) ID](/glossary/client-id): Application identifier from the OIDC provider
- [Client Secret](/glossary/client-secret): Authentication secret for the application
- [Discovery endpoint](/glossary/discovery-endpoint): Configuration URL containing OIDC metadata

Normally, this information will come from the organization’s IT Management team when they set up your application’s OIDC configuration in their Entra ID admin center. But, should that not be the case during your setup, the next steps will show you how to obtain it.

---

## (1) Register an application

Sign in to the [Microsoft Entra admin center](https://entra.microsoft.com/).

In the left navigation menu, expand the **Identity** section. Expand the **Applications** sub-section. Select the **App registrations** tab. Click **New registration**.

![Microsoft Entra admin center navigation showing Identity > Applications > App registrations](https://images.workoscdn.com/images/67c07f6f-f60d-48da-b950-eac73d094dfb.png?auto=format&fit=clip&q=50)

Enter an appropriate app name, such as your organization or application name.

Select one of these **Supported account types**:

- Accounts in this organizational directory only (Default Directory only - Single tenant) (Default)
- Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant)

In the **Redirect URI** field, select the **Web** option from the dropdown menu. Copy the [Redirect URI](/integrations/entra-id-oidc/what-workos-provides) from the SSO connection page in the WorkOS Dashboard and paste it into the input field.

![App registration form with name, supported account types, and redirect URI fields](https://images.workoscdn.com/images/d09699ac-00d4-4a8f-9ff7-9090c79d805b.png?auto=format&fit=clip&q=50)

Click **Register**.

---

## (2) Obtain required configuration details

Now you'll need to gather three pieces of information from your Entra ID application that will be configured in your WorkOS dashboard: the client ID, client secret, and discovery endpoint. Keep these values handy to input into the WorkOS Dashboard.

### Get the client ID

From the application **Overview** page, copy the **Application (client) ID**.

![Entra ID application Overview page showing Application (client) ID field](https://images.workoscdn.com/images/70506649-66e4-490a-82b0-69175d0f3381.png?auto=format&fit=clip&q=50)

### Create and retrieve the client secret

Navigate to the **Certificates & secrets** page. Click **New client secret**.

![Certificates & secrets page with "New client secret" button](https://images.workoscdn.com/images/28afb31c-3e94-4263-aedb-9924e0a4678d.png?auto=format&fit=clip&q=50)

Enter an appropriate secret description and select an expiration period. Click **Add**.

![Add a client secret panel with the description, expires at fields highlighted](https://images.workoscdn.com/images/6d72665b-7ad0-4837-ac58-b9acbe2d7fee.png?auto=format&fit=clip&q=50)

Copy the newly created client secret **Value** immediately as it will not be shown again after you navigate away from this page.

![Client secret creation form with description field and generated secret value](https://images.workoscdn.com/images/7e1604a5-1bdb-4a0c-80d5-8b4401c4269e.png?auto=format&fit=clip&q=50)

### Get the discovery endpoint

From the application **Overview** page, click the **Endpoints** tab.

![Entra ID application Overview page with Endpoints tab highlighted](https://images.workoscdn.com/images/70fee14e-bb7d-43ab-8bb8-70150af299b6.png?auto=format&fit=clip&q=50)

Scroll down to find and copy the **OpenID Connect metadata document** URL. This is your Discovery Endpoint.

![Endpoints list showing OpenID Connect metadata document URL](https://images.workoscdn.com/images/aca9c724-2a6f-4449-b435-f63bd538d60f.png?auto=format&fit=clip&q=50)

### Update the SSO connection settings

Back in the WorkOS Dashboard on the SSO connection page, enter the client ID, client secret, and discovery endpoint you obtained from Entra ID into the respective fields in the **\{SSO connection name\} Settings** section.

![WorkOS Dashboard Identity Provider Configuration with Client ID, Client Secret, and Discovery Endpoint fields](https://images.workoscdn.com/images/714cb015-94db-4080-ad53-942da1804c01.png?auto=format&fit=clip&q=50)

Click **Update connection** to save.

---

## (3) Configure token claims

Navigate to the **Token configuration** page. Click **Add optional claim**.

![Token configuration page with "Add optional claim" button](https://images.workoscdn.com/images/c71dc730-995d-48d3-a5eb-3b28166fa6c0.png?auto=format&fit=clip&q=50)

Select **ID** token type, and then select the following claims:

- `email`
- `family_name`
- `given_name`

![Optional claims dialog with ID token type selected and email, family_name, given_name claims](https://images.workoscdn.com/images/0cfa531a-de60-4ead-9655-0a473dbd5658.png?auto=format&fit=clip&q=50)

Click **Add**. In the pop-up, select **Turn on the Microsoft Graph email, profile permission**, then click **Add**.

![Add optional claim panel with turn on Microsoft Graph checkbox highlighted](https://images.workoscdn.com/images/644ac9db-6bb6-4ca5-bd65-af23ceec5b6a.png?auto=format&fit=clip&q=50)

---

## (4) Assign users and groups

In the left navigation menu, expand the **Identity** section. Expand the **Applications** sub-section. Select the **Enterprise applications** tab.

Search for your application by name and select it.

![Enterprise applications search interface with application list](https://images.workoscdn.com/images/7ca10480-3bc6-4d1e-99cd-7de8543e374d.png?auto=format&fit=clip&q=50)

From the Enterprise application page, select the **Users and groups** tab. Click **Add user/group**.

![Enterprise application Users and groups tab with "Add user/group" button](https://images.workoscdn.com/images/15448828-6288-4350-9ac3-27c9997f04e4.png?auto=format&fit=clip&q=50)

Select appropriate users and groups to add to the OIDC application.

![User and group assignment interface with selection options and Assign button](https://images.workoscdn.com/images/e3964bfc-92b2-497d-b291-098cbe1ee94f.png?auto=format&fit=clip&q=50)

When finished, click **Assign** to add the selected users to your OIDC application.

![Add assignment page with Assign button highlighted](https://images.workoscdn.com/images/80e136c6-6e9f-41f4-aed9-85421746906b.png?auto=format&fit=clip&q=50)

---

## (5) Role assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. Users will automatically be granted the assigned roles within your application when they authenticate. To enable this functionality:

### Configure groups claim in Entra ID

From the app registration, navigate to the **Token configuration** page. Click **Add groups claim**.

![Token configuration page with "Add groups claim" button](https://images.workoscdn.com/images/d6342c8f-1f32-43c3-a91e-16cacdd62b31.png?auto=format&fit=clip&q=50)

In the **Group Claims** panel, select appropriate groups. For example, you could select **Groups assigned to the application** to only send groups assigned to the OIDC app in Entra ID. Click **Add**.

![Group Claims configuration panel with group selection options](https://images.workoscdn.com/images/5cf70ad4-6eb3-4f6e-87c6-16b15c1c781f.png?auto=format&fit=clip&q=50)

### Configure role assignment in WorkOS

From the SSO connection page in the [WorkOS Dashboard](https://dashboard.workos.com/), scroll to the **Groups and role assignments** section.

![WorkOS dashboard highlighting create group button](https://images.workoscdn.com/images/c29ef1a7-d873-49f6-ad43-8c945245a033.png?auto=format&fit=clip&q=50)

For each group you want to assign a role, click the **Create group** button and enter the following:

1. Copy the group id from Entra ID into the **IdP ID** field.
2. Optionally, enter a group name into the **Name** field.
3. Assign the appropriate role to the group.

![WorkOS dashboard with open create group dialog and idp_id, name, and role assignment inputs](https://images.workoscdn.com/images/d542c8c3-e032-41a6-ae72-c8dc586ec88d.png?auto=format&fit=clip&q=50)

> Group members without an explicit role will receive the default role.

---

## Next steps

Your Entra ID OIDC connection is now configured and ready to use. Users assigned to the application in Entra ID will be able to authenticate through WorkOS using their Microsoft credentials.

To start using this connection in your application, refer to the [SSO guide](/sso) for implementation details.

### Duo

Learn how to configure a connection to Duo via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a Duo SAML Connection, you’ll need three pieces of information: an [ACS URL](/glossary/acs-url) (provide by WorkOS), an [SP Entity ID](/glossary/sp-entity-id) (provided by WorkOS), and the [Metadata URL](/glossary/idp-metadata) (provided by Duo).

Duo is also unique in that it requires a 3rd party IdP to federate the authentication. This means that along with the three pieces of information, you’ll also need to configure a Single Sign-On Authentication Source and a Cloud Application in your Duo Workspace.

The high level overview of the authentication flow:

Your App → WorkOS → Duo → Your SSO IdP → Duo → WorkOS → Your App

![A flowchart showing the authentication flow of Duo using WorkOS.](https://images.workoscdn.com/docs/integrations/sso/duo-saml/v1/duo-saml-1.png?auto=format&fit=clip&q=50)

---

## (1) Create a new Duo SAML Connection in WorkOS

Navigate to the Organization in your WorkOS Dashboard under which you would like to set up this new SSO Connection. Click “Manually Configure Connection” and select Duo SAML from the list of SSO Identity Providers. You’ll want to select “Duo SAML” as the Identity Provider and give the Connection a descriptive name. Once this is filled out, click “Create Connection”.

![A screenshot showing how to create a Duo SAML connection in the WorkOS dashboard.](https://images.workoscdn.com/images/cfd42823-38c8-4994-b05c-b7c3609d1755.png?auto=format&fit=clip&q=50)

Take note of the Connection Details as you’ll need to enter those in Duo later on. This page is also where you’ll enter the Metadata URL in a later step.

![A screenshot showing where to access Service Provider details in the connection settings.](https://images.workoscdn.com/images/98f72b30-9e6b-4e96-be86-176939471b6b.png?auto=format&fit=clip&q=50)

---

## (2) Select or create your application

WorkOS will allow you to use any Duo supported IdP to handle the Federated authentication. Since each IdP will have different ways of setting up the SSO connection between Duo and the IdP, please refer to the [documentation that Duo provides to configure a Duo SSO Connection](https://duo.com/docs/sso#enable-duo-single-sign-on).

---

## (3) Create a Cloud Application in Duo

After configuring the Duo SSO Connection with the IdP of your choice, the next step is to create a Cloud Application in Duo. This app will handle the connection between WorkOS and Duo.

Navigate to the Duo Admin Panel and click on Applications on the left sidebar.

Click “Protect an Application” and locate the entry for “Generic SAML Service Provider” with a protection type of “2FA with SSO hosted by Duo (Single Sign-On)” in the applications list. Click _Protect_ to the far-right to start configuring “Generic SAML Service Provider”.

![A screenshot showing how to create a Cloud App in Duo.](https://images.workoscdn.com/images/8404f0a8-a56f-4c58-b03e-d0ec48ef66b8.png?auto=format&fit=clip&q=50)

Next, configure the Generic Service Provider settings. There are pieces of information on this page that need to come from WorkOS and your Duo SSO Connection, and also information to copy and enter in the WorkOS Connection.

Start by gathering the Metadata URL to enter in the WorkOS Duo SAML Connection that you created in the prior step.

![A screenshot showing where to copy the IdP Metadata URL in Duo.](https://images.workoscdn.com/images/250ed44e-4044-441e-ab02-a045ed011cb2.png?auto=format&fit=clip&q=50)

---

## (4) Enter Duo SAML Settings in your WorkOS Dashboard

Navigate to your WorkOS Duo SAML Connection and paste the Metadata URL in to the Metadata field.

You won’t see the connection flip to Active yet as there is still some configuration to do on the Duo side.

![A screenshot showing how to add the IdP metadata in the WorkOS dashboard.](https://images.workoscdn.com/images/73a827e1-fa4f-4399-a1e6-3589abd0874a.png?auto=format&fit=clip&q=50)

From the WorkOS Connection page you are currently on, copy the ACS URL value from the field just above the SAML Settings.

![A screenshot highlighting the ACS URL in the WorkOS dashboard.](https://images.workoscdn.com/images/45ce0799-449b-417e-8f2b-08cdaacdfea6.png?auto=format&fit=clip&q=50)

Navigate to the Duo Applications Generic Service Provider configuration settings and paste the ACS URL in the Assertion Consumer Service (ACS) URL field under the Service Provider section.

![A screenshot showing where to input the ACS URL in Duo settings.](https://images.workoscdn.com/images/d7bff970-44e9-4320-b675-53d54d2ab4c9.png?auto=format&fit=clip&q=50)

Next, copy the SP Entity ID value from the WorkOS Connection page.

![A screenshot highlighting the Entity ID in the WorkOS dashboard.](https://images.workoscdn.com/images/5dfd097f-1027-48af-9cdc-6ad2fd97f3d3.png?auto=format&fit=clip&q=50)

Paste the SP Entity ID into the Entity ID field under the Service Provider section in the Duo Applications Generic Service Provider configuration.

You may leave the Single Logout URL, Service Provider Login URL, and Default Relay State fields empty.

![A screenshot showing where to input the Entity ID in Duo settings.](https://images.workoscdn.com/images/5938b3ee-95a7-4dcf-aa2a-9e064d8c8311.png?auto=format&fit=clip&q=50)

Scroll down on this page to the SAML Response section. Ensure that the NameID format has the id that you’d like to use for the unique identifier selected and matches the NameID attribute that you’d like to use as the value. If you’re using email as the unique ID, the options would look like the below.

![A screenshot showing how to configure SAML Response NameID in Duo.](https://images.workoscdn.com/images/e2ae9786-2a3f-4408-9c15-b33ba4c34f39.png?auto=format&fit=clip&q=50)

Ensure the Signature algorithm is SHA256 and that the Signing options have both Sign response and Sign assertion selected.

![A screenshot showing where to configure the SAML Response Signing.](https://images.workoscdn.com/images/c491cab0-5abe-4b63-89cc-c5b8dbed9657.png?auto=format&fit=clip&q=50)

Next make sure that you are mapping the attributes which WorkOS requires: `id`, `email`, `firstName`, and `lastName`. In the Map Attributes section enter these on the right side under SAML Response Attribute. on the left side, click the empty field box and select the pre-populated values that look like ``. Duo will automatically grab the corresponding fields and map them to the expected values.

You can map any values you like, but WorkOS requires that these four values are included in SAML responses. If your users don’t have a last name value for instance, you could map Display Name or any other value to `lastName`, but `lastName` still needs to be included or WorkOS will reject the SAML Response.

Here’s an example of the attribute mappings:

![A screenshot showing where to configure SAML Attribute Mapping in Duo.](https://images.workoscdn.com/images/dc4517d1-7f02-4199-a06e-e3d31ac56b76.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, follow the guidance below.

In the "Role Attributes" section, enter `groups` as the "Attribute name". Then map the role names to their corresponding Duo groups. In the example below, the "Admins" role is mapped to the Admins group and the "Developers" role is mapped to the Developers group.

![A screenshot showing how to configure a groups attribute in Duo.](https://images.workoscdn.com/images/a13b9af3-65fc-4595-acd6-ecc3bc026fc3.png?auto=format&fit=clip&q=50)

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

### Save your changes

You may leave all of the other fields as their defaults. Scroll to the very bottom of the page and click the Save button.

![A screenshot highlighting the finished SAML Configuration in Duo.](https://images.workoscdn.com/images/dbe959a3-41eb-4dca-b1bd-69f1a389b10e.png?auto=format&fit=clip&q=50)

---

## (5) Verify Connection Status in WorkOS

Navigate back to the WorkOS dashboard. After a minute or two you should see the Connection become Active as indicated by the green badge next to the connection name.

![A screenshot highlighting active status of the Duo connection.](https://images.workoscdn.com/images/9d79fcfe-386d-4bd7-a69d-e8e0578f0352.png?auto=format&fit=clip&q=50)

### CyberArk SCIM

Learn about syncing your user list with CyberArk SCIM.

## Introduction

This guide outlines how to synchronize your application’s CyberArk directories using SCIM.

To synchronize an organization’s users and groups provisioned for your application, you’ll need to provide the organization with two pieces of information:

- An [Endpoint](/glossary/endpoint) that CyberArk will make requests to.
- A [Bearer Token](/glossary/bearer-token) for CyberArk to authenticate its endpoint requests.

After completing step 1 below, both of these are available in your Endpoint’s Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

> The rest of the steps below will need to be carried out by the organization when configuring your application in their CyberArk instance.

---

## (1) Set up your directory in the WorkOS Dashboard

In your WorkOS Dashboard, select or create an Organization. Then select “Manually Configure Directory”.

![A screenshot showing where to select "Manually Configure Directory" in the WorkOS dashboard.](https://images.workoscdn.com/images/2865e608-6524-4bd6-8f35-070de0d6cf2b.png?auto=format&fit=clip&q=50)

Select “CyberArk” as the Directory Provider and add a descriptive name for the directory sync connection.

![A screenshot showing the proper configuration of the "Create Directory" modal in the WorkOS dashboard.](https://images.workoscdn.com/images/ea86a861-c18c-4d8b-ad92-5942f11a98c7.png?auto=format&fit=clip&q=50)

On the Directory Sync connection settings page, save the Endpoint and the Bearer Token. You’ll input these in the CyberArk settings.

![A screenshot showing the Endpoint and Bearer Token in the WorkOS dashboard.](https://images.workoscdn.com/images/f77f41f5-8641-4452-b933-3a2d3f2351c5.png?auto=format&fit=clip&q=50)

> We have support for whitelabeled URLs for Directory Sync endpoints. [Contact us](mailto:support@workos.com) for more info!

---

## (2) Select or create your CyberArk application

CyberArk supports SCIM provisioning in the context of a SAML app. The usual set up is to enable SAML first, following [our docs here](/integrations/cyberark-saml).

Log in to the CyberArk Admin Portal, and navigate to your SAML app. Open the “Provisioning” tab, and select the box to “Enable provisioning for this application”.

![A screenshot showing where to enable the "Enable provisioning for this application" setting in the CyberArk dashboard.](https://images.workoscdn.com/images/83b18d01-90d6-4cf2-8866-84c2046cd1f5.png?auto=format&fit=clip&q=50)

Click “Yes” in the confirmation modal.

![A screenshot showing where to select "Yes" in the confirmation modal in the CyberArk dashboard.](https://images.workoscdn.com/images/38f35897-4fb6-47d0-9445-53b0405b8809.png)

Enter the Endpoint from the WorkOS Dashboard into the "SCIM Service URL" field, and enter the Bearer Token from the WorkOS Dashboard into the corresponding field in the Provisioning tab. Select “Verify” to save these credentials.

![A screenshot showing where to input the WorkOS Endpoint as the "SCIM Service URL" and the Bearer Token in the CyberArk dashboard.](https://images.workoscdn.com/images/2bee64a8-cbb8-4d31-9f35-4f2bb3c237bd.png)

Once the credentials have been verified, more options will be appear below. Deselect "Do not de-provision (deactivate or delete) users in target application" as seen below.

![A screenshot showing which checkboxes to disable in the CyberArk dashboard.](https://images.workoscdn.com/images/f8e6980a-76f7-4cf5-a5c5-958dae8268ba.png)

---

## (3) Configure your role mappings in CyberArk

Users assigned to the SAML app will be synced, and roles mapped will be synced as groups. The roles are mapped on the Provisioning settings page, by selecting the “Add” button.

![A screenshot showing where to select “Add” in the CyberArk dashboard.](https://images.workoscdn.com/images/8a6039da-ccc0-493d-9888-40337e70da74.png)

In the role mapping modal, select the role you’d like to map, and then create a destination group. The name will be what you see as the group name in directory sync. All users assigned to that role will be members of the mapped group. Select “Done”.

![A screenshot showing how to configure the "Role" and "Destination Group" settings in the "Role Mapping" modal of the CyberArk dashboard.](https://images.workoscdn.com/images/34f5f6cf-5011-4540-a911-d68d583e8411.png)

After the role mapping is completed, click “Save”. The SCIM configuration part of the setup is complete.

---

## (4) Trigger the directory sync run in CyberArk

In CyberArk, navigate to the Settings → Users → Outbound Provisioning page. Under Synchronizations, start the sync. You can also set up scheduled syncs here.

![A screenshot showing where to select "Start Sync" in the "Outbound Provisioning" settings in the CyberArk dashboard.](https://images.workoscdn.com/images/fe15e2da-4312-4b22-9750-6d9657d569f2.png)

In the CyberArk SCIM directory in the WorkOS dashboard, select the "Users" tab and you will now see the users and groups synced over.

![A screenshot showing the populated "Users" tab in the CyberArk SCIM directory in the WorkOS dashboard.](https://images.workoscdn.com/images/fd7f1d1b-4390-44e5-9aa6-95308d911829.png)

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

## Frequently asked questions

### When a group is removed, I don't see a `dsync.group.deleted` or `dsync.group.user_removed` events - is this expected?

Instead of individually assigning users to a SCIM application, CyberArk SCIM requires that users are assigned to the application through group membership.

It is a known issue with CyberArk SCIM that when a group is removed from the app, no indication is received that the group has changed.

The users of the group must be cleaned up before the group itself is removed from the SCIM application.

### CyberArk SAML

Learn how to configure a connection to CyberArk via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a CyberArk SAML Connection, you’ll need the Identity Provider metadata that is available from your CyberArk instance.

---

## What WorkOS provides

The first thing you’ll need to do is create a new CyberArk SAML connection in your [WorkOS dashboard](https://dashboard.workos.com/). Start by logging in to your WorkOS dashboard and browse to the “Organizations” tab on the left hand navigation bar.

Select the organization you’d like to configure a CyberArk SAML Connection for, and then click “Manually Configure Connection”.

![A screenshot showing where to select "Manually Configure Connection" in the WorkOS dashboard.](https://images.workoscdn.com/images/72c85573-ffe7-4be4-8fe1-2ea60db0c77a.png?auto=format&fit=clip&q=50)

Select “CyberArk SAML” as the Identity Provider, give the Connection a descriptive name, and click “Create Connection”.

![A screenshot showing the "Create Connection" modal in the WorkOS dashboard.](https://images.workoscdn.com/images/d5ef1aab-8d6d-47ff-9af8-ae237ed31440.png?auto=format&fit=clip&q=50)

WorkOS provides the [ACS URL](/glossary/acs-url) and [SP Entity ID](/glossary/sp-entity-id). They are readily available in your Connection Settings in the [WorkOS dashboard](https://dashboard.workos.com/).

![A screenshot showing where to locate the "ACS URL" and "SP Entity ID" in the WorkOS dashboard.](https://images.workoscdn.com/images/d443909c-712a-4084-9ac8-2b47f560a6fa.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. In CyberArk’s case, it needs to be set by the organization when configuring your application in their CyberArk instance.

The SP Entity ID is a URI used to identify the issuer of a SAML request and the audience of a SAML response. In this case, the SP Entity ID is used to communicate that WorkOS will be the party performing SAML requests to the organization's CyberArk instance, and that WorkOS is the intended audience of the SAML responses from the CyberArk instance.

Specifically, the ACS URL will need to be set as the “Assertion Consumer Service (ACS) URL”, and the SP Entity ID will need to be set as the “SP Entity Id / Issuer / Audience”, in the “Service Provider Configuration” section of the “Trust” tab in the SAML App.

![A screenshot showing where to input the WorkOS ACS URL and SP Entity ID in the “SP Entity ID” and "ACS URL" fields in the CyberArk dashboard.](https://images.workoscdn.com/images/bb1b0fe6-0e13-4c45-8bfd-fd0b4d9dc028.png?auto=format&fit=clip&q=50)

---

## What you’ll need

Next, provide the Identity Provider metadata.

Normally, this information will come from the organization's IT Management team when they set up your application’s SAML configuration in their CyberArk Identity Admin Portal. If that’s not the case during your setup, the following steps describe how to get the necessary information.

---

## (1) Log in

Log in to the [CyberArk Identity Admin Portal](https://pod0.idaptive.app/my) and select “Web Apps” from the left-side navigation.

![A screenshot showing where to select 'Web Apps" in the CyberArk dashboard.](https://images.workoscdn.com/images/1e496ecf-4948-4161-8d0e-7dd085d1cc74.png?auto=format&fit=clip&q=50)

---

## (2) Select or create your application

If your application is already created, select it from the list of applications and move to Step 4. If you haven’t created a SAML application in CyberArk, select “Add Web Apps”.

![A screenshot showing where to select "Add Web Apps" in the CyberArk dashboard.](https://images.workoscdn.com/images/034f7256-e5d1-40bf-a258-4532ba462966.png?auto=format&fit=clip&q=50)

Select the “Custom” tab and then click to add “SAML”.

![A screenshot showing how to select the "SAML" web application type in the CyberArk dashboard.](https://images.workoscdn.com/images/48709bed-91f5-4549-8fec-3766ca10b5ee.png?auto=format&fit=clip&q=50)

Select “Yes” to begin setting up the SAML App.

![A screenshot indicating to select "Yes" in the confirmation to add the new application in the CyberArk dashboard.](https://images.workoscdn.com/images/2877ea73-3e8b-4370-9dd2-b3a64ea8990a.png?auto=format&fit=clip&q=50)

---

## (3) Initial SAML Application Setup

Enter a descriptive App Name and Description, then click “Save”.

![A screenshot showing how to populate the "Name" and "Description" fields in the CyberArk dashboard.](https://images.workoscdn.com/images/bb5bf913-edae-4286-9a72-20eaa12ca1e7.png?auto=format&fit=clip&q=50)

Next, navigate to the “Trust” tab and enter the SP Entity ID from the Connection Settings into “SP Entity Id / Issuer / Audience” and the ACS URL from the Connection Settings into “Assertion Consumer Service (ACS) URL” in the “Service Provider Configuration” section of the “Trust” tab in the SAML App.

> IMPORTANT: Be sure to check “Both” under “Sign Response or Assertion?”.

![A screenshot showing where to input the WorkOS ACS URL and SP Entity ID in the “SP Entity ID” and "ACS URL" fields in the CyberArk dashboard.](https://images.workoscdn.com/images/bb1b0fe6-0e13-4c45-8bfd-fd0b4d9dc028.png?auto=format&fit=clip&q=50)

---

## (4) Configure Attribute Mapping

Select the “SAML Response” tab and use the “Add” button to add the following key-value pairs. Then, click “Save”.

- `id` → `LoginUser.Uuid`
- `email` → `LoginUser.Email`
- `firstName` → `LoginUser.FirstName`
- `lastName` → `LoginUser.LastName`

![A screenshot showing the "SAML Response" tab successfully configured in the CyberArk dashboard.](https://images.workoscdn.com/images/63c47f86-6205-4c23-b4b2-1c2950d94fe7.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, first add a new attribute in the "SAML Response" tab. In the "Attribute Name" column, input `groups`, and map it to the "Attribute Value" for a user’s group membership, such as `LoginUser.GroupNames`, as shown in the example below.

![A screenshot showing the groups attribute successfully configured in CyberArk.](https://images.workoscdn.com/images/e5b30513-3915-46a3-b876-650898f8f288.png?auto=format&fit=clip&q=50)

Once your SAML app is configured to return groups, navigate to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (5) Add Users to SAML Application

To give users permission to authenticate via this SAML app, you will need to assign individual users and/or groups of users to the CyberArk SAML app.

Click on the “Permissions” tab, and select “Add”.

![A screenshot showing where to select "Add" in the "Permissions" tab of the application in the CyberArk dashboard.](https://images.workoscdn.com/images/473838e4-cf5f-4feb-a577-f167ac907f01.png?auto=format&fit=clip&q=50)

Search for the individual user(s) and/or group(s) that you would like to assign to the app, and check the box next to them. Click “Add” when you are finished. Once users have been successfully added, you should also notice the “Status” of your CyberArk SAML app change to “Deployed”.

![A screenshot showing the selection of a user to add to the SAML application in the CyberArk dashboard.](https://images.workoscdn.com/images/a09d23b6-5eb7-4fdf-999b-fff77159d43c.png?auto=format&fit=clip&q=50)

---

## (6) Copy Metadata

On the “Trust” tab of the SAML App, go to the “Service Provider Configuration Section” and select “Metadata”. Then click on “Copy URL” button to copy the Metadata URL. This URL will get entered in the WorkOS dashboard in the next step.

![A screenshot showing where to obtain the "Metadata URL" in the CyberArk dashboard.](https://images.workoscdn.com/images/5da3432f-1105-44f1-9433-d1002d1c832d.png?auto=format&fit=clip&q=50)

---

## (7) Provide Metadata

Finally, select "Edit Metadata Configuration" and input the Metadata URL in your WorkOS Connection Settings. Your Connection will then be verified and good to go!

![A screenshot showing where to select "Edit Metadata Configuration" in the "Identity Provider Configuration" in the WorkOS dashboard.](https://images.workoscdn.com/images/bedce7fc-3dcd-468d-ab31-1e65f8f14cb9.png?auto=format&fit=clip&q=50)

### Cloudflare

Learn how to configure a connection to Cloudflare via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a Cloudflare SAML Connection, you’ll need to manually enter the SSO URL, [IdP Entity ID](/glossary/idp-uri-entity-id), and X.509 Certificate obtained from your Cloudflare instance. Instructions on where to obtain these will be covered in this guide.

---

## What WorkOS provides

The first thing you’ll need to do is create a new Cloudflare SAML connection in your [WorkOS Dashboard](https://dashboard.workos.com/). Start by logging in to your WorkOS dashboard and browse to the “Organizations” tab on the left hand navigation bar.

Select the organization you’d like to configure a Cloudflare SAML Connection for, and from the dropdown menu select “Add Connection”.

![A screenshot showing how to add an SSO connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/685a5cfc-14f2-44b9-95de-3b6af1c1b4b1.png?auto=format&fit=clip&q=50)

Select “Cloudflare SAML” as the Identity Provider and give the Connection a descriptive name. Once this is filled out, click “Create Connection”.

![A screenshot showing how to create a Cloudflare SAML Connection.](https://images.workoscdn.com/images/bb5d99c0-0f69-4ef6-b67d-654dd2311745.png?auto=format&fit=clip&q=50)

WorkOS provides the [ACS URL](/glossary/acs-url) and the [SP Entity ID](/glossary/sp-entity-id). These are available in your Connection’s Settings in the Developer Dashboard.

![A screenshot showing where to find the Service Provider details in the WorkOS Dashboard.](https://images.workoscdn.com/images/bea6f73d-6dae-452b-be22-f22861c9497c.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. In Cloudflare’s case, it needs to be set by the organization when configuring the application in the Cloudflare instance.

The SP Entity ID is a URI used to identify the issuer of a SAML request. In this case, the entity ID is used to communicate that WorkOS will be the party performing SAML requests to the organization's Cloudflare instance.

---

## What you’ll need

Cloudflare SAML is a unique integration in that it sits between WorkOS and the Identity Provider. This allows for additional rules to be configured, but also means there are two connections that need to be made. The first necessary connection is between Cloudflare and the IdP, and the second connection is between WorkOS and Cloudflare.

---

## (1) Connect Cloudflare with your Identity Provider

First, create the connection between Cloudflare and the Identity Provider. Cloudflare Access allows you to connect with any IdP that supports a SAML 2.0 connection. Follow the [documentation from Cloudflare](https://developers.cloudflare.com/cloudflare-one/identity/idp-integration/generic-saml) to configure a SAML application connection between Cloudflare and your IdP.

The one deviation from the CloudFlare documentation is that the SAML attributes must include `email`, `firstName`, `lastName`, and `id`. Email is included by default as the “Email attribute name”, but you will need to add the other three as SAML attributes.

When setting up the connection, be sure to enter `email`, `firstName`, `lastName`, and `id` as SAML attributes.

![A screenshot showing how to configure SAML attributes in Cloudflare Access.](https://images.workoscdn.com/images/57473539-2c40-4c16-b59b-471cbdce1764.png?auto=format&fit=clip&q=50)

Save the connection and then click the “Test” button. When successful, you will see a success screen including your `saml_attributes` that have been added.

![A screenshot showing a successful test of Cloudflare Access.](https://images.workoscdn.com/images/bd575c26-8d01-4e12-8e7e-70198da3e33d.png?auto=format&fit=clip&q=50)

---

## (2) Add an Application in Cloudflare Access

Next, create the connection between Cloudflare and WorkOS. From the Cloudflare Zero Trust dashboard Access menu, select “Applications”, then “Add an application”.

![A screenshot showing where to add an application in Cloudflare Access.](https://images.workoscdn.com/images/ae6525fa-194c-44f5-a20b-f6ea14667ec2.png?auto=format&fit=clip&q=50)

Select “SaaS” for the type of application.

![A screenshot highlighting the SaaS application type in Cloudflare.](https://images.workoscdn.com/images/9202ac92-d1b7-4ad7-9c2d-486528e8edcb.png?auto=format&fit=clip&q=50)

Copy the ACS URL and Entity ID from the Connection Settings in your WorkOS Dashboard.

![A screenshot showing where to find the Service Provider details in the WorkOS Dashboard.](https://images.workoscdn.com/images/bea6f73d-6dae-452b-be22-f22861c9497c.png?auto=format&fit=clip&q=50)

Select the name of your application from the dropdown menu. If your application is not listed, type the name to save it.

Paste the ACS URL and SP Entity ID to the corresponding fields in Cloudflare. Then select the Name ID Format that you would like to use for this application. For this example we’ll use Unique ID.

![A screenshot showing where to input Service Provider details into the Cloudflare application.](https://images.workoscdn.com/images/2417371c-2a7d-41e7-a98b-295461e1741f.png?auto=format&fit=clip&q=50)

---

## (3) Configure Attribute Mapping

Now, Configure the attribute statements. WorkOS requires that `email`, `firstName`, `lastName`, and `id` be included. Cloudflare automatically sends `id` and `email`, so you only need to add `firstName` and `lastName`. These attributes were configured in Step 1, and the mapped values are the same here.

Add `firstName` and `lastName` to both the right and left sides of the SAML attribute statements.

![A screenshot showing where to configure Cloudflare attribute mapping.](https://images.workoscdn.com/images/6d0a7e54-e912-4cb7-8688-427d595d30e6.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information, add a new attribute statement with `groups` as the "Name" and map it to the "IdP attribute" for `groups`, as shown in the example below.

![A screenshot showing how to configure a groups attribute in Cloudflare.](https://images.workoscdn.com/images/659df99d-79b9-4fd4-bcec-69b337504cfe.png?auto=format&fit=clip&q=50)

#### Resolving groups attribute issues

If you're having issues getting the `groups` attribute to come through, it's possible that Cloudflare is sending it as a nested structure, specifically an array of group objects rather than plain strings.

WorkOS expects `groups` to be a top-level attribute where each value is a simple string, such as the group name or ID.

To resolve this, go to the **Advanced Settings** section of your Cloudflare Access application and define a [JSONata transformation](https://developers.cloudflare.com/cloudflare-one/applications/configure-apps/saas-apps/generic-saml-saas/#jsonata-transforms) to map the structured `groups` attribute into the expected format.

For example, to extract the `name` from each group object, use the following transformation: `$ ~> | $ | { "groups": groups.name } |`

![A screenshot showing JSONata transform applied to the groups attribute](https://images.workoscdn.com/images/3be403b4-26a1-40b6-a64e-3503f6f69a21.png?auto=format&fit=clip&q=50)

This will transform an input like:

```json
{
  "groups": [
    { "name": "Engineering", "id": "abc123" },
    { "name": "Finance", "id": "def456" }
  ]
}
```

Into the expected format:

```json
{
  "groups": ["Engineering", "Finance"]
}
```

You may also use groups.id if you prefer to map group IDs instead.

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

---

## (4) Finish SSO Application Configuration

Select the Identity Provider that you are using from the list. In this example we are using an Okta SAML connection.

![A screenshot highlighting where to select the Identity Provider in the Cloudflare application.](https://images.workoscdn.com/images/0f4ea850-5111-4659-a67f-8887cde842dd.png?auto=format&fit=clip&q=50)

Configure at least one policy and one rule, then click next. For this example the Policy sets the session length to 30 minutes for everyone.

![A screenshot showing where to configure policy and rules for the Cloudflare application.](https://images.workoscdn.com/images/c6141486-5b88-47e5-88d8-161294698ece.png?auto=format&fit=clip&q=50)

---

## (5) Copy Connection Credentials

The SSO endpoint, Entity ID, and Public key (X.509 certificate) all will be entered in the Connection details in the [WorkOS Dashboard](https://dashboard.workos.com/). The SSO endpoint and Entity ID can be entered as-is, but the Public Key needs to be formatted as an X.509 certificate.

![A screenshot showing where to copy the connection credentials from the Cloudflare dashboard.](https://images.workoscdn.com/images/81f19129-0b22-4f78-b238-e9b087a3a52b.png?auto=format&fit=clip&q=50)

To format the Public Key, copy the value to a text editor and add the following header and footer to the Public Key. Ensure there are no spaces above or below the Key value, then save with the file extension “.cert”.

```shell title="Certificate format"
-----BEGIN CERTIFICATE-----

-----END CERTIFICATE-----
```

The format of the file should look like this when you’re finished.

```shell title="Completed Certificate Format"
-----BEGIN CERTIFICATE-----
MIIDUTCCAjmgAwIBAgIRAN557boQ2ZxW4Ww08cZYK2IwDQYJKoZIhvcNAQELBQAw
YjELMAkGA1UEBhMCVVMxDjAMxxxxxAgTBVRleGFzMQ8wDQYDVQQHEwZBdXN0aW4x
EzARBgNVBAoTCkNsb3VkZmxhcmUxHTAbBgNVBAMTFGNsb3VkZmxhcmVhY2Nlc3Mu
Y29tMB4XDTxxxxxwMjE5MzMxM1oXDTMyMDIwMjE5MzMxM1owYjELMAkGA1UEBhMC
VVMxDjAMBgNVBAgTBVRleGFzMQ8wDQYDVQQHEwZBdXN0aW4xEzARBgNVBAoTCkNs
b3VkZmxhcmUxHTAbBgNVBAMTFGNsb3VkZmxxxxxhY2Nlc3MuY29tMIIBIjANBgkq
hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA49p6jXzk65DeG4DI2NgW0UOOJrd+9qYS
OCuBYq/e4IqSeqchsm1JDY9MjB6xmiw+urC1qWuj0MS4dwAJQwiGFbCGDh5m4FAF
mZm5VaMkW5Q+MG5zXRfeLmhvLuT0XVBcDlkwPC3k28/moKi1KlwPcujLF43+rf2d
8Rm6ZNCJgfVzRxxxxxPd5NGpNlEZ0ViPXM1gsO15/1Iginevv+xKqRTx0vMsNLWJ
BwWLAAqm5b6U9XQefwy9lPqPywFwCuZEMXwI9Rpm0f2xmOK56EudtdSkQ1JtSgYX
x9rf/97NfP8wI2x1IncQtwdWNdW5cvxMqYU/Za6WZvjNCnpFQGXLJQIDAQABowIw
ADANBgkqhkiG9w0BAQsFAAOCAQEARZ0h2ZeNXSme0EbQeJfEFOX+mj9rPkHIJFfQ
G7+dRG6DwDubxG56TsvUINcJX8O5C6oQ0T6dRutO/jG5LxJqmCz5wLUTA/6/YLDk
95gbYyJ/yfLm4sd6DEoXzWSld+EZ5b86pxFnvR/+cPY2tcSghQ+moZKR5THwHLsZ
hie2Pr6UVvuS5D9BC4ijR+cPyB5r4qliI9C1p8phuZctoX9dPpFY+UwkWgUDx9sz
UXFJsqueoibxfVqh4Jzdw+2XH6xN3WvTdJN4Sh1fqEpBeOxxxxxlRrCAJiMnLtG6
QgHF9ZnNRbIFcUHF/lyWY3oxcvgeUwEnE5QVVbdoMMGKKgffbQ==
-----END CERTIFICATE-----
```

---

## (6) Provide Connection Credentials

Navigate to the Connection in your Developer Dashboard. Enter the SSO endpoint in the [IdP SSO URL](/glossary/idp-sso-url) field and enter the “Access Entity ID or Issuer” value into the “IdP URI (Entity ID)” field.

Upload the file that you saved for the X.509 certificate to the “Add an X.509 Certificate” field. Click Save Configuration.

![A screenshot showing where upload the Metadata configuration details.](https://images.workoscdn.com/images/2d149107-fbc3-4e09-a644-b68dc5ff151b.png?auto=format&fit=clip&q=50)

Your Connection will then be Active and good to go!

### Clever OIDC

Learn how to configure a connection to Clever via OIDC.

## Introduction

Each SSO identity provider requires specific information to create and configure a new [SSO connection](/glossary/connection). Often, the information required to create an SSO connection will differ by identity provider.

To create a Clever OIDC SSO connection, you'll need three pieces of information: a [redirect URI](/glossary/redirect-uri), [client ID](/glossary/client-id), and [client secret](/glossary/client-secret).

Start by logging into your WorkOS dashboard and navigate to the **Organizations** page from the left-hand navigation bar.

Select the organization you'd like to configure a Clever OIDC SSO connection for, and select **Configure manually** under **Single Sign-On**.

![WorkOS Dashboard Organizations tab with "Configure manually" button highlighted](https://images.workoscdn.com/images/d577cfbe-028b-48cf-8cc0-4cd5d3adf853.png?auto=format&fit=clip&q=50)

Select **Clever OIDC** from the identity provider dropdown. Click **Create Connection**.

![Create Connection form with Clever OIDC selected as Identity Provider](https://images.workoscdn.com/images/2a5545f1-70ea-4347-8d99-a39c5850085c.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

WorkOS provides the Redirect URI, which can be found in the **Service Provider Details** section on the SSO connection page in the [WorkOS Dashboard](https://dashboard.workos.com/).

- [Redirect URI](/glossary/redirect-uri): The endpoint where identity providers send authentication responses after successful login

![The Redirect URI of a OIDC connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/062a78e9-1d87-4643-890f-ebd1221e645b.png?auto=format&fit=clip&q=50)

The Redirect URI is the location an identity provider redirects its authentication response to. In Clever’s case, it needs to be added to the OAuth settings in the Clever admin as outlined in [step 1](/integrations/clever-oidc/1-configure-the-redirect-uri).

---

## What you'll need

You will need to obtain two pieces of information from the organization:

- [Client ID](/glossary/client-id): Application identifier from the OIDC provider
- [Client secret](/glossary/client-secret): Authentication secret for the application

Typically, this information comes from the organization's IT team when they set up your application's OIDC configuration in their Clever admin dashboard. However, if that’s not the case during your setup, the next steps will show you how to obtain it.

---

## (1) Configure the Redirect URI

Sign in to [Clever](https://apps.clever.com/).

In the left navigation bar, select the **Settings** tab. In the horizontal menu, select the **Integration** tab.

Locate the **OAuth Settings** section and click **Edit**.

![Setting the redirect URI in the Clever admin dashboard](https://images.workoscdn.com/images/0f7a4169-8cf1-4239-9d03-9f2022fb6a88.png?auto=format&fit=clip&q=50)

The **Update OAuth Settings** dialog will open. Copy the [Redirect URI](/integrations/clever-oidc/what-workos-provides) from the SSO connection page in the WorkOS Dashboard into the **REDIRECT URIS** field. Click **Save**.

---

## (2) Obtain configuration details

While on the **Settings** tab in Clever, select the **General** tab in the horizontal menu.

After creating an application, a client ID and client secret are provisioned. Locate the **CLIENT ID** and **CLIENT SECRET** fields and copy the values.

![Copying the client id and secret from the Clever admin dashboard](https://images.workoscdn.com/images/b4c527e1-0335-428e-a658-ef3ecfd820a3.png?auto=format&fit=clip&q=50)

Back in the [WorkOS Dashboard](https://dashboard.workos.com/) on the SSO connection page, enter the client ID and client secret you obtained from Clever into the respective fields in the **Settings** section.

![WorkOS Dashboard Settings with Client ID and Client Secret fields](https://images.workoscdn.com/images/d7ebf399-4cc9-4588-9961-6160d6bbd9bf.png?auto=format&fit=clip&q=50)

Click **Update connection** to save.

---

## (3) Test Single Sign-On

Test signing in to verify that the single sign-on connection was configured correctly.

From the SSO connection page in the WorkOS Dashboard, click **Test SSO** to initiate a test authentication flow.

---

## Next steps

Your Clever OIDC connection is now configured and ready to use. Users assigned to the application in Clever will be able to authenticate through WorkOS using their Clever credentials.

To start using this connection in your application, refer to the [SSO guide](/sso) for implementation details.

### ClassLink

Learn how to configure a connection to ClassLink via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a ClassLink SAML Connection, you’ll need the Identity Provider Metadata URL that is available from the organization's ClassLink SAML instance.

Start by logging in to your WorkOS dashboard and browse to the “Organizations” tab on the left hand navigation bar.

Select the organization you’d like to configure a ClassLink SAML Connection for, and select “Manually Configure Connection” under “Identity Provider”.

![A screenshot showing the "Manual Configure Connection" option in the WorkOS Dashboard.](https://images.workoscdn.com/images/fe7f0470-1d95-4708-b364-6dfea9e94e59.png?auto=format&fit=clip&q=50)

Select “ClassLink SAML” from the Identity Provider dropdown, enter a descriptive name for the connection, and then select the “Create Connection” button.

![A screenshot showing a ClassLink connection being created in the WorkOS Dashboard.](https://images.workoscdn.com/images/20fabb8d-91a2-4f7d-965f-837f886a8481.png?auto=format&fit=clip&q=50)

---

## What WorkOS provides

WorkOS provides the [ACS URL](/glossary/acs-url), the [SP Metadata](/glossary/sp-metadata) link and the [SP Entity ID](/glossary/sp-entity-id). They are readily available in your Connection Settings in the [Developer Dashboard](https://dashboard.workos.com/).

The SP Metadata link contains a metadata file that the organization can use to set up the SAML integration.

![A screenshot showing the Service Provider Details provided by WorkOS for a ClassLink connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/46a922ac-10d2-424a-9b10-762702f8fc05.png?auto=format&fit=clip&q=50)

---

## What you’ll need

In order to integrate you’ll need the [IdP Metadata URL](/glossary/idp-metadata).

Normally, this will come from the organization's IT Management team when they set up your application’s SAML 2.0 configuration in their ClassLink instance. Here’s how to obtain them:

---

## (1) Select or create your application

Login to the ClassLink Management Console (CMC), click Single Sign-On and select SAML Console.

Click ADD NEW or COPY EXISTING. Copy Existing contains pre-configured SAML apps which need to be updated to fit your unique settings.

![A screenshot showing where to select "Add Application" in the ClassLink console.](https://images.workoscdn.com/images/2adb6c82-eeb2-4fee-9eb1-cd1655d08e35.png?auto=format&fit=clip&q=50)

---

## (2) Initial SAML Application Setup

Edit the new application by click the three dots menu icon, and then selecting Edit.

![A screenshot showing where to edit the ClassLink application.](https://images.workoscdn.com/images/70877547-fcac-40ec-a98f-87f5333ad59f.png?auto=format&fit=clip&q=50)

Update the Metadata URL in the ClassLink application settings with the SP Metadata URL provided to you by WorkOS.

![A screenshot showing where to enter the SP Metadata URL in the ClassLink application settings.](https://images.workoscdn.com/images/d97393b1-5066-4f48-a6e4-bb5cf1a2c6c8.png?auto=format&fit=clip&q=50)

---

## (3) Configure SAML Application

Under the “Attribute Mapping” section of the SAML app, map the following four attributes as shown below, and the select “Update”.

- `id` &rarr; `Login id`
- `email` &rarr; `Email`
- `firstName` &rarr; `Given Name`
- `lastName` &rarr; `Family Name`

![A screenshot showing how to input user attribute mapping in the ClassLink dashboard.](https://images.workoscdn.com/images/a6f3d9da-cb06-4eda-a243-f3fb84f9df76.png?auto=format&fit=clip&q=50)

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, map the groups in your identity provider to a SAML attribute named `groups`.

> Finish role assignment set-up by navigating to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

## (4) Upload Metadata URL

Copy the IdP Metadata URL from your ClassLink SAML settings and upload it to your WorkOS Connection settings.

![A screenshot highlighting where the ClassLink Metadata URL is located in the ClassLink console.](https://images.workoscdn.com/images/a75ed9fa-3b21-469b-93e4-3b8483da3717.png?auto=format&fit=clip&q=50)

In the Connection settings in the WorkOS Dashboard, click “Edit Metadata Configuration”.

![A screenshot highlighting the "Edit Metadata Configuration" button in a Connection details view in the WorkOS Dashboard.](https://images.workoscdn.com/images/c03dd1dc-84b3-4909-bee5-61249280e35f.png?auto=format&fit=clip&q=50)

Paste the Metadata URL from ClassLink into the “Metadata URL” field and select “Save Metadata Configuration”.

![A screenshot showing how to input the Metadata URL into the Connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/88884c90-bb7d-4f18-9a7c-bb7c7ad1fee2.png?auto=format&fit=clip&q=50)

Your Connection will then be linked and good to go!

### Cezanne HR

Learn about syncing your user list with Cezanne HR.

## Introduction

This guide outlines how to synchronize your application’s Cezanne HR directories.

To synchronize an organization’s users and groups provisioned for your application, you’ll need the following information from the organization:

- Cezanne HR Client ID
- Cezanne HR Client Secret

> Note: The Cezanne HR integration isn't enabled by default in the WorkOS Dashboard or Admin Portal. Please reach out to [support@workos.com](mailto:support@workos.com) or via your team’s WorkOS Slack channel if you would like Cezanne HR enabled.

---

## (1) Set up your Directory Sync Connection

Login to your WorkOS Dashboard and select “Organizations” from the left hand navigation bar.

Select the organization you’ll be configuring a new Directory Sync Connection with.

Click “Manually Configure Connection”.

![A screenshot showing where to find "Manually Configure Directory" button for an organization in the WorkOS dashboard.](https://images.workoscdn.com/images/e65f54ae-6010-4492-a838-8583dc614e50.png?auto=format&fit=clip&q=50)

Input the Name, and select “Cezanne HR” as the directory type.

Click the “Create Directory” button.

![A screenshot showing "Create Directory" details in the WorkOS dashboard.](https://images.workoscdn.com/images/1217ac5a-6d04-4783-8ce5-b005c14aa005.png?auto=format&fit=clip&q=50)

You will now see your Cezanne HR directory sync has created successfully with an input for the Client ID and Client Secret

---

## (2) Obtain a Cezanne HR Client ID and Client Secret

To obtain these credentials, you will need to request a new API Application from the Cezanne HR Support Team.

---

## (3) Enter the details in the Directory’s detail page

Click “Update Directory”.

There are two fields to enter, the Client ID and Client Secret that Cezanne support provided for you.

![A screenshot showing where to find the "Update Directory" button in the WorkOS dashboard.](https://images.workoscdn.com/images/1b94ab4a-b001-47ea-a89f-548011881ff0.png?auto=format&fit=clip&q=50)

---

## (4) Sync Users and Groups to Your Application

When the connection is successfully made, you will see the green “Linked” icon appear. Now, whenever the organization assigns users or groups to your application, you’ll receive Dashboard updates based on changes in their directory.

Click on the “Users” tab in the Dashboard to view synced users.

![A screenshot showing where to find the "Users" tab in the WorkOS directory.](https://images.workoscdn.com/images/ed0393d9-84de-416b-8410-b5596e091d67.png?auto=format&fit=clip&q=50)

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

## Frequently asked questions

### How often do Cezanne HR directories perform a sync?

Cezanne HR directories poll every 30 minutes starting from the time of the initial sync.

### CAS SAML

Learn how to configure a connection to CAS via SAML.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a CAS SAML Connection, you’ll need the Identity Provider Metadata URL that is available from your customer’s CAS SAML instance.

---

## What WorkOS provides

WorkOS provides the [ACS URL](/glossary/acs-url), the [SP Metadata](/glossary/sp-metadata) link and the [SP Entity ID](/glossary/sp-entity-id). They are readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot highlighting the "Service Provider Details" of a CAS SAML connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/68f2825e-7787-4100-b7d5-8339ed75b6be.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. The SP Metadata link contains a metadata file that the organization can use to set up the SAML integration. The SP Entity ID is a URI used to identify the issuer of a SAML request, response, or assertion.

---

## What you’ll need

In order to integrate you’ll need the [IdP Metadata URL](/glossary/idp-metadata).

Normally, this will come from the organization’s IT Management team when they set up your application’s SAML 2.0 configuration in their CAS instance. But, should that not be the case during your setup, here’s how to obtain it.

---

## (1) Enter Service Provider Details

Copy and paste the “ACS URL” and “SP Entity ID” into the corresponding fields for Service Provider details and configuration. For some setups, you can use the metadata found at the SP Metadata link to configure the SAML connection.

---

## (2) Obtain Identity Provider Metadata

Copy the IdP Metadata URL from your CAS SAML settings and upload it to your WorkOS Connection settings. Your Connection will then be linked and good to go!

![A screenshot highlighting the "URL Metadata Configuration" input of a CAS SAML Connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/a32e166f-ab97-47f1-988d-6799b303160f.png?auto=format&fit=clip&q=50)

Alternatively, you can manually configure the connection by providing the IdP URI (Entity ID), [IdP SSO URL](/glossary/idp-sso-url) and X.509 Certificate.

![A screenshot highlighting the "Switch to Manual Configuration" button on the URL Metadata Configuration modal of a CAS SAML connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/4b40807d-0f4c-4b0f-81a5-05f832b88b25.png?auto=format&fit=clip&q=50)

![A screenshot showing the input fields for manual configuration of a CAS SAML connection in the WorkOS Dashboard.](https://images.workoscdn.com/images/0eb372eb-551f-4ad8-8d89-9519ce10dfbe.png?auto=format&fit=clip&q=50)

---

## (3) Configure Attribute Mapping

At minimum, the Attribute Statement in the SAML Response should include `id`, `email`, `firstName`, and `lastName` attributes.

### Role Assignment (optional)

With [identity provider role assignment](/sso/identity-provider-role-assignment), users can receive roles within your application based on their group memberships. To return this information in the attribute statement, map the groups in your identity provider to a SAML attribute named `groups`.

Once your SAML app is configured to return groups, navigate to the SSO connection page in the _Organization_ section of the [WorkOS Dashboard](https://dashboard.workos.com/). Create SSO groups by referencing the group IdP ID. Then, assign roles to these SSO groups so group members are automatically granted roles within your application.

### Bubble Plugin

Add WorkOS features to your Bubble application.

## Introduction

The [Bubble plugin for WorkOS](https://bubble.io/plugin/workos-sso-1666727595127x530956156372516860) allows you to easily integrate [WorkOS API](/reference) endpoints in your application's workflows. This plugin includes actions for SSO, Directory Sync, Admin Portal, and webhook validation.

---

## Install the WorkOS SSO and API Plugins

In the **Plugins** tab of your app editor in Bubble, click **Add Plugins**, then search for WorkOS. Install the plugins for both WorkOS SSO and WorkOS API and then click **Done**.

![A screenshot showing how to install the WorkOS SSO plugin in Bubble.](https://images.workoscdn.com/images/03cf97a8-e0e9-49bc-be67-e21501ff5ab4.png?auto=format&fit=clip&q=50)

![A screenshot showing how to install the WorkOS API plugin in Bubble.](https://images.workoscdn.com/images/165832c3-88d2-49e5-9153-8fd1009367aa.png?auto=format&fit=clip&q=50)

The next step is to enter your secret keys/parameters on the **Plugins** settings page as seen below. The API key can be found in your WorkOS dashboard under **API Keys**.

> In the WorkOS SSO plugin the API Key value can be entered directly.

![A screenshot showing where to enter environment variables in Bubble for the WorkOS SSO plugin.](https://images.workoscdn.com/images/40fd465f-b73c-4dd2-8478-375eb68757ae.png?auto=format&fit=clip&q=50)

> In the WorkOS API plugin the API Key value needs to be preceded by **Bearer**.

![A screenshot showing where to enter environment variables in Bubble for the WorkOS API plugin.](https://images.workoscdn.com/images/4bd64da1-4212-4ef9-a1bc-8064d60eac64.png?auto=format&fit=clip&q=50)

Now you’re set up to use the plugin directly in your workflows.

---

## Single Sign-On

Whether you are implementing a Single Sign-On authorization flow for your application using a no-code platform or building your app from the ground up, the steps that you need to take on a high level are the same. You can find more information in our [SSO Quickstart Guide](/sso).

### Use SSO in a Workflow

To configure SSO, you will need:

- An active SSO connection, which can be configured manually or by using the [Admin Portal](/admin-portal).
- A [connection](/reference/sso/connection) ID or [organization](/reference/organization) ID associated with the user logging in. If WorkOS does not handle user management on your application’s behalf, it is necessary to keep track of the association between your users and their WorkOS connection or organization IDs in your database.
- [Redirect URI](glossary/redirect-uri), which is the URL to redirect the user to when they are authorized. This is provided by Bubble in the **Plugins** tab.

Navigate to the **Workflow** page in your application and add a new event. Select the action that will trigger the workflow to start. In this case, the workflow is triggered when the submit button is clicked.

Under the **Account** menu option, select **Signup/login with a social network**, then select **WorkOS SSO** from the **OAuth provider** dropdown menu. Enter either the connection ID, organization ID, or provider.

> Select whether you will use connection, organization, or provider (OAuth connections only), and delete the other defaults. The value should be entered in the `organization=` format.

![A screenshot showing how to enter the parameter values in a Bubble workflow.](https://images.workoscdn.com/images/c39e8579-e064-4f79-b6ad-a3ec8d5c1118.png?auto=format&fit=clip&q=50)

When a user launches this workflow, they will be prompted to log in through the associated WorkOS SSO connection.

Upon a successful login, if the user does not exist in the application database, a new user will be created and logged in as the current user. If the user already exists, that user will be logged in as the current user.

---

## Directory Sync

To start using [Directory Sync](/directory-sync), you will need to configure a new directory connection between your customer’s directory provider and WorkOS. This can be completed manually or by using the [Admin Portal](/admin-portal).

Once a directory connection is activated in WorkOS, you can configure webhooks to send events to your Bubble application using the WorkOS plugin through a backend workflow.

### Enable backend workflows

To enable backend workflows, navigate to the **Settings** page of your Bubble app under the **API** tab, and select **Enable Workflow API and backend workflows**. You are now able to configure backend workflows in the **Workflow** section.

![A screenshot showing how enable backend workflows in Bubble.](https://images.workoscdn.com/images/e3443ee9-38fb-4d1a-98d3-40d0af2bfa3d.png?auto=format&fit=clip&q=50)

### Create a new workflow to receive webhooks

To create a new workflow that subscribes to WorkOS webhooks, navigate to the **Workflows** section of your app in Bubble and select **backend workflows** from the page selection dropdown.

![A screenshot showing how to navigate to and create a new backend workflow in Bubble.](https://images.workoscdn.com/images/ec2377c0-1d06-40a0-9608-710690f539b3.png?auto=format&fit=clip&q=50)

Create a new API Workflow. In the **detected data option** ensure that **include headers** is selected before clicking **Detect data**.

![A screenshot showing how to configure a backend workflow to detect data in Bubble.](https://images.workoscdn.com/images/67a1be1b-7ec7-4f6a-8c30-d3804eca2aa7.png?auto=format&fit=clip&q=50)

A pop-up window will show a test URL to validate the webhook body.

![A screenshot showing when a backend workflow is ready to detect data in Bubble.](https://images.workoscdn.com/images/070d64e5-899f-499c-9fca-74eb5cbc267a.png?auto=format&fit=clip&q=50)

Navigate to the **Webhooks** tab in your WorkOS dashboard and enter this test URL as your webhook endpoint.

![A screenshot showing how to configure a webhook endpoint in the WorkOS dashboard.](https://images.workoscdn.com/images/85e7b624-c107-49d2-82af-9c7a026caeb9.png?auto=format&fit=clip&q=50)

Then, click the **Send Test Event** button to send a test event.

![A screenshot showing where to send a test webhook event in the WorkOS dashboard.](https://images.workoscdn.com/images/87937fdf-a9e7-4804-a780-5e5d96b40a18.png?auto=format&fit=clip&q=50)

Bubble will recognize the event and validate the endpoint. Click save to complete the subscription to WorkOS webhook events for this workflow.

![A screenshot showing a successfully detected webhook event in Bubble.](https://images.workoscdn.com/images/aa9531f1-7df5-4053-9021-e9cca649dbcc.png?auto=format&fit=clip&q=50)

### Implement the webhook validation action

After the new workflow is set up to listen for new events, it is recommended that you use the webhook validation action to verify that the webhooks being received are from WorkOS.

This action verifies the request is valid by using the webhook body, signature, and secret that you provide from your WorkOS dashboard. To properly define the webhook parameter, you should use the raw body text of the request data. Similarly, the `webhook_signature` should be defined using the `workos-signature` in the request data headers.

![A screenshot showing how to select the webhook validation action in Bubble.](https://images.workoscdn.com/images/e43720ac-5669-4a8d-8ac3-5a220ed2c730.png?auto=format&fit=clip&q=50)

After the event is validated, you can use the data from the body to log the webhook and make changes to users.

### Reconcile the users

The plugin also includes endpoints, documented under the directory sync section of the [API Reference](/reference), that can be used to reconcile users.

Periodically calling the [List Directory Users](/reference/directory-sync/directory-user/list) endpoint and verifying that the returned date matches what you have stored in your user table helps ensure your application has up-to-date information about your users, so you can use it with confidence.

---

## Admin Portal

The [Admin Portal](/admin-portal) provides an out-of-the-box UI for organization admins to configure SSO and Directory Sync connections.

The WorkOS API plugin provides an API call that launches the Admin Portal if you would like to display it on the settings page of your application. You can also copy and paste these links directly from the WorkOS dashboard in the connection settings.

Upon completing the setup flow with the Admin Portal, the organization admin will be able to test the new connection and validate that it has been configured correctly.

![A screenshot showing how to select the admin portal action in Bubble.](https://images.workoscdn.com/images/14cafa76-cb94-4880-800c-5b8b2aa93777.png?auto=format&fit=clip&q=50)

### Breathe HR

Learn about syncing your user list with Breathe HR.

## Introduction

This guide outlines how to synchronize your application’s Breathe HR directories.

To synchronize an organization’s users and groups provisioned for your application, you’ll need the following information from the organization:

- Breathe HR API key

> Note: The Breathe HR integration isn't enabled by default in the WorkOS Dashboard or Admin Portal. Please reach out to [support@workos.com](mailto:support@workos.com) or via your team’s WorkOS Slack channel if you would like Breathe HR enabled.

---

## (1) Create an API Key

The organization will need to create an API key for you. An API key can be generated from the Admin Settings menu.

![A screenshot showing where to select "Settings" in the Breathe HR dashboard.](https://images.workoscdn.com/images/3defb6ef-fe7d-458f-8639-d0410fc11f51.png)

Under "Integrations", select "API Setup".

![A screenshot showing where to select "API Setup" in the Breathe HR dashboard settings.](https://images.workoscdn.com/images/d6c8d0e9-1d71-428e-b368-4bcd5240432c.png)

Next, select "Enable API".

![A screenshot showing where to select "Enable API" on the "API Setup" page in the Breathe HR dashboard.](https://images.workoscdn.com/images/890c4a8e-4217-433f-b67f-037dda40a7c5.png)

Verify that you’d like to enable the API to access user information.

![A screenshot showing to mark the checkbox denoting "I understand and want to continue" in the "Warning" modal in the Breathe HR dashboard.](https://images.workoscdn.com/images/e6623c61-c520-4636-a029-c91fb2b5a33f.png)

Save the production API key – this will be used in the next step.

![A screenshot showing where to select the production API key in the "API Setup" section of the Breathe HR dashboard.](https://images.workoscdn.com/images/d66a8ba2-bcf6-44bf-a714-e08164cdf632.png)

---

## (2) Create your Directory Sync Connection

Login to your WorkOS dashboard and select “Organizations” from the left hand Navigation bar

Select the Organization you’d like to enable a Breathe HR Directory Sync connection for.

On the Organization’s page click “Add Directory”.

![A screenshot showing where to select "Add Directory" in the WorkOS dashboard.](https://images.workoscdn.com/images/f6bdcf89-cfc4-46e6-a67c-d2f428e6052a.png)

Select “Breathe HR” as the Directory Provider, and then provide a descriptive name for the connection. Select “Create Directory”.

![A screenshot showing the configuration of the "Create Directory" modal to create a Breathe HR Directory in the WorkOS dashboard.](https://images.workoscdn.com/images/32c361da-6bf7-428b-84c0-5b1f27db5c51.png)

---

## (3) Set up your Directory Sync Connection

Click “Update Directory” on the Directory details page.

![A screenshot showing where to select "Update Directory" in the WorkOS dashboard.](https://images.workoscdn.com/images/d2f1bfb0-f119-4582-8c6c-83e11bbbbd87.png)

Input the Breathe HR API key and click “Save Directory Details”.

![A screenshot showing the input of the Breathe HR API key into the "Directory Details" modal in the WorkOS dashboard.](https://images.workoscdn.com/images/12ede429-9f2b-4cff-8e30-00e2b3594a85.png)

---

## (4) Sync Users and Groups to Your Application

Now, you should see users and groups synced over from Breathe HR.

Departments from Breathe HR are synced as groups in WorkOS. All users are synced, but only those marked as “Current employee” or "Pending leaver" are active.

![A screenshot showing a successfully linked Breathe HR Directory in the WorkOS dashboard.](https://images.workoscdn.com/images/26b9a26a-1abc-4517-9251-104da59f7251.png)

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

## Frequently asked questions

### How often do Breathe HR directories perform a sync?

Breathe HR directories poll every 30 minutes starting from the time of the initial sync.

### BambooHR

Learn about syncing your user list with BambooHR.

## Introduction

This guide outlines how to synchronize your application’s BambooHR directories.

To synchronize an organization’s users and groups provisioned for your application, you’ll need the following information from the organization:

- The BambooHR subdomain.
- A BambooHR API key to authenticate requests.

> Note: The BambooHR integration isn't enabled by default in the WorkOS Dashboard or Admin Portal. Please reach out to [support@workos.com](mailto:support@workos.com) or via your team’s WorkOS Slack channel if you would like BambooHR enabled.

---

## (1) Create your Directory Sync Connection

Login to your WorkOS Dashboard and select “Organizations” from the left hand navigation bar.

Select the organization you’ll be configuring a new Directory Sync Connection with.

Click “Manually Configure Connection”.

![A screenshot showing where to find “Manually Configure Connection” for an Organization in the WorkOS Dashboard.](https://images.workoscdn.com/images/60d14679-0ff2-4b7b-9e75-82ea0ae158f5.png?auto=format&fit=clip&q=50)

Input the Name, and select “BambooHR” as the directory type.

Click the “Create Directory” button.

![A screenshot showing "Create Directory" details in the WorkOS Dashboard.](https://images.workoscdn.com/images/e696881c-64b9-40c4-aa8e-593913179c92.png?auto=format&fit=clip&q=50)

You will now see your BambooHR directory sync has created successfully with an [Endpoint](/glossary/endpoint), as well as fields to input your subdomain and API Key from BambooHR.

---

## (2) Retrieve the details from an organization IT admin

To generate an API key, an IT admin should log into BambooHR and click their name in the upper right-hand corner of the BambooHR console. Select "API Keys" from the list.

![A screenshot showing where to find the "API Keys" option in the BambooHR Dashboard.](https://images.workoscdn.com/images/6165e109-527d-4960-adc2-b7882262e526.png?auto=format&fit=clip&q=80)

Next, the IT admin should click “Add New Key”.

![A screenshot showing where to find the "Add New Key" in the BambooHR Dashboard.](https://images.workoscdn.com/images/eb6b50be-6a2c-478b-aa3f-0d7b69240ddd.png?auto=format&fit=clip&q=80)

Give your key a descriptive name and select "Generate Key."

![A screenshot showing where to find "Generate Key" in the BambooHR Dashboard.](https://images.workoscdn.com/images/a176f1f3-10a0-4803-acd2-fbbe69fb9719.png?auto=format&fit=clip&q=80)

Select "Copy Key" and save this API key, which you’ll upload in the next step.

![A screenshot showing where to find "Copy Key" in the BambooHR Dashboard.](https://images.workoscdn.com/images/69c5bff2-023f-4a1e-8cdf-48edc4609a29.png?auto=format&fit=clip&q=80)

---

## (3) Set up your Directory Sync Connection

Click “Update Directory”.

There are two fields to enter, one is the API key you created in step 2.

The other is “Subdomain” which is the subdomain name of the Company’s BambooHR instance.

![A screenshot showing where to find the "Update Directory" button in the WorkOS Dashboard.](https://images.workoscdn.com/images/f562e95e-faf9-4658-ac27-1d1396abcccb.png?auto=format&fit=clip&q=50)

---

## (4) Sync Users and Groups to Your Application

When the connection is successfully made, you will see the green “Linked” icon appear. Now, whenever your customer assigns users or groups to your application, you’ll receive Dashboard updates based on changes in their directory.

A detailed guide to integrate the WorkOS API with your application can be found [here](/directory-sync)

## Frequently Asked Questions

### How do I add BambooHR's custom fields?

For BambooHR's custom fields, please contact [support@workos.com](mailto:support@workos.com) with your directory ID and a list of the custom fields you would like to be added.

### How often do BambooHR directories perform a sync?

BambooHR directories poll every 30 minutes starting from the time of the initial sync.

### AWS Cognito

Learn how to use WorkOS with your existing AWS Cognito applications.

## Introduction

This guide outlines the steps to make WorkOS SSO Connections available to AWS Cognito applications without requiring changes to your existing application code.

The integration works by configuring WorkOS connections as third-party [Identity Providers](https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-identity-federation.html) inside a Cognito User Pool which enables users to sign in to a Cognito application leveraging all SSO integrations supported by WorkOS.

> The AWS Cognito integration is in feature preview. Reach out to [WorkOS support](mailto:support@workos.com?subject=AWS%20Cognito%20Integration) if you want early access.

---

## (1) Configure AWS IAM role

WorkOS manages the configuration of the Cognito Identity Providers by leveraging AWS role delegation. You will need to create an IAM role in your AWS account that grants permissions to the WorkOS AWS account. This is can be easily accomplished through the AWS Console.

![Create AWS IAM role](https://images.workoscdn.com/images/0a36c5ff-505e-46ba-805a-66d13c9150ed.png?auto=format&fit=clip&q=50)

The external ID will be provided by the WorkOS support team upon request. The AWS account ID should be `611361754156` which is the ID of a dedicated WorkOS AWS account used for Cognito integrations.

You will need to attach the following policy to the role so that the Identity Providers can be managed when the role is assumed by WorkOS.

```json language="json" title="IAM Policy"
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "VisualEditor",
      "Effect": "Allow",
      "Action": ["cognito-idp:*"],
      "Resource": "*"
    }
  ]
}
```

Complete the creation of the role and take note of the name you provide as it will be used in the following step.

## (2) Provide AWS details to WorkOS

Once the role has been configured you will need to provide the following details from your AWS account to the WorkOS support team.

- Account ID
- Role name
- User pool ID

Once the WorkOS support team has configured your AWS details, you should see Identity Providers configured in the specified User Pool for every connection configured in WorkOS. Newly added WorkOS connections will automatically be created in the specified User Pool.

## (3) Enable Identity Providers for App Client

Now that the Identity Providers have been configured, they will need to be enabled for the App Client you wish to use the WorkOS Connections with.

From the user pool navigate to **App integration** → **_Your App Client_** → **Edit hosted UI settings** and select the newly created Identity Providers.

![App Client Identity Provider settings](https://images.workoscdn.com/images/e0f4a7c1-4131-4110-a6a3-9f5466110745.png?auto=format&fit=clip&q=50)

> If you do not complete this step you will receive a **Login option is not available** error from Cognito upon sign in.

## (4) Configure redirect URI

Locate the domain of the Cognito User Pool and configure the following redirect URI in the WorkOS Dashboard under **Configuration** → **Settings** → **Redirect URIs**.

```plain title="Cognito callback URI"
https:///oauth2/idpresponse
```

## (5) Sign in with WorkOS connection

Once an Identity Provider has been created in the Cognito User Pool, you may initiate authentication by passing the `idp_identifier` query parameter to the [OAuth2 Authorize endpoint](https://docs.aws.amazon.com/cognito/latest/developerguide/authorization-endpoint.html) provided by Cognito using the details from the App Client that was previously configured with the Identity Providers.

You may pass either a WorkOS [Organization](/reference/organization) or [Connection](/reference/sso/connection) ID as the `idp_identifier`. Passing this query parameter will result in Cognito bypassing it’s standard sign-in page and immediately redirecting the user to the appropriate sign-in page of the upstream identity provider configured in the WorkOS Connection.

Once the user is authenticated they will be redirected to your Cognito App Client redirect URL with the Cognito `code` query parameter.

### Auth0

Learn how to configure a connection to Auth0 via SAML.

> Looking to migrate from Auth0 to WorkOS? Check out the [full migration guide](/migrate/auth0).

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a Connection will differ by Identity Provider.

To create a Auth0 SAML Connection, you’ll need the Identity Provider metadata that is available from the organization's Auth0 instance.

Start by logging in to your WorkOS dashboard and browse to the “Organizations” tab on the left hand navigation bar.

Select the organization you’d like to configure an Auth0 SAML Connection for, and select “Manually Configure Connection” under “Identity Provider”.

![A screenshot showing where to find "Manually Configure Connection" in the WorkOS Dashboard.](https://images.workoscdn.com/images/2c3eff01-e84c-4e65-9739-ae72facb9eaa.png?auto=format&fit=clip&q=50)

Select "Auth0 SAML” from the Identity Provider dropdown, enter a descriptive name for the connection, and then select the “Create Connection” button.

![A screenshot showing "Create Connection" details in the WorkOS Dashboard.](https://images.workoscdn.com/images/6e0f49c0-06fb-4a18-b805-31e3a10b27bb.png?auto=format&fit=clip&q=50)

---

## What WorkOS Provides

WorkOS provides the [ACS URL](/glossary/acs-url) and [SP Entity ID](/glossary/sp-entity-id), which are readily available in your Connection Settings in the [WorkOS Dashboard](https://dashboard.workos.com/).

![A screenshot showing where to find the ACS URL and SP Entity ID in the WorkOS Dashboard.](https://images.workoscdn.com/images/ec8cb8f8-b440-47d5-9a80-7b51ca9950bd.png?auto=format&fit=clip&q=50)

The ACS URL is the location an Identity Provider redirects its authentication response to. In Auth0’s case, the ACS URL needs to be set by the organization when configuring your application in their Auth0 instance.

The SP Entity ID is a URI used to identify the issuer of a SAML request and the audience of a SAML response. In this case, the SP Entity ID is used to communicate that WorkOS will be the party performing SAML requests to the organization's Auth0 instance, and that WorkOS is the intended audience of the SAML responses from the Auth0 instance.

Specifically, the ACS URL will need to be set as the “Application Callback URL” on the SAML2 Web App Settings page found under the “Addons” tab in an Auth0 application. You will need to toggle on the SAML2 Web App for the settings modal to appear where you can add the ACS URL under the Application Callback URL input.

![A screenshot showing a toggle to turn on the SAML2 web app addon for Auth0 applications.](https://images.workoscdn.com/images/63ffadf6-ed3b-429d-a4a7-a5294b1a3a0d.png?auto=format&fit=clip&q=50)

![A screenshot showing where to set the ACS URL in the SAML2 web app settings for Auth0 applications.](https://images.workoscdn.com/images/294645cc-18d2-4969-a9ed-6ec69f2bca3d.png?auto=format&fit=clip&q=50)

The SP Entity ID will need to be set as the "audience" value in the Settings JSON object on the SAML2 Web App Settings page.

After the Application Callback URL and Audience have been added, scroll to the bottom and click "Enable".

![A screenshot showing where to set the SP Entity ID in the SAML2 web app settings for Auth0 applications.](https://images.workoscdn.com/images/4fd65ff7-6296-43d8-8e65-0bd528028f70.png?auto=format&fit=clip&q=50)

---

## What you’ll need

In order to integrate you’ll need the Auth0 IdP Metadata URL.

Normally, this information will come from the organization's IT Management team when they set up your application’s SAML 2.0 configuration in their Auth0 admin dashboard. Here’s how to obtain them:

---

## (1) Log In and Select Your Application

Log in to [Auth0](https://auth0.com/auth/login), go to the admin dashboard, select “Applications” in the sidebar, and then select the “Applications” menu option. Next, select your application from the list of applications.

![A screenshot showing where to find the web application in Auth0 Dashboard.](https://images.workoscdn.com/images/e4bb38d9-fa10-4caa-b097-05a8d83a4e2b.png?auto=format&fit=clip&q=50)

---

## (2) Obtain Identity Provider Metadata

On the application’s Settings page, scroll down to the bottom and expand the “Advanced Settings” section. Select the “Endpoints” tab and copy the SAML Metadata URL. You’ll need this in the next step.

![A screenshot of the IdP Metadata XML URL in the Auth0 Dashboard.](https://images.workoscdn.com/images/6288c6a6-ab57-4608-8a1e-872bbd7eb2bd.png?auto=format&fit=clip&q=50)

---

## (3) Upload Metadata URL

Finally, upload the SAML Metadata URL you saved earlier in your WorkOS Connection settings. Your Connection will then be linked and good to go!

![A screenshot showing where to place the Auth0 IdP Metadata URL in the WorkOS Dashboard.](https://images.workoscdn.com/images/f1cb1c5c-8554-48a5-89a1-31a42d356690.png?auto=format&fit=clip&q=50)

### Auth0 Enterprise Connection

Learn how to use WorkOS with your existing Auth0 applications.

> Looking to migrate from Auth0 to WorkOS? Check out the [full migration guide](/migrate/auth0).

## Introduction

This guide outlines the steps to make WorkOS SSO connections available to Auth0 applications without requiring changes to your existing Auth0 application code.

> The Auth0 Enterprise Connection integration is in feature preview. Reach out to [WorkOS support](mailto:support@workos.com?subject=WorkOS%20Support) if you want early access.

---

## (1) Configure Auth0 API Access

WorkOS uses Auth0 credentials you provide to manage the Auth0 Enterprise Connection automatically. The first step is authorizing an application in Auth0 to access the Management API.

In the Auth0 dashboard, navigate to **Applications** → **APIs** → **Auth0 Management API**:

![A screenshot showing the "Auth0 Management API" entry on the Auth0 APIs page.](https://images.workoscdn.com/images/e2baba2e-a442-4449-90db-d1be8db41ef2.png?auto=format&fit=clip&q=50)

Click on the **Machine To Machine Applications** tab and expand the section for your Auth0 application. Then, toggle the **Authorized** switch to enable the API.

Under **Permissions**, ensure the following scopes are granted to the application:

- `create:connections`
- `read:connections`
- `update:connections`

Your permissions configuration should match the following screenshot:

![A screenshot a correctly configured API application in the Auth0 dashboard.](https://images.workoscdn.com/images/13b5acb2-b5c6-4cd5-a032-0dd7afedc81a.png?auto=format&fit=clip&q=50)

Next, navigate to **Applications** → **_Your App_** → **Settings**. You should see three fields under **Basic Information**: "Domain", "Client ID", and "Client Secret".

![A screenshot showing application credentials in the Auth0 dashboard.](https://images.workoscdn.com/images/c8303868-de12-40e5-a0cc-27bec508131c.png?auto=format&fit=clip&q=50)

Record this information in a safe place, as you will provide it to the WorkOS dashboard in the next step.

---

## (2) Connect WorkOS to Auth0

In the WorkOS dashboard, navigate to **Configuration** → **Settings** and scroll to the **Auth0 Credentials** section. Click **Set Auth0 Credentials**:

![A screenshot showing the "Auth0 Credentials" section in the WorkOS dashboard.](https://images.workoscdn.com/images/16b3ea51-8564-4ced-86fb-f3ab9fad8d28.png?auto=format&fit=clip&q=50)

In the modal, enter the credentials you obtained in the previous step: "API Domain", "Client ID", and "Client Secret".

![A screenshot showing the "Auth0 Credentials" form in the WorkOS dashboard.](https://images.workoscdn.com/images/3e915c68-97c0-4d1e-88e9-cda8bff7fd31.png?auto=format&fit=clip&q=50)

Click **Save**. In the final step, you will head back to the Auth0 dashboard one last time to complete the configuration.

---

## (3) Enable the Enterprise Connection

After saving your credentials, WorkOS will create an Enterprise Connection in your Auth0 environment. This connection is the entry point into WorkOS SSO from Auth0. The next step is to enable the connection for your Auth0 application.

In the Auth0 dashboard, navigate to **Applications** → **_Your App_** → **Connections**. You should see a connection with a `workos-sso-` prefix in its name. Enable it for your application.

![A screenshot showing enabled connections for an application in the Auth0 dashboard.](https://images.workoscdn.com/images/4cd3dbec-7ccc-462a-a101-5f8fc29aa332.png?auto=format&fit=clip&q=50)

---

## (4) Enable "Identifier First" Login Flow

In the Auth0 dashboard, navigate to **Authentication** → **Authentication Profile**. You should see three options for configuring login flow. Select **Identifier First**.

![A screenshot showing "Identifier First" selected in the Auth0 dashboard.](https://images.workoscdn.com/images/b30e3808-b978-4f86-9443-8e2e7d588a90.png?auto=format&fit=clip&q=80)

This configures the Auth0 Universal Login page to begin by prompting the user for their email address. This is necessary as it allows Auth0 to select the WorkOS SSO Enterprise Connection if the user’s email domain matches one of your WorkOS organizations. Non-enterprise users will still be prompted for their password.

> [IdP-initiated SSO](/sso/login-flows/idp-initiated-sso) is currently not supported when using the Auth0 Enterprise Connection integration.

---

## Summary

Your WorkOS SSO connections are now available to your Auth0 application! You are ready to use WorkOS features like [Admin Portal](admin-portal), allowing IT admins to configure their SSO setup for your application directly.

As you create [organizations](/reference/organization), WorkOS will keep the Auth0 Enterprise Connection's [Home Realm Discovery](https://auth0.com/docs/authenticate/login/auth0-universal-login/identifier-first#define-home-realm-discovery-identity-providers) list updated with the organization's domains – ensuring correct routing of enterprise users to WorkOS for authentication.

When users enter their email address into the Auth0 Universal Login, which matches a domain associated with a WorkOS organization, Auth0 redirects users to their WorkOS-enabled IdP sign-in page for their organization. Once the authentication process is complete with the IdP, WorkOS redirects to your Auth0 app callback URL.

> Since email domains are used to route users to the correct IdP when using Auth0, WorkOS will enforce that [organization domains](/reference/organization-domain) are unique, and therefore a domain cannot be assigned to more than one organization.

### Auth0 Directory Sync

Learn how to use Directory Sync with your Auth0 applications.

> Looking to migrate from Auth0 to WorkOS? Check out the [full migration guide](/migrate/auth0).

## Introduction

This guide will walk you through the steps to enable WorkOS Directory Sync for your Auth0 applications. If you are new to automated user provisioning and deprovisioning, the [Directory Sync](/directory-sync) introduction is a good place to learn the basics.

> The Auth0 Directory Sync integration is in feature preview. Reach out to [WorkOS support](mailto:support@workos.com?subject=Auth0%20Directory%20Sync%20Integration) if you want early access.

## (1) Configure Auth0 API access

WorkOS uses Auth0 credentials you provide to automatically create and manage an Auth0 database connection. The first step is to authorize an application in Auth0 to access the Management API.

In the Auth0 dashboard, navigate to **Applications** → **APIs** → **Auth0 Management API**:

![A screenshot showing the “Auth0 Management API” entry on the Auth0 APIs page.](https://images.workoscdn.com/images/e2baba2e-a442-4449-90db-d1be8db41ef2.png?auto=format&fit=clip&q=50)

Click on the **Machine To Machine Applications** tab and expand the section for your Auth0 application. Then, toggle the **Authorized** switch to enable the API.

Under **Permissions**, ensure the following scopes are granted to the application:

- `create:connections`
- `create:users`
- `read:connections`
- `read:users`
- `update:connections`
- `update:users`

Your permissions configuration should match the following screenshot:

![A screenshot a correctly configured API application in the Auth0 dashboard.](https://images.workoscdn.com/images/13b5acb2-b5c6-4cd5-a032-0dd7afedc81a.png?auto=format&fit=clip&q=50)

Next, navigate to **Applications** → **_Your App_** → **Settings**. You should see three fields under **Basic Information**: “Domain”, “Client ID”, and “Client Secret”.

![A screenshot showing application credentials in the Auth0 dashboard.](https://images.workoscdn.com/images/c8303868-de12-40e5-a0cc-27bec508131c.png?auto=format&fit=clip&q=50)

Record this information in a safe place, as you will provide it to the WorkOS dashboard in the next step.

---

## (2) Connect WorkOS to Auth0

In the WorkOS dashboard, navigate to **Configuration** → **Settings** and scroll to the **Auth0 Credentials** section. Click **Set Auth0 Credentials**:

![A screenshot showing the “Auth0 Credentials” section in the WorkOS dashboard.](https://images.workoscdn.com/images/16b3ea51-8564-4ced-86fb-f3ab9fad8d28.png?auto=format&fit=clip&q=50)

In the modal, enter the credentials you obtained in the previous step: “API Domain”, “Client ID”, and “Client Secret”.

![A screenshot showing the “Auth0 Credentials” form in the WorkOS dashboard.](https://images.workoscdn.com/images/3e915c68-97c0-4d1e-88e9-cda8bff7fd31.png?auto=format&fit=clip&q=50)

Click **Save**. In the final step, you will head back to the Auth0 dashboard one last time to complete the configuration.

---

## (3) Enable the database connection

After saving your credentials, WorkOS will create a database connection in your Auth0 environment. This connection will contain the users from directories in your WorkOS organizations. The next step is to enable the connection for your Auth0 application.

In the Auth0 dashboard, navigate to **Applications** → **_Your App_** → **Connections**. You should see a connection with a `workos-dsync-` prefix in its name. Enable it for your application.

![A screenshot showing enabled connections for an application in the Auth0 dashboard.](https://images.workoscdn.com/images/73b12882-d286-49cd-ba58-a0527eab7f4f.png?auto=format&fit=clip&q=50)

---

## Summary

Your WorkOS directories will now be synchronized with your new Auth0 database connection! You are ready to use WorkOS features like [Admin Portal](/admin-portal), allowing IT admins to configure their directory provider for your application directly.

New users provisioned into Auth0 are given a randomly generated password. They will need to reset their password before they can sign in. You can also use [WorkOS directory sync webhooks](/events/data-syncing/webhooks) to be notified when new users are provisioned, allowing you to tailor the onboarding experience for these new users, like sending a welcome email.

Deprovisioned users will be deleted from the Auth0 database connection. If you need to perform additional cleanup in your application, you can receive WorkOS directory sync webhooks for delete events as well.

### Apple

Learn how to set up “Sign in with Apple”

## Introduction

The “Sign in with Apple” integration allows your users to authenticate using their Apple ID credentials.

The configuration process involves obtaining credentials from your Apple Developer account and configuring them in the WorkOS Dashboard. You may also set up Private Email Relay for users who choose to hide their email addresses.

---

## Testing with default credentials in the staging environment

WorkOS provides a default set of Apple credentials, which allow you to quickly enable and test Sign in with Apple. WorkOS will automatically use the default credentials until you add your own Apple Team ID, Apple Service ID, and Apple Private Key to the configuration in the [WorkOS dashboard](https://dashboard.workos.com).

> The default credentials are only intended for testing and therefore only available in the Staging environment. For your production environment, please follow the steps below to create and specify your own Apple Team ID, Apple Service ID, and Apple Private Key.

Please note that when you are using WorkOS default credentials, Apple's authentication flow will display the WorkOS name, logo, and other information to users. Once you register your own application and use its credentials for the authentication flow, you will have the opportunity to customize the app.

---

## What WorkOS provides

When setting up “Sign in with Apple”, WorkOS provides two key pieces of information that need to be configured in your Apple Developer account:

- [Redirect URI](/glossary/redirect-uri): The endpoint where Apple will send authentication responses after successful login
- **Outbound Email Domains**: Registered domains for Apple's Private Relay email service

These are available in the [WorkOS Dashboard](https://dashboard.workos.com/). In the left navigation menu, select the **Authentication** tab and the **OAuth providers** sub-tab. Locate the **Sign in with Apple** section.

![Open the Sign in with Apple configuration dialog](https://images.workoscdn.com/images/b9abf389-f950-49b2-8cf3-2c47e9b810bf.png?auto=format&fit=clip&q=50)

Click **Enable**. The **Sign in with Apple** configuration dialog will open. Locate the **Redirect URI** and **Outbound email domains**.

![Sign in with Apple Redirect URI in the WorkOS dashboard.](https://images.workoscdn.com/images/54680256-09bc-478f-ab0f-5889c1d846be.png?auto=format&fit=clip&q=50)

The **Redirect URI** serves as the destination for authentication responses and must be configured in your Apple Developer account. **Outbound email domains** are registered with Apple's Private Relay email service to deliver email to users who choose to hide their email addresses.

---

## What you'll need

You will need to obtain four pieces of information from your Apple Developer account:

- **Apple Team ID**: Your organization's unique identifier in the Apple Developer program
- **Apple Service ID**: Application identifier for “Sign in with Apple”
- **Apple Private Key**: Authentication key file for secure communication
- **Private Key ID**: Identifier for the private key

The following sections will guide you through generating these credentials in your Apple Developer account.

---

## (1) Retrieve your Apple Team ID

Sign in to the [certificates, identifiers, and profiles](https://developer.apple.com/account/resources/certificates/list) section of your Apple Developer account.

The landing page will display your name, company name, and Team ID. Note the Team ID value as you'll need it later.

![Team ID in the Apple Developer dashboard.](https://images.workoscdn.com/images/2edd45b9-7e84-45fa-8da2-3c6dcd5607a1.png?auto=format&fit=clip&q=80)

> The Team ID is sensitive and will only be used by the server to communicate with Apple. It should not be shared with the client.

---

## (2) Register an App ID

> Skip this step if you already have an App ID.

Click on **Identifiers** in the sidebar, then click the + button to create a new identifier.

![Identifiers page in the Apple Developer dashboard with Create Identifier plus button highlighted.](https://images.workoscdn.com/images/54be9c35-f7c9-4119-9765-64299d42ff23.png?auto=format&fit=clip&q=80)

On the next page, select **App IDs** and click **Continue**.

![First step in the Identifier creation wizard with App IDs selected.](https://images.workoscdn.com/images/a028e2b5-9443-4208-aa0c-175056ac55b5.png?auto=format&fit=clip&q=80)

Next, select **App** and click **Continue**.

![Second step in the Identifier creation wizard with App selected.](https://images.workoscdn.com/images/baff59f5-f060-4faf-9761-678321cc496a.png?auto=format&fit=clip&q=80)

On the next page, fill in a description and a bundle ID. The bundle ID should be unique and in reverse domain notation, e.g., `com.example.myapp`.

Also check the **Sign in with Apple** box in the Capabilities section. There is no need to update anything in the **Edit** modal.

![Third step in the Identifier creation wizard with placeholder Description and Bundle ID entered.](https://images.workoscdn.com/images/ef85061d-ff63-4d5a-8fad-a9cbefeb6786.png?auto=format&fit=clip&q=80)

![Third step in the Identifier creation wizard with Sign in with Apple checkbox checked.](https://images.workoscdn.com/images/9f184ccb-40d8-4410-9250-b8ab56600452.png?auto=format&fit=clip&q=80)

Then click **Continue**. Review your selections and click **Register**.

---

## (3) Register a Service ID

Next you need to create a linked Service ID. Click on **Identifiers** in the sidebar, then click the + button.

![Identifiers page in the Apple Developer dashboard with Create Identifier plus button highlighted.](https://images.workoscdn.com/images/4a129d31-33c8-4976-8340-d59fc6618b67.png?auto=format&fit=clip&q=80)

On the next page, select **Services IDs** and click **Continue**.

![First step in the Identifier creation wizard with Services IDs selected.](https://images.workoscdn.com/images/2496cf53-f593-4eda-a2f9-14d6728b0c5d.png?auto=format&fit=clip&q=80)

Enter a description and a Service ID. The Service ID should be unique and in reverse domain notation, e.g. `com.example.myapp`.

![Second step in the Identifier creation wizard with placeholder Description and Service ID entered.](https://images.workoscdn.com/images/dbf69235-951c-4f1d-97b2-3a1c6854c758.png?auto=format&fit=clip&q=80)

Click **Continue**. Note the Service ID as you'll need it later, then click **Register** to create the service.

Now you'll configure your new service for “Sign in with Apple”. First select the new service from the list of Service IDs.

![Identifiers page in the Apple Developer dashboard with the newly created Service ID highlighted.](https://images.workoscdn.com/images/478f799f-298e-4dee-9b6d-ff75d02fd9f5.png?auto=format&fit=clip&q=80)

Check the **Sign in with Apple** box and click **Configure**.

![Service ID Edit page with Sign in with Apple checkbox checked.](https://images.workoscdn.com/images/8c3e92fe-f5fc-403e-b7ee-fa215ad61ccf.png?auto=format&fit=clip&q=80)

Ensure the App ID you created earlier is selected in the dropdown. Then enter `api.workos.com` in the **Domains and Subdomains** field and paste the **Redirect URI** from the WorkOS Dashboard in the **Return URLs** field.

![Service ID Sign in with Apple edit modal with placeholder values in the inputs.](https://images.workoscdn.com/images/574617e5-4e3c-41a9-8704-dfa47bf504e2.png?auto=format&fit=clip&q=80)

Click **Done** and then **Continue**. Review your changes and click **Save**.

---

## (4) Register a private key

Click on **Keys** in the sidebar, then click the + button to create a new key.

![Keys page in the Apple Developer dashboard with Create Key plus button highlighted.](https://images.workoscdn.com/images/ebeffde4-091d-4b2c-a9f9-fede59d6674a.png?auto=format&fit=clip&q=80)

On the next page, enter a human-readable **Key Name**. Then check the **Sign in with Apple** box and click **Configure**.

![First step in the Key creation wizard.](https://images.workoscdn.com/images/264d1e39-ccae-4d32-80da-af2d5813723c.png?auto=format&fit=clip&q=80)

In the **Configure** dialog, select the App ID you created earlier and click **Save**.

![Key Configure dialog with App ID from the previous step selected.](https://images.workoscdn.com/images/d1442a7c-47a3-412c-956b-415a11acda9b.png?auto=format&fit=clip&q=80)

Click **Continue**. Review your changes and click **Register** to create your key.

![Download Your Key page.](https://images.workoscdn.com/images/eb032a3d-4d2a-44be-a2f5-292e901fae16.png?auto=format&fit=clip&q=80)

Make sure to download your new private key and note the Key ID as you'll need both later.

---

## (5) Configure Apple credentials in WorkOS

Now you have all the required credentials:

- Apple Team ID
- Apple Service ID
- Private Key ID
- The downloaded private key file

Return to the [WorkOS Dashboard](https://dashboard.workos.com). In the **Sign in with Apple** configuration dialog, toggle **Enable** on. Select **Your app's credentials**. Paste the credentials from Apple that you generated in the previous steps into their respective fields.

![Sign in with Apple configuration modal in the WorkOS dashboard filled out with information from earlier steps.](https://images.workoscdn.com/images/cfedc298-8666-4f38-ab71-f6ed777b44c1.png?auto=format&fit=clip&q=80)

---

## (6) Set up Private Email Relay

Sign in with Apple users can opt to hide their email address when signing in. In order for emails to be sent to those users, you need to configure Private Email Relay.

Copy the **Outbound Email Domains** from the **Sign in with Apple** configuration modal in the WorkOS Dashboard.

![Sign in with Apple configuration modal in the WorkOS dashboard with outbound email domains control highlighted.](https://images.workoscdn.com/images/8c4ae9a5-1b27-49c7-90f7-31a3010ee2b5.png?auto=format&fit=clip&q=80)

Open your Apple Developer account and click on **Services** in the sidebar. Then click on **Configure** under **Sign in with Apple for Email Communication**.

![Services page in the Apple Developer dashboard with Sign in with Apple Configure button highlighted.](https://images.workoscdn.com/images/cc81ae18-450d-417f-9e22-6392b335e437.png?auto=format&fit=clip&q=80)

Click the + button next to **Email Sources** and enter the outbound email domains from the WorkOS Dashboard in the **Domains and Subdomains** text box. Then click **Next** and **Register**.

![Modal to register Email Sources with domains from the WorkOS dashboard in the Domains and Subdomains text box.](https://images.workoscdn.com/images/021882c4-e299-44b8-9a44-fcf22f3be150.png?auto=format&fit=clip&q=80)

![New domains with green check marks next to them.](https://images.workoscdn.com/images/fa3e78e6-688d-46a8-b4e7-1f6c788da4f6.png?auto=format&fit=clip&q=80)

You are now ready to start authenticating with “Sign in with Apple”. Your users will see the option to “Sign in with Apple” when visiting your [AuthKit](/authkit) domain. Alternatively if you're using the [standalone SSO API](/reference/sso/get-authorization-url), you can initiate “Sign in with Apple” by passing `AppleOAuth` as the `provider`.

---

## Frequently asked questions

### How is the WorkOS “Sign in with Apple” integration different from implementing regular Apple OAuth flow?

It's the same Apple OAuth flow as you could build yourself, but it's encapsulated within WorkOS SSO. This means you don't need to build it yourself. In addition to “Sign in with Apple”, you can use WorkOS SSO to support other identity providers, all with a single integration.

### What is the provider query parameter and how is it used in the Apple OAuth integration?

You can use the `provider` query parameter in the [Get Authorization URL API endpoint](/reference/sso/get-authorization-url) to support global Apple OAuth for any domain. The `provider` query parameter should be set to `AppleOAuth`.

### Why do I need to configure Private Email Relay?

“Sign in with Apple” allows users to hide their real email address from your app. When a user chooses this option, Apple generates a unique, random email address that forwards to their real email. To send emails to these users, you need to register your sending domains with Apple's Private Email Relay service.

### What happens if I don't set up Private Email Relay?

If you don't configure Private Email Relay, you won't be able to send emails to users who choose to hide their email address. Those users will still be able to sign in, but any emails you attempt to send to their relay address will not be delivered.

### Can I use the same App ID for multiple services?

Yes, you can use the same App ID for multiple Services IDs. This is useful if you have multiple applications or environments that need to use “Sign in with Apple”.

### ADP OpenID Connect

Learn how to configure a connection to ADP via OIDC.

## Introduction

Each SSO Identity Provider requires specific information to create and configure a new [Connection](/glossary/connection). Often, the information required to create a connection will differ by Identity Provider.

ADP is unique in that it authenticates using the Open ID Connect (OIDC) protocol instead of [SAML](/glossary/saml). This means that instead of providing an [ACS URL](/glossary/acs-url) and [SP Entity ID](/glossary/sp-entity-id) into the IdP, The IdP will provide a client ID and secret. ADP also provides an SSL Certificate and Private RSA Key file to authenticate. These four pieces of information will all need to be uploaded into the WorkOS dashboard in the steps below.

---

## (1) Create a New ADP OIDC Connection in WorkOS

Navigate to the Organization in your WorkOS Dashboard under which you would like to set up this new SSO connection. Click on the "Manually Configure Connection" button.

![A screenshot showing where to find "Manually Configure Connection" in the WorkOS Dashboard.](https://images.workoscdn.com/images/b7370939-c547-4ad1-9b2d-cc8ed150b90b.png?auto=format&fit=clip&q=50)

Select ADP OIDC as the Identity Provider and select “Create Connection”.

![A screenshot showing "Create Connection" details in the WorkOS Dashboard.](https://images.workoscdn.com/images/e20c45f0-2842-45e0-9364-7878f493f0a4.png?auto=format&fit=clip&q=50)

---

## (2) Select or Create a Project in ADP

Login to the [ADP Partner Self Service Portal](https://adpapps.adp.com/self-service/projects).

From this page there are two environments to select from, Development and Production. Please use the environment that best suits your use-case for this SSO connection.

In the selected environment select “Create New Project”.

![A screenshot showing the Projects Overview page in the ADP Partner Self Service Portal.](https://images.workoscdn.com/images/39422d34-f4b8-42c2-af5a-b7c8b26dfe1f.png?auto=format&fit=clip&q=50&w=2048)

Give the project a meaningful name to designate the SSO connection, there is no need to add a description.

![A screenshot showing the Create New Project details in the ADP Partner Self Service Portal.](https://images.workoscdn.com/images/614daf3e-afa8-4007-9aec-f087fb60a394.png?auto=format&fit=clip&q=50&w=2048)

Make the selections “US Marketplace” and “ADP Workforce Now” respectively for the next selections and then click “Next”.

![A screenshot showing selection options for the ADP Marketplace in the ADP Partner Self Service Portal.](https://images.workoscdn.com/images/e38e06a8-7c82-44d3-bb58-cc7cc875b8cc.png?auto=format&fit=clip&q=50&w=2048)

Finally, select “Other” for the use case that best describes your application and click “Submit”.

![A screenshot showing app description selection options in the ADP Partner Self Service Portal.](https://images.workoscdn.com/images/8de31a18-444c-4a48-b41a-fd3be86b4933.png?auto=format&fit=clip&q=50)

---

## (3) Upload the WorkOS Redirect URI in ADP

After configuring the ADP project, the next step is to provide ADP with the redirect URI generated by WorkOS.

![A screenshot showing where to find the ACS URL and SP Entity ID in the WorkOS Dashboard.](https://images.workoscdn.com/images/5bc6cf1c-c327-4e81-9588-442fc61bf55d.png?auto=format&fit=clip&q=50)

Now that a new project has been created browse to the “Development API Credentials” Tab within the project.

Click on the “End-User/SSO sub-tab” from this view.

Paste the [Redirect URI](/glossary/redirect-uri) into the App redirect URI field and click “Update Redirect”.

![A screenshot showing where to place the WorkOS Single Sign-On URL and SP Entity ID in the ADP Partner Self Service Portal.](https://images.workoscdn.com/images/5ae15d57-82d5-4591-bc86-f6637a1588f7.png?auto=format&fit=clip&q=50)

---

## (4) Enter ADP OIDC Client Settings in your WorkOS Dashboard

Now that the redirect URI has been provided, the next step is to gather the [Client ID](/glossary/client-id) and [Client Secret](/glossary/client-secret) from ADP and add it into the WorkOS Dashboard.

Under the same tab used in the previous step, you’ll provide the Client ID and Client Secret from ADP. Click to reveal the secret and copy and paste both the client ID and client secret into the WorkOS dashboard.

![A screenshot showing where to find the ADP Client Credentials in the ADP Partner Self Service Portal.](https://images.workoscdn.com/images/2c8b784a-88e5-4d63-9853-3f8eb6acd304.png?auto=format&fit=clip&q=50)

![A screenshot showing where to enter the ADP Client Credentials WorkOS Dashboard.](https://images.workoscdn.com/images/fc0444d4-9864-4c19-ab4a-327ab914417f.png?auto=format&fit=clip&q=50)

---

## (5) Upload the ADP SSL Cert and Private Key in your WorkOS Dashboard

Now that the Client ID and Secret have been provided, the next step is to gather the SSL Certificate and Private Key from ADP and add it into the WorkOS Dashboard.

ADP uses a two fold certificate method with an SSL certificate and an SSL Private Key. The SSL Private Key is only displayed one time when the certificate is generated. If the certificate has already been generated, the IT Administrator who generated it should have also received the Private Key otherwise a new certificate and key can be generated by browsing to the certificates tab on the left hand navigation.

The SSL Certificate can be found in ADP by browsing to “Certificate” on the left hand nav bar. You can also create a new SSL Certificate and Private Key pair if necessary.

![A screenshot showing where to download the ADP SSL Certificate and Private Key in the ADP Partner Self Service Portal.](https://images.workoscdn.com/images/31e16dbd-3f08-41b4-9478-5a02b0c3a9f5.png?auto=format&fit=clip&q=50)

Upload the two files into your WorkOS dashboard in their respective portals on the connection page and click “Update Connection”.

![A screenshot showing where to upload the ADP SSL Certificate and Private Key in the WorkOS Dashboard](https://images.workoscdn.com/images/783a81be-f5c4-43ba-b2f2-25a9f1c18a8f.png?auto=format&fit=clip&q=50)

---

## (6) Verify Connection Status in WorkOS

Navigate back to the connection in your WorkOS dashboard. After a minute or two you should see the connection become Active as indicated by the green badge next to the connection name.

All that’s left to do now is test out the connection. You can use your own application if it’s connected to WorkOS already, or feel free to use one of our example applications like this [Python Flask SSO app](https://github.com/workos/python-flask-example-applications/tree/main/python-flask-sso-example) to get up and running with a PoC quickly

### Access People HR

Learn about syncing your user list with Access People HR.

## Introduction

This guide outlines how to synchronize your application’s Access People HR directories.

To synchronize an organization’s users and groups provisioned for your application, you’ll need the following information from the organization:

- Access People HR API key

> Note: The Access People HR integration isn't enabled by default in the WorkOS Dashboard or Admin Portal. Please reach out to [support@workos.com](mailto:support@workos.com) or via your team’s WorkOS Slack channel if you would like Access People HR enabled.

---

## (1) Create an API Key

The organization will need to create an API key for you. First, they’ll need to log in to their Access People HR admin dashboard and select to the “Settings” page from the side bar menu. Then, select “API” from the Settings side bar menu. On the API Key Management page, select the plus sign to add a new API Key.

![A screenshot showing where to find the plus sign in the Access People HR Dashboard.](https://images.workoscdn.com/images/9cbff13f-9ea3-442a-90ae-7c135e14e07b.png?auto=format&fit=clip&q=50)

In the API Key Generator, give the API Key a descriptive name. Under “Application”, select “Employee”.

![A screenshot showing where the "Employee" option is location in the Access People HR Dashboard.](https://images.workoscdn.com/images/02f54969-422c-4f17-9c34-559bd419cf3e.png?auto=format&fit=clip&q=50)

On the Select Permissions page, check only “Get All Employee Detail” and then select “Save”.

![A screenshot showing where to select the "Get All Employee Detail" permission is located in the Access People HR Dashboard.](https://images.workoscdn.com/images/7387653b-7d30-4733-96e4-033004396449.png?auto=format&fit=clip&q=50)

On the API Key Generator page, select “Save”.

![A screenshot showing the API Key Generator page in the Access People HR Dashboard.](https://images.workoscdn.com/images/c58ba765-8015-4776-8fe0-6260de530d52.png?auto=format&fit=clip&q=50)

Copy and save the API key – this will be used in Step 3.

![A screenshot showing the copy icon in the Access People HR Dashboard.](https://images.workoscdn.com/images/a8248b85-173a-4f6b-812f-f58b9abfc9f1.png?auto=format&fit=clip&q=50)

---

## (2) Create your Directory Sync Connection

Login to your WorkOS dashboard and select “Organizations” from the left hand Navigation bar

Select the Organization you’d like to enable an Access People HR Directory Sync connection for.

On the Organization’s page click “Manually Configure Directory”.

![A screenshot showing where to find “Manually Configure Directory” for an Organization in the WorkOS Dashboard.](https://images.workoscdn.com/images/ed383bc9-e626-4d2c-bbfd-78dbe8bbc5d4.png?auto=format&fit=clip&q=50)

Select “Access People HR” as the Directory Provider, and then provide a descriptive name for the connection. Select “Create Directory”.

![A screenshot showing Create Directory details in the WorkOS Dashboard.](https://images.workoscdn.com/images/cc5dde6b-4eda-4af7-bcb9-3ec958e6bc79.png?auto=format&fit=clip&q=50)

---

## (3) Setup your Directory Sync Connection

In the directory details section, select “Update Directory”.

![A screenshot showing where to find "Update Directory" in the WorkOS Dashboard.](https://images.workoscdn.com/images/b0b0e10f-59ab-43da-b348-52b5d53bd299.png?auto=format&fit=clip&q=50)

Enter your API Key from Step 1, and select “Save Directory Details”.

![A screenshot showing where to enter your API Key in the WorkOS Dashboard.](https://images.workoscdn.com/images/31881779-5153-4193-a5bd-316b9684650b.png?auto=format&fit=clip&q=50)

---

## (4) Sync Users and Groups to Your Application

Now, you should see users and groups synced over from Access People HR.

Departments from Access People HR are synced as groups in WorkOS. All users are synced, but only those marked as “ACTIVE” or “LEAVER_MARKED” have a state of active.

---

## Frequently asked questions

### How often do Access People HR directories perform a sync?

Access People HR directories poll every 30 minutes starting from the time of the initial sync.


## FGA {#fga}

### Warrants

Warrants specify relationships between resources in your application.

**Warrants** are access rules that specify relationships between the resources in your application (e.g. `[store:A] is [parent] of [item:123]`). WorkOS FGA uses the set warrants and resource types for an application to answer access checks and queries. Individual warrants define explicit relations between resources while resource types define rules (policies) by which some relationships can exist implicitly.

## Overview

```shell
   tenant:stark-industries  #  admin  @  user:tony-stark
              |                  |              |
           Resource           Relation       Subject
```

Each warrant is composed of three core attributes and an optional _policy_ (more on this later):

- **Resource** - This is the resource the warrant specifies a relationship on. The resource is broken down into a `resource_type` and a `resource_id`. The `resource_type` must refer to a valid [resource type](/fga/schema/schema-syntax/resource-types) defined for the application. The `resource_id` must be a unique identifier used by the application to identify the resource.
- **Relation** - This is the relationship the warrant specifies between the resource and the subject. The relation must be one of the defined [relations](/fga/schema/schema-syntax/relations) on the referenced `resource_type`. It is often used to specify an action the warrant will grant the subject the ability to perform on the resource (e.g. `editor`, `viewer`, etc.).
- **Subject** - This is the resource being granted the specified relation. Like the resource, the subject is broken down into a `resource_type`, and a `resource_id`, and optionally a `relation` (to specify a group of subjects). A subject's `resource_type` must refer to a valid resource type defined for the application, and its `resource_id` must be a unique identifier used by the application to identify the resource. While the subject will often times be an individual user or resource, the subject can also specify a _group_ of resources (e.g. in [group warrants](#group-warrants)).
- **Policy** (optional) - The policy specifies an additional boolean expression to be evaluated _at the time of each check/query request_. The provided expression can reference arbitrary variables which can be provided in check or query requests as _context_. Given some context at check/query time, a warrant's policy must evaluate to `true` in order for the warrant to be considered a match for the check/query. If a warrant's resource, relation, and subject attributes do not match the requested check/query **or** the policy expression evaluates to `false`, the warrant will not be matched during evaluation of the check/query. The policy attribute can be used to implement a form of attribute-based access control (ABAC).

Here is an example warrant specifying that the subject `user:ABC` has the relation `editor` on resource `item:123`:

```json
{
  "resource_type": "item",
  "resource_id": "123",
  "relation": "editor",
  "subject": {
    "resource_type": "user",
    "resource_id": "ABC"
  }
}
```

## Direct Warrants

A direct warrant represents a relationship between a resource and a _specific_ subject. For example, we can define a warrant specifying that `[user:1] is a [member] of [role:admin]`:

```json
{
  "resource_type": "role",
  "resource_id": "admin",
  "relation": "member",
  "subject": {
    "resource_type": "user",
    "resource_id": "1"
  }
}
```

## Group Warrants

In some cases, we might need to specify a relationship between a resource and a _group_ of subjects (e.g. `[member]s of [role:admin]`, `[manager]s of [tenant:acme]`, etc). Group warrants are warrants that include the optional `relation` attribute on the `subject`. They specify that _all_ resources matching the subject's `resource_type`, `resource_id`, and `relation` will have the specified `relation` on the resource. For example, we can define a group warrant specifying that `[member]s of [role:admin] are [editor]s of [report:1]`:

```json
{
  "resource_type": "report",
  "resource_id": "1",
  "relation": "editor",
  "subject": {
    "resource_type": "role",
    "resource_id": "admin",
    "relation": "member"
  }
}
```

It's important to note that resource inheritance rules achieve the same thing as group warrants, but group warrants are a data-first approach. Group warrants are typically used as an exception for certain resources that might have different sets of requirements than the schema. We typically recommend using resource inheritance rules over group warrants because it is easier to manage a single schema than a set of group warrants defined on several different resources.

## Wildcard Warrants

While FGA is designed to model fine-grained authorization, some use-cases call for more coarse-grained access to individual resources. For example, publicly sharing read privileges on a particular document with all users. Scenarios like this can be modeled using wildcard warrants. A wildcard warrant is a warrant that specifies a wildcard (`*`) for the `subject_id` attribute. This means the warrant applies to _all_ subjects of the specified `subject_type`. Note that group warrants cannot specify a wildcard as the `subject_id`. Here is an example of a wildcard warrant that grants _all users_ `viewer` access to `document:doc_123`:

```json
{
  "resource_type": "document",
  "resource_id": "doc_123",
  "relation": "viewer",
  "subject": {
    "resource_type": "user",
    "resource_id": "*"
  }
}
```

## Creating and Managing Warrants

Warrants can be created directly in the [FGA dashboard](https://fga.workos.com) or programmatically via API. Refer to the [Warrants API Reference](/reference/fga/warrant/list) to learn more about managing Warrants via API.

### Warrant Tokens

Configure whether you favor performance or consistency on a per request basis depending on your application's consistency requirements.

## Overview

FGA is a distributed service deployed to multiple cloud regions. All traffic to the FGA API flows through a single endpoint (`api.workos.com/fga`). To ensure reliability, data is replicated to multiple regions behind the scenes. To maximize performance, FGA is an _eventually consistent_ service by default.

In order to balance performance and consistency, FGA supports a _bounded staleness protocol_ similar to Google Zanzibar's _Zookie_ protocol. This allows client applications to specify when they prefer the fastest results (to minimize latency added by authorization checks) and when they prefer immediately consistent results (to ensure recent changes to permissions are reflected for a particular check or query).

FGA generates an opaque token (known as a _Warrant Token_) for all warrant _write_ operations (i.e. creating or deleting warrants). Each Warrant Token uniquely identifies a warrant write operation. All warrant write operations return a Warrant Token in the response body.

```shell
{
  "warrant_token": "MjM0fDM0MzQyM3wyMTM0MzM0MzY0NQ=="
}
```

## `Warrant-Token` Header

Unlike traditional eventually-consistent distributed systems, FGA allows clients to specify their desired consistency level via Warrant Tokens. Clients can pass a previously generated Warrant Token via the `Warrant-Token` header on check, query, and list warrants requests to instruct the server to process the request using data _no older_ than the write operation identified by the specified Warrant Token. This allows clients to ensure that a particular check, query, or list warrants request has the data necessary to give the most up-to-date result as dictated by the application's authorization requirements.

### `latest`

In some cases, a client may need an up-to-date result but may not have an accompanying Warrant Token to use for the request. In this scenario, the client can pass the special value `latest` in the `Warrant-Token` header to instruct FGA to use the most up-to-date data:

```shell
'Warrant-Token: latest'
```

Note that using the `latest` token effectively instructs FGA to bypass all caches in favor of hitting the database for the most up-to-date result. Therefore, it can incur additional performance overhead, so it's recommended to only use `latest` sparingly. Instead, opt to use server-provided Warrant Tokens or no token at all (the default consistency) to maximize performance in most cases.

## Storing Warrant Tokens

In practice, clients can store Warrant Tokens in their system on a _per-subject_ basis, passing in the stored token to each read request for that subject to achieve optimal performance. For example, if creating a new warrant (e.g. `user:x is an editor of report:y`) generates a Warrant Token with value `45f87sdf=`, the client can store that token their db along for subject `user:x`. Subsequent checks or queries for `user:x` can then include that stored Warrant Token for the optimal balance of performance and consistency.

## Default consistency

Passing a Warrant Token on check, query, and list warrants requests is optional. If a Warrant Token is not provided, FGA uses a default staleness window to fulfill check and query requests. This window is cache-optimized and is the recommended approach for the 90-95% of read requests that can tolerate short periods (on the order of seconds) of inconsistent results.

### Schema

Define authorization logic independently from application code using a domain-specific language (DSL).

## Overview

A schema is the core structure of an authorization model in FGA. It defines the types of resources, the relations between them, and the policies that govern access.

A schema can be represented in two formats:

- **JSON** – Accepted by [Schema API](/reference/fga/schema) endpoints when using `Content-Type: application/json`.
- **FGA Schema Language** – A more developer-friendly domain-specific language (DSL) that is applied via the `apply` command with the CLI or on the [FGA Dashboard](https://fga.workos.com/schema).

Schemas allow you to manage authorization logic independently from application logic. They can be versioned, stored in Git, and applied via the CLI:

```shell
workos fga schema apply ./schema.txt
```

Once applied, changes take effect immediately, meaning any updates to authorization logic will instantly reflect in subsequent permission checks and queries.

FGA Schema Language transpiles into JSON format so that you can write your authorization model in a more readable and maintainable way, but still use JSON for API calls if you prefer.

## JSON vs Schema Language

The JSON representation of a schema is the raw format that FGA uses to define resource types, relations, and inheritance rules. However, it can be verbose and difficult to read - especially for complex authorization models.

Consider the following examples:

### JSON Representation

```json
{
  "resource_types": [
    {
      "type": "user",
      "relations": {
        "manager": {
          "allowed_types": ["user"]
        }
      }
    },
    {
      "type": "store",
      "relations": {
        "owner": {
          "allowed_types": ["user"]
        },
        "editor": {
          "allowed_types": ["user"],
          "inherit_if": "owner"
        },
        "viewer": {
          "allowed_types": ["user"],
          "inherit_if": "editor"
        }
      }
    },
    {
      "type": "item",
      "relations": {
        "owner": {
          "allowed_types": ["user"]
          "inherit_if": "owner",
          "of_type": "store",
          "with_relation": "parent"
        },
        "editor": {
          "allowed_types": ["user"],
          "inherit_if": "any_of",
          "rules": [
            {
              "inherit_if": "owner"
            },
            {
              "inherit_if": "editor",
              "of_type": "store",
              "with_relation": "parent"
            },
            {
              "inherit_if": "manager",
              "of_type": "user",
              "with_relation": "owner"
            }
          ]
        },
        "viewer": {
          "allowed_types": ["user"],
          "inherit_if": "editor"
        },
        "parent": {
          "allowed_types": ["store"]
        }
      }
    }
  ]
}
```

### Schema Language Representation

```fga
version 0.3

type user
    relation manager [user]

type store
    relation owner [user]

    relation viewer [user]
    inherit viewer if
        relation editor // editors are also viewers

    relation editor [user]
    inherit editor if
        relation owner

type item
    // An item can have a parent store
    relation parent [store]

    relation owner [user]
    inherit owner if
        relation owner on parent [store]

    relation editor [user]
    inherit editor if
        any_of
            relation owner
            relation editor on parent [store]
            relation manager on owner [user]

    relation viewer [user]
    inherit viewer if
        relation editor
```

The FGA schema language representation is more concise, easier to read, and supports comments. These features make it simpler to define and manage complex authorization models in a more developer-friendly format.

## Schema Syntax

### Version

Each schema must start with a `version` declaration. This version declaration dictates the version of the schema language the transpiler will use to convert the schema into its JSON representation. As we add support for new features and functionality to the schema language, we will release new versions of it. Versioning the language in this way allows us to ensure backwards compatibility as we roll out these enhancements. See a full changelog of schema versions [here](/fga/schema/schema-changelog).



### Comments

Comments are prefixed with `//`. Comments are ignored by the transpiler.



### Resource Types

Resource types are the basic building blocks of an authorization model in FGA. Each resource type defines a set of relationships that can exist on a specific type of resource (e.g. store, item, etc). These relationships can be assigned to other resources (e.g. user) known as subjects.

Resource types are an incredibly flexible way to define authorization models, allowing you to express complex hierarchical and inherited relationships. They can be created directly in the [FGA dashboard](https://fga.workos.com/schema), via the [Resource Types API](/reference/fga/resource-type/create) or by applying the schema with the CLI.

Let's explore the various attributes of resource types by creating a schema-based authorization model for a simple e-commerce application that has three resource types: users, stores, and items.

First, define a resource type using the `type` keyword. Each resource type must have a unique string as its type. Let's start defining the resource types for our e-commerce application:



### Relations

With the basic definitions above, we've started building an authorization model for our application that will allow us to create fine grained access control rules for stores, items, and users, helping us answer questions like:

```shell
Does [user:1] have the ability to [edit] [item:x]?
is [user:1] the [owner] of [store:3]?
```

In order to create access rules using our resource types, we first need to define the relationships available on a resource of that type. For example, if we want to specify that `[user:A] is an [owner] of [store:S]`, we must add an `owner` relation to the `store` resource type.

By default, a subject can only have a relation on a resource explicitly. This means the relation must be _explicitly_ granted via a [warrant](/fga/warrants).

Let's add some relations to our resource types.

In our application, a store can have `owners`, `editors`, and `viewers`. `owners` and `editors` have more privileged access (like being able to modify details about a store) than `viewers` (who have read-only access).

An item can have the same three relations as a store _plus_ a fourth relation called `parent`. This is because a store can be the `parent` of an item, meaning the item belongs to that store. We'll use this relation later to implement inherited relations on items.

Lastly, our `user` resource type is relatively simple and has one relation: `manager`. This is because a user can be the `manager` of another user. We'll use this relation later to enable inherited relations based on user hierarchies.

Let's add these relations to our resource types:



With these resource types, we can now create authorization rules that specify exactly which users are `owners`, `editors`, and `viewers` of each store or item. We can also assign stores as `parents` of items, and users as `managers` of other users.

Use brackets [] in the schema language after defining a relation to enforce which type(s) of subjects can be assigned the relation.

Use empty type restrictions to define computed relationships with no direct subjects. This is useful for defining a relation that cannot be assigned directly to a subject but is used to make an authorization check from your application.

> Version `0.1` of the schema language does not support type safety on relations.

### Inheritance Rules

While only using explicitly assigned relations to build your authorization model can be powerful, creating warrants for each and every relationship in an application can become tedious or infeasible for larger, more complex use cases. That's why relations can define rules under which they can be inherited (e.g. `a user is an editor of a store if they're an owner of that store`).

There are two ways in which relations can be inherited:

- Relation Inheritance
- Resource Inheritance

#### Relation Inheritance

In practice, it's common for relations to have overlap (e.g. an `owner` has the same privileges as an `editor` + additional privileges). For example, in many applications a user with write privileges inherits read privileges too.

In our example application, an `owner` will inherit both the `editor` and the `viewer` relations, and an `editor` will inherit the `viewer` relation. Instead of having to explicitly assign each of the `owner`, `editor`, and `viewer` relations to a user who is an `owner`, resource types allow you to specify an inheritance hierarchy (e.g. the `editor` relation is inherited if the user is an `owner`) using the `inherit_if` property.

Let's add `inherit  if` rules to our `store` and `item` resource types specifying that:

- `owners` are also `editors`
- `editors` are also `viewers`



With our `inherit  if` rules in place, we can simply grant a user the `editor` relation and they will implicitly inherit the `viewer` relation. `inherit` rules also work recursively on other inherited relations, so assigning a user the `owner` relation will implicitly grant that user _both_ the `editor` and `viewer` relations. This is because `owner` will inherit `editor` and `editor` will in turn inherit `viewer`.

This will simplify our access checks and cut down on the number of warrants we need to create for each user.

#### Resource Inheritance

In many applications, resources themselves have a hierarchy (e.g. a document belongs to a folder, a user belongs to a team, a team belongs to an organization, etc.) and the access rules for these resources follow that hierarchy (e.g. the owner of a folder is the owner of any document in that folder).

Using the following two rules:

```txt
inherit  if
```

```txt
relation  on  []
```

We can specify that a relation can be inherited when a user has a particular relation (``) on another resource (``) that has a particular relation (``) on the resource we are checking access to.

For example, a user is an `editor` of a document if they are an `editor` of a `folder` that is the document's `parent`. In our example app, let's define the following three resource inheritance rules:

1. A user is an `owner` of an item if that user is an `owner` of a `store` that is the item's `parent`.
2. A user is an `editor` of an item if that user is an `editor` of a `store` that is the item's `parent`.
3. A user is an `editor` of an item if that user is the `manager` of the `user` that is the item's `owner`.

> **NOTE:** Some of the relations below will be [composing multiple inheritance rules together using logical operators](/fga/schema/schema-syntax/logical-operators). We'll cover this in detail later.



These rules make it easy to define inheritance rules for complex relationships between resources so we don't have to create a large number of explicit warrants. Without them, we'd need to create a warrant for every item &harr; store &harr; user relationship in our application. This could easily be thousands, if not hundreds of thousands of rules.

### Logical Operators

With both the two types of relation inheritance rules in our toolkit, we can create authorization models for a majority of use cases, but there are still some scenarios that require a combination of these inheritance rules (e.g. a user is an `editor` of an item if they are an `owner` of that item **OR** they are the `manager` of another user who is an `editor` of that item).

To design authorization models that cover such scenarios, relations can compose multiple inheritance rules using _logical operators_ to form more complex conditions.

The three supported logical operations are `any_of`, `all_of`, and `none_of`.

#### any_of

The `any_of` operation allows you to specify that a relation be inherited if _at least one of_ the rules in the set is satisfied. In other words, it works like the logical _OR_ operation.

The following resource type specifies an `editor-or-viewer` relation that is inherited if the user is an `editor` **OR** if the user is a `viewer`:



#### all_of

The `all_of` rule type allows you to specify that a relation be inherited if _all of_ the rules in the set are satisfied. In other words, it works like the logical _AND_ operation.

The following resource type specifies an `editor-and-viewer` relation that is implicitly granted if the user is an `editor` **AND** the user is a `viewer`:



#### none_of

The `none_of` rule type allows you to specify that a relation be inherited if _none of_ the rules in the set are satisfied. In other words, it works like the logical _NOR_ operation.

The following resource type specifies a `not-editor-and-not-viewer` relation that is implicitly granted if the user is _not_ an `editor` **AND** the user is _not_ a `viewer`:



### Policies

Policies are a way to define custom logic that can be used in your schema. They allow you to create complex rules that go beyond simple relation inheritance. Policies can be defined using the `policy` keyword and can include parameters, expressions, and logical conditions.



Read more about policies in the [Policies documentation](/fga/policies).

### Group Warrants

Define type restrictions on [group warrants](/fga/warrants/group-warrants) by joining the type and expected relation with a `#`. For example, `relation editor [group#member]` means that the `editor` relation can be assigned to warrants where `group` is the subject type and `member` is the subject relation.

Group warrants are a special type of warrant that allow you to define exceptions to schema relationships at runtime. See the [Group Warrant documentation](/fga/warrants/group-warrants) for more details.



If your relation type defines a resource type and no group warrant types, it will default to allow all group warrants.

For example:

```js
// Allows subject_type == "group" and subject_relation == null | 
relation editor [group]

// Allows subject_type == "group" and subject_relation == "member"
relation editor [group#member]

// Allows subject_type == "group" and subject_relation == "member" | "owner"
relation editor [group#member, group#ownwer]

// Allows subject_type == "group" and subject_relation == null | "member"
relation editor [group, group#member]
```

## Converting Schema Language to JSON

You can convert the FGA schema language to JSON using the `workos fga schema convert` command. This command transpiles the schema language into its JSON representation, which can then be used with the FGA API.

```shell
workos fga schema convert schema.txt --to json --output raw > schema.json
```

## Schema Changelog

### v0.3

- Add support for policy in the schema

```fga
version 0.3

type user

type group
    relation member [user]

type asset
    relation access_diagnostics []
    relation service_manager [group]

    inherit access_diagnostics if
        all_of
          relation member on service_manager [group]
          policy is_in_geo_fence

policy is_in_geo_fence(user_location map, geofence map) {
    user_location.lat >= geofence.min_lat &&
    user_location.lat <= geofence.max_lat &&
    user_location.lon >= geofence.min_lon &&
    user_location.lon <= geofence.max_lon
}

```

### v0.2

- Add support for resource-type relation type safety
- Add support for group warrant types

```fga
version 0.2

type report
    relation parent [organization, organization#member]
    relation owner [user]
    relation editor [user]
```

### v0.1

- Initial implementation of the schema language
- Supported features:
  - Transpiler version
  - Resource types
  - Relations
  - Inheritance rules
  - Resource inheritance
  - Logical operators

### Schema Management

Learn how to test, debug, and safely apply changes to your authorization schema and setup a GitOps workflow to automatically validate and apply changes to production.

## Overview

Designing a schema that meets your requirements and using it in production for the first time is only the beginning of your fine-grained authorization journey. As your product's authorization requirements change, you will need to evolve your schema to meet those requirements.

To do this safely, you need a process in place to test, debug, and safely apply changes to your schema in production. In case of bugs, you also need the ability to roll back to a previous (working) schema if needed.

This guide will explain how to use the [FGA Dashboard](https://fga.workos.com) and [WorkOS CLI](https://github.com/workos/workos-cli) to test and debug your schema. We will use the CLI and the [CLI GitHub Action](https://github.com/workos/cli-action) to setup a GitOps workflow that automatically tests and applies changes to your schema as part of your software development life cycle (SDLC).

## Before getting started

To get the most out of this guide, you'll need:

- A [WorkOS account](https://dashboard.workos.com/)
- Your WorkOS [API Key](/glossary/api-key)
- The [WorkOS CLI](/fga/quick-start/1-install-the-workos-cli)

---

## Test Your Schema

Let's create a shell script that uses the WorkOS CLI to test the example schema below.

> Note: we've decided to prefix permissions in our authorization model with `can_` (`can_invite_users`) to imply an action. This is not a required convention, so feel free to use relation names that suit your application.

```fga title="schema.txt"
version 0.3

type user

type organization
    relation role_admin [user]
    relation role_member [user]
    relation can_invite_users []
    relation can_remove_users []
    relation can_view_users []

    inherit role_member if
        relation role_admin

    inherit can_invite_users if
        relation role_admin

    inherit can_remove_users if
        relation role_admin

    inherit can_view_users if
        relation role_member

```

First, apply the schema

```shell title="Apply the example schema"
workos fga schema apply schema.txt
```

Next, use the `fga warrant create` command to setup some warrants.

```shell title="Setup test data"
workos fga warrant create user:acme_admin role_admin organization:org_acme
workos fga warrant create user:acme_member role_member organization:org_acme
```

Then use the `fga check` command with the `--assert` flag to assert that a permission check returns the expected result.

```shell title="Make assertions"
workos fga check user:acme_admin can_invite_users organization:org_acme --assert true
workos fga check user:acme_admin can_remove_users organization:org_acme --assert true
workos fga check user:acme_admin can_view_users organization:org_acme --assert true

workos fga check user:acme_member can_invite_users organization:org_acme --assert false
workos fga check user:acme_member can_remove_users organization:org_acme --assert false
workos fga check user:acme_member can_view_users organization:org_acme --assert true
```

Finally, use the `fga resource delete` command to clean up the test data. This makes it easy to re-run tests with a clean environment in the future.

```shell title="Clean up test data"
workos fga resource delete user:acme_admin
workos fga resource delete user:acme_member
workos fga resource delete organization:org_acme
```

---

## Debug Your Schema

The simplest way to understand (debug) why your schema is (or is not) answering a permission check as you expect it to is via the [Check page](https://fga.workos.com/check) or using the `--debug` flag via the CLI.

### Using the FGA Dashboard

To debug a permission check from the FGA dashboard, navigate to the [Check page](https://fga.workos.com/check). Enter valid arguments for the permission check you want to debug and click `Check Access`. The page will display the result of the permission check and a tree visualizing all of the paths in the authorization graph that were explored to reach the result.

### Using the CLI

To debug a permission check using the CLI, use the `fga check` command with the `--debug` flag:

```shell title="Debug a permission check"
workos fga check user:james can_approve_purchase purchase:pur_123 --debug
```

Permission checks that use the `--debug` flag will output the check result and a tree visualizing all of the paths in the authorization graph that were explored to reach the result.

> Note: running the `fga check` command with the `--debug` flag will execute the check without any caching enabled.

#### Tests

The CLI provides a streamlined way to run multiple tests against your schema using a single `workos fga test command`. The `test` command will set up warrants, perform checks, and handle teardown.

It also supports running multiple test files from a directory, allowing you to organize tests in a structure that fits your application.

```yaml title="org-roles.test.yaml"
setup:
  warrants:
    - subject: user:acme_admin
      relation: role_admin
      resource: organization:org_acme
    - subject: user:acme_member
      relation: role_member
      resource: organization:org_acme

tests:
  - name: acme_admin can invite users
    check:
      subject: user:acme_admin
      relation: can_invite_users
      resource: organization:org_acme
    expect: true

  - name: acme_admin can remove users
    check:
      subject: user:acme_admin
      relation: can_remove_users
      resource: organization:org_acme
    expect: true

  - name: acme_admin can view users
    check:
      subject: user:acme_admin
      relation: can_view_users
      resource: organization:org_acme
    expect: true

  - name: acme_member cannot invite users
    check:
      subject: user:acme_member
      relation: can_invite_users
      resource: organization:org_acme
    expect: false

  - name: acme_member cannot remove users
    check:
      subject: user:acme_member
      relation: can_remove_users
      resource: organization:org_acme
    expect: false

  - name: acme_member can view users
    check:
      subject: user:acme_member
      relation: can_view_users
      resource: organization:org_acme
    expect: true

teardown:
  resources:
    - user:acme_admin
    - user:acme_member
    - organization:org_acme
```

To run the tests defined in the `schema.test.yaml` file, use the following command:

```shell title="Run tests"
workos fga test org-roles.test.yaml
```

> The teardown section is optional and used for cleaning up specific data (resources or warrants). If you want to automatically cleanup **all resources and warrants** created during the test, you can also use the `--cleanup` flag when running the `workos fga test` command.

---

## GitOps Workflow

Now that we have a script to test that our schema works as we expect, let's setup a GitHub Action to automatically test changes to the schema and apply the schema if all of the tests pass.

```yaml title=".github/workflows/fga.yaml"
name: Test FGA Schema

on:
  push:
    branches: [main]

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - name: Install WorkOS CLI
        uses: workos/cli-action@v1
        with:
          version: latest
      - name: Test Schema
        run: |
          workos fga schema apply schema.txt
          workos fga test tests/org-roles.test.yaml
        env:
          WORKOS_ACTIVE_ENVIRONMENT: staging
          WORKOS_ENVIRONMENTS_HEADLESS_API_KEY: 
      - name: Apply Schema to Production
        if: github.ref == 'main' && github.event_name == 'push'
        run: |
          workos fga schema apply schema.txt
        env:
          WORKOS_ACTIVE_ENVIRONMENT: production
          WORKOS_ENVIRONMENTS_HEADLESS_API_KEY: 
```

### Resources

Resources are FGA's references to your application's access controlled resources.

FGA stores a set of warrants representing relationships between _resources_ in an application. These resources are typically application-specific objects persisted in the application's datastore (e.g. MySQL, PostgreSQL, MongoDB, etc). In FGA, they are referred to as _resources_.

## Overview

```shell
      report    :    balance-sheet
        |                  |
   Resource Type      Resource ID
```

Resources consist of three attributes:

- **Resource Type** - Specifies what _type_ of entity a particular resource is (e.g. a user, a tenant, a report, etc).
- **Resource ID** - Specifies a unique identifier for the resource (typically the same unique identifier used in your application to identify the resource).
- **Meta** (optional) - A JSON object containing additional data related to the resource that it would be helpful for FGA to know about (e.g. a user's email address, a tenant's display name, a description of the privileges a role grants, etc).

Resources make it easier to manage the warrants associated with each resource, providing a way for applications to persist authorization-specific data outside of (or often, in lieu of) their primary datastore.

## Creating and Managing Resources

FGA automatically creates the resources that are referenced by warrants when they are created. This means developers using FGA don't need to worry about manually creating resources.

For example, given the following warrant:

```json title="report:balance-sheet#editor@user:john-doe"
{
  "resource_type": "report",
  "resource_id": "balance-sheet",
  "relation": "editor",
  "subject": {
    "resource_type": "user",
    "resource_id": "john-doe"
  }
}
```

FGA will automatically create two resources upon creation of the warrant:

```json title="report:balance-sheet"
{
  "resource_type": "report",
  "resource_id": "balance-sheet"
}
```

```json title="user:john-doe"
{
  "resource_type": "user",
  "resource_id": "john-doe"
}
```

Resources can be managed from the [FGA Dashboard](https://fga.workos.com) and/or via API. Refer to the [Resources API Reference](/reference/fga/resource/create) to learn more about managing resources via API.

> When a resource is deleted, any warrants associated with the resource will automatically be deleted. This makes it easier for applications to remove all warrants associated with a resource when the resource is deleted from the application itself.

## Metadata

Resources can be augmented with additional authorization-specific metadata (e.g. the display name for a role or permission, the description of a particular feature, etc). Metadata is especially useful when implementing permission-specific user interfaces. For example, when building a customer-facing page for managing team-level roles and permissions, metadata can provide user-friendly names and descriptions of what actions/resources each role or permission will grant to a user.

```json title="user:john-doe w/ metadata"
{
  "resource_type": "user",
  "resource_id": "john-doe",
  "meta": {
    "email": "john-doe@acme-corp.com",
    "isActivated": true
  }
}
```

```json title="role:accountant w/ metadata"
{
  "resource_type": "role",
  "resource_id": "accountant",
  "meta": {
    "name": "Accountant",
    "description": "Allows a user to view the financial reporting pages and edit charges."
  }
}
```

> There is a 50kb limit on the size of the metadata object.

### Quick Start

Set up resource types and warrants that model your authorization requirements. Then use the SDK to make access checks from your application.

## Before getting started

To get the most out of this guide, you should have:

- A [WorkOS account](https://dashboard.workos.com/)
- Your WorkOS [API Key](/glossary/api-key)
- A basic understanding of [resource types](/fga/schema/schema-syntax/resource-types)

## What you'll build

In this guide, we'll implement fine-grained authorization for a simple B2B SaaS application that gives users the ability to build and share reports generated using company data.

We will:

1. Design a resource type schema that models the application's authorization requirements.
2. Create warrants to define relationships between the application's resources.
3. Make access checks that determine whether or not a user should have access to a resource.

## API resource definitions

[Schema](/fga/schema)
: A schema defining the different types of relationships available on your application's resources and how those relationships can be inherited

[Warrant](/fga/warrants)
: A rule assigning a relationship between two resources in your application

## (1) Install the WorkOS CLI

Install the WorkOS CLI using [Homebrew](https://brew.sh/).

```shell
brew install workos/tap/workos-cli
```

To initialize the CLI, use the command below. Follow the prompts to complete setup.

```shell
workos init
```

---

## (2) Define a resource type schema

Our application has three types of resources: reports, teams, and users. Our authorization model should meet the following requirements:

- Every report belongs to a team.
- Every user belongs to a team.
- Users who create a report are considered the owner of the report.
- The owner of a report can also edit the report.
- The owner of a report can add other users as editors.
- An editor of a report can also view the report.
- Users can view any report belonging to their team.

We'll define the following resource type schema to fulfill these requirements:

```fga title="schema.txt"
version 0.3

type user

type team
  relation member [user]

type report
  relation parent [team]
  relation owner [user]
  relation editor [user]
  relation viewer [user]

  inherit editor if
    relation owner

  inherit viewer if
    any_of
      relation editor
      relation member on parent [team]

```

### (A) Using the CLI

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to update your schema in WorkOS FGA.

```shell
workos fga schema apply schema.txt
```

### (B) Using the FGA Dashboard

Define a resource type schema from the FGA dashboard using the schema editor available on the [Schema](https://fga.workos.com/schema) page.

---

## (3) Create warrants

Warrants are rules that assign relationships between the resources in an application. These relationships are then used to figure out whether or not a user should have access to a resource.

For example, let's create two warrants:

- One specifying that `[user:d6ed6474-784e-407e-a1ea-42a91d4c52b9] is a [member] of [team:stark]`
- One specifying that `[team:stark] is [parent] of [report:7]`

### (A) Using the CLI

Create warrants using the CLI.

```shell
workos fga warrant create user:d6ed6474-784e-407e-a1ea-42a91d4c52b9 member team:stark
workos fga warrant create team:stark parent report:7
```

### (B) Using the SDK



Create warrants programmatically from your application using the SDK.



---

## (4) Check and query access

Now that we have our resource types and some warrants set up, we can check and query access.

Since we assigned `[team:stark]` as the `parent` team of `[report:7]` and `[user:d6ed6474-784e-407e-a1ea-42a91d4c52b9]` as a `member` of `[team:stark]`, they should automatically be a `viewer` of `[report:7]`. Let's do a check to make sure.

### (A) Using the CLI

Check if a subject has a given relation on a resource.

```shell title="Check if user is viewer of report:7"
workos fga check user:d6ed6474-784e-407e-a1ea-42a91d4c52b9 viewer report:7
```

Query which resources a user has a given relation on.

```shell title="List reports where user is a viewer"
workos fga query 'select report where user:d6ed6474-784e-407e-a1ea-42a91d4c52b9 is viewer'
```

### (B) Using the SDK

Check if a subject has a given relation on a resource.



Query which resources a user has a given relation on.



---

## Summary

That's it! We've now setup a powerful authorization system for our application that features a hierarchy of privileges (owner → editor → viewer) and inheritance of privileges based on team membership.

### Query Language

Query which resources users have access to in your application.

The Query Language is a declarative, SQL-like language used to [query](/reference/fga/query) WorkOS FGA for (1) the set of resources a particular subject has access to or (2) the set of subjects who have access to a particular resource. Examples of queries that can be specified with the query language include:

1. List all documents `user:A` is a `viewer` on.
2. List all users who are `editor`s of `document:finance-report`.
3. List all resources `user:malicious` has access to.
4. List all users who have the permission `view-financial-reporting`.
5. and many more

## Overview

A query is composed of a `select` clause and either a `for` clause (if querying for subjects) or a `where` clause (if querying for resources):

```sql
select permission where user:tony-stark is member
```

## Select Clause

The **select clause** specifies whether a query should return resources a subject has access to or return subjects that have access to a resource.

### Select Resources

Return resources a subject has access to

```sql
select 
```

> `` can be a comma separated list of one or more resource types that results of the query will be filtered to. To select resources matching _any_ resource type, pass a wildcard (`*`) instead.

### Select Subjects

Return subjects that have access to a resource.

```sql
select  of type 
```

> `` and `` can be comma separated lists of one or more relations or one or more resource types respectively, that results of the query will be filtered to. To match _any_ relation or _any_ subject type, pass a wildcard (`*`) for the `` or `` properties respectively.

## Where Clause

When selecting resources (e.g. `select tenant`), provide a `where` clause to specify a subject and one or more relations that subject must have on any resources returned in the query result.

```sql
select  where  is 
```

> `` must be a resource in the format `:`. `` can be a comma separated list of one or more relations. To match _any_ relation, pass a wildcard (`*`) instead.

## For Clause

When selecting subjects (e.g. `select member of type user`), provide a `for` clause to specify a resource and one or more relations subjects must have on the specified resource to be returned in the query result.

```sql
select  of type  for 
```

> `` and `` can be comma separated lists of one or more relations or one or more resource types respectively. To match _any_ relation or _any_ resource type respectively, pass a wildcard (`*`) instead.

### Implicit vs. Explicit Results

A query can optionally include the `explicit` keyword immediately following the `select` keyword to indicate that the query should _only_ return results that _explicitly_ match the provided relations. Explicit results are results for which a warrant matching one or more of the relations specified in the query explicitly exists. Implicit results are results which may implicitly match the relations specified in the query through [inheritance rules](/fga/schema/schema-syntax/inheritance-rules). Without the `explicit` keyword specified, a query will return both explicit and implicit results.

```sql title="Example: Get all users who explicitly have the viewer relation on document:doc1"
select explicit viewer of type user for document:doc1
```

```sql title="Example: Get all users who have the viewer relation on document:doc1 explicitly OR implicitly"
select viewer of type user for document:doc1
```

## Limitations

### Schema policies

Schema policies are **not supported** in the current Query implementation. Any access results that are granted only by schema policies (as determined via the [check endpoint](/reference/fga/check)) will be excluded from query responses.

This limitation exists because schema policies are fundamentally more complex than warrant policies. While warrant policies apply to specific relationships (e.g., user:1 is viewer of document:doc1), schema policies define rules that apply across all resources of a certain type and relation — for example, every viewer of every document.

This generalization introduces two core issues:

1. **Scalable Evaluation**: The query engine would have to evaluate every resource of type B for every relation A, leading to major performance bottlenecks at scale.
2. **Security and UX Risks**: Alternatively, returning wildcard-based access (e.g., “user has access to resource type B:\*”) increases the risk of unintended data exposure and shifts the burden of filtering valid results to the application layer.

Given these challenges, schema policies should be evaluated like traditional policy engines — by explicitly checking access between individual subjects and resources. This is what the check endpoint is for.

> Warrant policies are supported in query, since they conditionally create specific relationship edges rather than applying general rules.

To check access to a list of resources when using schema policies, you have two options:

1. Convert schema policies into equivalent warrant policies where feasible.
2. Use the batch check endpoint to validate access for many resources individually.

### No Joins

The query engine does not support join semantics across relationships. For example, a query like:

```sql title="Invalid query"
select viewer of type user for document:doc1 where group is viewer
```

…is not supported directly.

To achieve a similar behavior, you could do one of the following:

#### 1. (Recommended) Define a new relation in your schema that does the join via [inheritance rules](/fga/schema/schema-syntax/inheritance-rules)

```fga title="Example: Define a new relation in schema to join viewer and group"
type user

type group
  relation member [user]

type document
  relation viewer [user, group]
  relation group_viewer []

  // Query for documents where a user is a viewer through their group membership
  inherit group_viewer if
    relation member on viewer [group]

  inherit viewer if
    relation member on viewer [group]
```

Then you can query for the new relation:

```sql title="Example: Get all users who are viewers of document:doc1 through their group membership"
select group_viewer of type user for document:doc1
```

If you want to intersect results of two queries, you can use an `all_of` rule in your schema to define a new relation that combines the results of two existing relations. For example:

```fga title="Example: Define an all_of rule to combine viewer and group membership"
type document
  relation subscriber [user]
  relation owner [group]

  inherit subscriber_and_owner if
    all_of
       relation owner
       relation subscriber

  inherit owner if
    relation member on owner [group]
```

Then you can query for the new relation:

```sql title="Example: Get all users who are both subscribers and owners (through a group membership) of document:doc1"
select subscriber_and_owner of type user for document:doc1
```

#### 2. Chain queries and combine results in application logic

```sql title="Example: Get all users who are viewers of document:doc1 and user:1 is a viewer"
select viewer of type group for document:doc1
select member of type user for group:xyz // using groups from prior query
```

#### 3. Use a [batch check](/reference/fga/batch-check) to check access on multiple resources returned by a query

```sql title="Example: Batch check access for multiple resources returned by a query"
select viewer of type group for document:doc1
```

Then you can batch check `user:xyz` on all `viewer groups` for `document:doc1`.

## Examples

```sql title="Get all documents on which user:1 is a viewer (either explicitly or implicitly)"
select document where user:1 is viewer
```

```sql title="Get all documents on which user:1 is explicitly a viewer"
select explicit document where user:1 is viewer
```

```sql title="Get all documents on which user:1 has any relation (either explicitly or implicitly)"
select document where user:1 is *
```

```sql title="Get all resources of any type on which user:1 has any relation (either explicitly or implicitly)"
select * where user:1 is *
```

```sql title="Get all users who are viewers of document:doc1 (either explicitly or implicitly)"
select viewer of type user for document:doc1
```

```sql title="Get all users who are explicitly viewers of document:doc1"
select explicit viewer of type user for document:doc1
```

```sql title="Get all users who have any relation on document:doc1 (either explicitly or implicitly)"
select * of type user for document:doc1
```

```sql title="Get all subjects of any type who have any relation on document:doc1 (either explicitly or implicitly)"
select * of type * for document:doc1
```

### Policies

Use policies to implement advanced attribute based access control with FGA, providing relevant data from your application at access control check time.

WorkOS FGA allows you to define custom logic that is executed when evaluating access checks. A **policy** is a [boolean expression](https://en.wikipedia.org/wiki/Boolean_expression) that specifies additional conditions to be satisfied in order for an access check to be authorized. Use policies to enforce complex rules and conditions that go beyond simple role-based access control (RBAC) or attribute-based access control (ABAC).

Policies can be defined on warrants or as part of your schema.

> FGA currently supports defining policy expressions using [expr](https://expr-lang.org/docs/language-definition). Support for more policy languages will be coming soon.

## Warrant Policies

You can optionally include a policy in a warrant. For a warrant to match a check/query, its policy must evaluate to true. The system evaluates policies after matching the warrant based on its resource, relation, and subject attributes. It evaluates the policy in the context of the check/query request, using any dynamic values provided via the context attribute (see [context](fga/policies/warrant-policies/context) below) to process the expression.

For example, the following warrant states that `[role:accountant] is a [member] of [permission:view-profits-and-losses]` _only when_ `companyId == 'wayne-enterprises'`:

```json
{
  "resource_type": "permission",
  "resource_id": "view-profits-and-losses",
  "relation": "member",
  "subject": {
    "resource_type": "role",
    "resource_id": "accountant"
  },
  "policy": "companyId == 'wayne-enterprises'"
}
```

Policies can reference dynamic variables. You must provide values for these variables in check or query requests via the context attribute (e.g., role, tenant, or geographic location). Before evaluating a policy, the system substitutes the provided values into the expression. Policy expressions undergo static type checking, so type mismatches prevent evaluation from returning true. Policies with missing values or evaluation errors also do not return true. The system compiles and statically checks policies for errors upon creation.

Policies have numerous uses but are most commonly used to implement forms of attribute-based access control (ABAC). For example, create a warrant that only matches users visiting from a specific IP address:

```json
{
  "resource_type": "database",
  "resource_id": "prod",
  "relation": "admin",
  "subject": {
    "resource_type": "user",
    "resource_id": "ops-user"
  },
  "policy": "user.client_ip == '192.168.1.1'"
}
```

Combine policies with role-based access control (RBAC) to support different role/permission mappings per customer or tenant. For example, define a warrant stating that `[role:accountant]` grants `[permission:view-balance-sheet]` only when `companyId == 'wayne-enterprises'`:

```json
{
  "resource_type": "permission",
  "resource_id": "view-balance-sheet",
  "relation": "member",
  "subject": {
    "resource_type": "role",
    "resource_id": "accountant"
  },
  "policy": "companyId == 'wayne-enterprises'"
}
```

Create another warrant specifying that `[role:accountant]` grants users `[permission:view-profits-and-losses]` only when `companyId == 'daily-planet'`:

```json
{
  "resource_type": "permission",
  "resource_id": "view-profits-and-losses",
  "relation": "member",
  "subject": {
    "resource_type": "role",
    "resource_id": "accountant"
  },
  "policy": "companyId == 'daily-planet'"
}
```

### Context

[Make access checks](/reference/fga/check), passing in different `companyId` values via the `context` based on the company a user belongs to:

```json
{
  "checks": [
    {
      "resource_type": "permission",
      "resource_id": "view-profits-and-losses",
      "relation": "member",
      "subject": {
        "resource_type": "role",
        "resource_id": "accountant"
      },
      "context": {
        "companyId": "wayne-enterprises"
      }
    }
  ]
}
```

This access check returns `false` because `[role:accountant]` only grants `[permission:view-profits-and-losses]` within the context of company `daily-planet`.

## Schema Policies

You can reference policies in your schema, allowing you to define and reuse complex rules across different relations and inheritance rules. Use policies in the inherit clause of your schema definition.
For example, consider the following schema:

```fga
version 0.3

type user

type organization
    relation viewer [user]

    relation view []
    inherit view if
        all_of
          policy ip_allowed
          relation viewer

policy ip_allowed(clientIp string) {
    clientIp matches "192\\.168\\..*\\..*"
}
```

Here, the `view` relation is inherited based on the ip_allowed policy and the viewer relation. This means that users must meet the conditions of the `ip_allowed` policy and also be in the `viewer` relation to access the `view` permission.

`view` has no allowed types, so it cannot be assigned a warrant directly. Instead, it inherits from the `viewer` relation and the `ip_allowed` policy so that we can check if a user is in the `viewer` relation and also meets the conditions of the `ip_allowed` policy.

> Make sure schema version is set to `0.3` or higher to use policies in your schema.

### Defining and Using Policies

Policies can be defined in the Schema Editor of the WorkOS FGA Dashboard or via the API. Each policy consists of the following fields:

- **name** - a unique identifier for the policy
- **language** - currently only `expr` is supported
- **parameters** - define which values the policy accepts
- **expression** - the boolean expression that defines the policy

#### Policy Syntax

`Expr` policies are defined directly in your FGA schema, making it easy to view policies alongside your inheritance rules. More languages will be supported in the future and managed through a different user interface.

```txt
policy ( , ...) {
    
}
```

> View `expr` language [documentation](https://expr-lang.org/docs/language-definition).

Policies are referenced in inheritance rules using their name.

```txt
inherit  if
    policy 
```

### Attribute-Based Access Control (ABAC)

You can use policies to implement pure attribute-based access control (ABAC) without any inheritance rules or warrant data. This allows you to define access control based solely on user attributes or other context values as you would with a policy engine. For example:

```fga
version 0.3

type user

type organization
    relation view_internal_settings []
    inherit view_internal_settings if
        policy staff_user

policy staff_user(user map) {
    user.email endsWith "@internal-domain.com" && user.role == "staff"
}
```

In this example, the `view_internal_settings` relation inherits from the `staff_user` policy. This means only users with a staff role and an email ending in `@internal-domain.com` can access `view_internal_settings`.

Since this policy is the sole inheritance rule for `view_internal_settings`, FGA does not check for warrants when evaluating access. This allows you to use FGA purely as an attribute-based access control (ABAC) system if desired.

### Combining Policies with ReBAC

Policies can also be combined with ReBAC inheritance rules to create more complex access control models. Consider the following example:

```fga
version 0.3

type user

type organization
    relation admin [user]
    relation configure_payments [user]

    inherit configure_payments if
        all_of
            relation admin
            policy has_strong_auth

policy has_strong_auth(user_attributes map) {
    user_attributes.mfa_enabled == true &&
    user_attributes.account_age_days > 30
}
```

In this example, the `configure_payments` relation inherits from both the `admin` relation and the `has_strong_auth` policy. This means that users must be an admin and meet the strong authentication requirements to access the `configure_payments` relation.

## Managing Policies via API

WorkOS FGA provides API endpoints if you prefer managing policies programmatically and separately from the schema.

For more details, see the [Policies API documentation](/reference/fga/policy).

## Making Checks

When making an FGA check, pass the required context values as you would with warrant policies. FGA evaluates warrant and schema policies together during access checks.

```json
{
  "checks": [
    {
      "resource_type": "organization",
      "resource_id": "acme-corp",
      "relation": "configure_payments",
      "subject": {
        "resource_type": "user",
        "resource_id": "123"
      },
      "context": {
        "user_attributes": { "mfa_enabled": true, "account_age_days": 45 }
      }
    }
  ]
}
```

## Policies in Schema JSON

Policies can also be defined in the schema JSON format. Here’s an example of how to define a policy in JSON:

```json
{
  "version": "0.3",
  "resource_types": {
    "user": {},
    "organization": {
      "relations": {
        "view": {
          "policy": "ip_allowed"
        }
      }
    }
  },
  "policies": {
    "ip_allowed": {
      "name": "ip_allowed",
      "language": "expr",
      "parameters": [
        {
          "name": "clientIp",
          "type": "string"
        }
      ],
      "expression": "clientIp matches \"192\\\\.168\\\\..*\\\\..*\""
    }
  }
}
```

> At runtime, if a policy fails to evaluate due to an invalid or missing context parameter, the system will return a 400 Bad Request in response to the check or query.

## Advanced Usage

### Injected Context

Policies can reference dynamic variables that are injected by the FGA system **at runtime**. When a policy is evaluated, the system substitutes the provided values into the expression. This allows you to create policies that depend on runtime context, such as warrant data that the policy is stored with or check arguments.

#### `check_ctx`

A map containing the subject, resource, and relation of the check (or sub-check) executing the policy. This context variable is only available when the policy is evaluated in the context of a check (otherwise it is an empty map).

```json title="check_ctx"
{
  "subject_type": "user",
  "subject_id": "123",
  "relation": "view_feature_1",
  "resource_type": "organization",
  "resource_id": "acme-corp"
}
```

```fga
policy is_user_in_org(user_attributes map) {
  check_ctx.resource_type == "organization" && user_attributes.organization_id == check_ctx.resource_id
}
```

Use `check_ctx` in a policy when:

- **You want to avoid duplicating check arguments in context**\
  Instead of manually passing `subject_id`, `resource_type`, or `relation` as context values in every access check, reference them directly via `check_ctx` to reduce redundancy and simplify your check requests.

- **Your policy logic needs to vary based on the check's subject or resource**\
  For example, use `check_ctx` when applying different rules depending on whether the subject is a `user` or `service`, or if the resource type is `document` versus `organization`.

- **You're leveraging [policy helper functions](/fga/policies/advanced-usage/helper-functions)**\
  Pass resource ids from `check_ctx` into helper functions.

#### `warrant_ctx`

A map containing the subject, resource, and relation of the warrant that the policy was stored on. This context variable is only available when the policy is stored on a warrant (otherwise it is an empty map).

```json title="warrant_ctx"
{
  "subject_type": "user",
  "subject_id": "123",
  "relation": "editor",
  "resource_type": "organization",
  "resource_id": "acme-corp",
  "created_at": "2023-10-01T00:00:00Z"
}
```

```fga
policy warrant_not_expired() {
  let expiration = duration("1h");
  date(warrant_ctx.created_at) > now() + expiration
}
```

Use `warrant_ctx` in a policy when:

- **You need time-based or expiring access control**\
  Reference `warrant_ctx.created_at` to enforce temporal constraints like short-lived or trial permissions.

- **Your policy behavior depends on the warrant’s subject, resource, or relation**\
  For example, restrict logic to apply only if the warrant’s `relation` is `"editor"` or `resource_type` is `"project"`.

- **You need to evaluate policies only within warrant-based contexts**\
  Helps enforce logic that should not apply in schema-only (inheritance) scenarios.

- **You're using [policy helper functions](/fga/policies/advanced-usage/helper-functions)**\
  Pass resource ids from `warrant_ctx` into helper functions.

> Context variables can be empty if the policy is not evaluated in the context of a check or warrant. Make sure to check for empty values in your policy expressions to avoid errors.

### Helper Functions

In addition to all of the built-in functions available in the [expr language](https://expr-lang.org/docs/language-definition), FGA provides the following helper functions for use in policies:

#### `get_metadata`

Fetches metadata for a given resource type and id when a policy is evaluated. This allows you to access metadata attributes stored on the resource in FGA without having to pass them in as context. This is especially useful when you don't want to update your check requests to include additional context values after schema changes.

```fga
policy user_in_org() {
  let subject_metadata = get_metadata(check_ctx.subject_type, check_ctx.subject_id);
  subject_metadata.organization_id == check_ctx.resource_id &&
    check_ctx.subject_type == "user" &&
    check_ctx.resource_type == "organization"
}
```

> Make sure to check for empty values in your policy expressions to avoid errors. It is best practice to avoid nested keys or use [optional chaining](https://expr-lang.org/docs/language-definition#optional-chaining) to prevent errors when accessing metadata attributes.

#### `jwt_claim`

Retrieves a specific claim from the JWT used to authenticate an access check. This is useful for policy logic that depends on user attributes embedded in the JWT, without needing to explicitly pass them through the context. This helper returns `nil` if a different authentication method (i.e. not a JWT) was used or the claim does not exist.

This also works directly with Custom Attributes from AuthKit [JWT templates](/authkit/jwt-templates), allowing you to access user attributes directly in your policies.

> Ensure your JWKS (JSON Web Key Set) is [properly configured](/fga/identity-provider-sessions) to validate JWT signatures and authorize requests.

```fga
policy user_is_workos_admin() {
  let role = jwt_claim("role");
  let email = jwt_claim("email");

  role == "admin" &&
    check_ctx.subject_type == "user" &&
    email endsWith "@workos.com"
}
```

### Combine with Inheritance Rules

Combine policies with inheritance rules to create complex access control models. For example, define a policy that checks specific conditions and apply it across multiple relations or inheritance rules:

```fga
version 0.3

type user

type staff_group
  relation member [user]

type org_role
  relation member [user]

type organization
  relation internal_admin [staff_group]
  relation viewer [user, org_role]

  relation view_feature_1 []
  inherit view_feature_1 if
    any_of
      relation member on internal_admin [staff_group]
      all_of
        any_of
          relation viewer
          relation member on viewer [org_role]
        policy valid_enterprise_plan

policy valid_enterprise_plan(payment_plan map) {
  payment_plan.is_active == true && payment_plan.tier == "enterprise"
}
```

In this example:

- `view_feature_1` access can be inherited based on multiple conditions.
- Internal admins (`staff_group` members) can access `view_feature_1`.
- Users in `viewer` or an `org_role` can also access it if they meet the `valid_payment_plan` policy requirements.

## Passing Context vs. Injecting Context

When using policies, you can provide context in two ways:
by passing values directly in the check request, or by injecting them into the policy using `get_metadata`. The right approach depends on where your data lives, how often it changes, and how you want to manage changes to your schema or policies.

**Pass context**: Use this method when you want to provide specific values for the policy to evaluate. This is useful for dynamic values that may change frequently or are specific to the check being made.

Passing context also does not require syncing data between your application and FGA, as the context is provided at check time. The major drawback is that it can lead to large check requests if you have many attributes to pass in. This can also make it difficult to manage and maintain the context values over time since changes to your schema or policies may require updates to the context values in your check requests.

**Inject context**: Use this method when you want to fetch metadata or other attributes from the resource itself. This is useful for static values that are stored in FGA and do not change frequently or when you want to avoid passing large amounts of context data in the check request.

Schema or policy changes do not require updates to the context values in your check requests, as the metadata is fetched at runtime. The major drawback is that it requires syncing data between your application and FGA.

See the [Policy Context](/fga/modeling/policy-context) modeling guide for more details on how to use context in your policies.

## Common Use Cases

Using policies and inheritance rules together provides a powerful way to model permissions for:

- **Entitlements** (e.g., feature access based on plan level)
- **Feature flags** (e.g., enabling experimental features for specific groups)
- **Domain-specific logic** (e.g., enforcing security constraints specific data attributes)
- **Temporal data** (e.g., granting temporary access based on time-based or location-based policies)

## Next Steps

To start using policies in your schema, ensure the following:

1. Create policies in the schema or with the Policy API
2. Reference policies in your schema
3. Pass the correct context values when making access checks
4. Test your schema logic using the FGA dashboard and API

### Playground

Use the FGA Playground to explore the capabilities of WorkOS Fine-Grained Authorization.

The [FGA Playground](https://explore.fga.workos.com/playground) runs in the browser and allows you to interact with the schema, warrants, and queries in real-time before implementing them in your application.

![A screenshot of the FGA Playground](https://images.workoscdn.com/images/d2e7e812-17d0-4607-a0c5-db78a4b86207.png?auto=format&fit=clip&q=50)

### Operations & Usage

Understand the operations_consumed metric and how it can help you optimize your FGA usage.

WorkOS Fine-Grained Authorization (FGA) empowers developers to design custom authorization models tailored to their specific needs using Access Control Lists (ACLs). In FGA, ACLs can inherit from one another through explicit connections or custom inheritance rules (see [inheritance rules documentation](/fga/schema/schema-syntax/inheritance-rules)). However, the flexibility of these models can complicate capacity planning for FGA quota.

FGA includes the `operations_consumed` metric in select API responses to provide visibility into quota consumption. This metric measures the computational cost of access checks, queries, and warrant transactions, offering developers valuable insights into how their authorization models affect quota usage.

Complex models with deeply nested data or intricate inheritance rules can significantly increase the computational cost of FGA transactions, making it critical to design models thoughtfully. By understanding the impact of these factors, developers can make informed decisions to balance functionality and efficiency.

This article breaks down the purpose of the `operations_consumed` metric, how it works, and strategies for optimizing FGA usage to better manage quota consumption.

## What is `operations_consumed`?

operations_consumed is a metric that quantifies the number of computational operations performed during an ACL check or query in FGA. These operations include sub-tree checks and partial queries that are required to return the response. By tracking this value, FGA provides visibility into quota consumption, enabling developers to:

- Understand the cost of their authorization checks.
- Optimize their schema for better performance.
- Ensure efficient usage within the provided quota.

```json title="POST /v1/check"
{
  "result": "authorized",
  "is_implicit": true,
  "operations_consumed": {
    "total": 5
  }
}
```

## How Does It Work?

FGA performs access checks by traversing the ACL graph. The ACL graph is defined by warrant connections that are bridged by the inheritance rules defined in your schema. These operations include:

1. **Edge Traversals:** Verifying ACL connectivity through adjacent resources using warrant relations.
2. **Inheritance Rules:** Evaluating relationships based on inherited connections in your schema.
3. **Consistency Operations:** Determining whether fully consistent or eventually consistent results are required.

In addition to schema complexity, the number of operations required to evaluate an access check also depends on sub-tree caching. Fully consistent checks inherently rely less on caching than eventually consistent checks. Eventually consistent checks have less strict cache policies, reducing the number of required sub-tree evaluations. However, requests for eventual consistency are not guaranteed to be served from cache. As a result, _`operations_consumed` may vary slightly across requests, with the worst-case scenario involving no caching._

FGA handles cached operations as follows:

- A single access check on cached data always counts as **one operation**.
- Multiple checks on the same cached result within a single transaction each count as **one operation**.
- Accessing cached sub-trees avoids evaluating the sub-tree, significantly optimizing query execution.

To optimize both performance and cost, it’s essential to use Warrant Tokens (see [Warrant Token documentation](/fga/warrant-tokens)) effectively and align your schema design with your consistency requirements.

## Implications of Graph Structure

The structure of your ACL graph significantly impacts the operations_consumed metric. Here’s why:

- **Nested Graphs:** While some nesting is acceptable, deeply nested relationships can significantly increase the complexity of access checks. Each additional layer in the graph requires more operations to resolve access, potentially impacting performance and query efficiency.

![FGA diagram showing an ACL graph with nested connections](https://images.workoscdn.com/images/9e3a627d-448a-4769-87e5-1de0ee4b5e10.png?auto=format&fit=clip&q=50)

- **Wide Graphs:** Graphs with many/all resources converging on a single node demand more operations per check to resolve access. As your application grows in size and complexity, more connections may focus on a single node. Performance may degrade and usage could increase.

![FGA diagram showing a wide ACL tree](https://images.workoscdn.com/images/bb30073a-aa9a-41aa-a22a-1c5766d610a0.png?auto=format&fit=clip&q=50)

- **Sparse or Disjoint Graphs:** Sparse graphs, where resources and subjects are minimally connected, consume fewer operations. Disjoint sub-graphs, typically separated by tenant or user, are particularly efficient. Both reduce the traversal scope.

![FGA diagram showing disjoint graphs separated by company identifier](https://images.workoscdn.com/images/2d4610e1-8e4c-44e8-bbfd-fe9f66c49731.png?auto=format&fit=clip&q=50)

## Optimizing operations_consumed Usage

To preserve operations and stay within quota limits, developers can utilize the following strategies:

### Sub-graph Separation

Divide ACLs into smaller, independent sub-graphs. This approach reduces the traversal depth and isolates computational effort to specific areas of the graph. For example, building disjoint sub-graphs for different tenants that use your application.

### Favor Eventual Consistency

Use fully consistent checks only when necessary. Opt for eventually consistent checks to increase the likelihood of cache hits. In practice, developers can avoid fully consistent checks by using Warrant Tokens in API requests.

### Cache Warrant Tokens

Store API-generated Warrant Tokens with atomic writes to reuse them for future access checks, minimizing redundant computations. Cached warrant tokens reduce the need to use fully consistent checks.

### Simplify Relationships

Avoid building a model with unnecessary nesting, complicated inheritance rules, or wide connections. Streamlining relationships minimizes the number of operations required to resolve an access check.

## Why `operations_consumed` Matters

FGA charges based on `operations_consumed` usage, encouraging efficient graph design while providing the flexibility to build robust, scalable access control systems. Key benefits include:

- **Lower Costs:** Reduce quota consumption with optimized graph structures.
- **Better Performance:** Deliver faster response times for access checks and queries.
- **Scalability:** Handle larger datasets efficiently without increased resource demands.

By optimizing `operations_consumed`, developers can create cost-effective, high-performing access control models that scale with their applications.

## Testing and Local Development

WorkOS offers an isolated FGA Docker image designed for testing and development. This image utilizes SQLite and in-memory caching and is not intended for production use. It should be used only in a local environment or for running test suites in your CI/CD pipeline.

The fga-dev image is available on our [public ECR repository](https://gallery.ecr.aws/workos/fga-dev). View the `Usage` section for more information about how to use it.

### Local Development

Learn how to setup your local development environment with FGA using the FGA Dev Docker image for isolated testing and schema development.

## Overview

When developing with FGA, you can either connect to a managed WorkOS FGA instance or run a local FGA instance using the [`fga-dev` Docker image](https://gallery.ecr.aws/workos/fga-dev). Each option has its own advantages depending on your workflow. This guide will help you choose the best approach and walk you through setting up a local instance if that fits your needs.

### Managed FGA Instance

Best for testing against production-like infrastructure and when you need persistent, shared data.

| Pros                                                           | Cons                                                                |
| -------------------------------------------------------------- | ------------------------------------------------------------------- |
| Data persists and is accessible by multiple clients            | Data is shared (multiple consumers can overwrite each other's data) |
| Uses production infrastructure for performance and reliability | Consumes operation credits                                          |

### Local FGA Instance

Best for isolated development and testing especially when you want to avoid using operation credits or need a clean environment for each run (such as in CI).

| Pros                           | Cons                                       |
| ------------------------------ | ------------------------------------------ |
| Isolated test environment      | You must manage setup and teardown of data |
| Does not use operation credits | Uses local resources and is not scalable   |

The `fga-dev` Docker image provides a fully self-contained FGA environment using SQLite and local caching. This setup is **not intended for production** but is fine for local development, CI, and integration testing. It is less scalable than the managed instance because it cannot handle high concurrency, complex models, or large datasets.

This guide will show you how to use the [`fga-dev` Docker image](https://gallery.ecr.aws/workos/fga-dev) to spin up an isolated FGA instance on your machine.

---

## Prerequisites

To start this guide, you'll need:

- [Docker](https://www.docker.com/get-started) installed on your machine
- A [WorkOS account](https://dashboard.workos.com/) (for API keys)
- Your WorkOS [API Key](/glossary/api-key)

---

## Running fga-dev Locally

### Option 1: Using Docker Compose (Recommended)

Create a `docker-compose.yaml`:

```yaml title="docker-compose.yaml"
version: '3.8'

services:
  fga-dev:
    image: public.ecr.aws/workos/fga-dev:latest-arm64
    user: root # Run as root to avoid permission issues with mounted volumes (non-production only)
    volumes:
      - fga-dev-volume:/data:rw,cached # Persist data between runs
    ports:
      - '8001:8001'
    environment:
      FGA_DEV_PORT: 8001
      FGA_DEV_AUTH_API_KEY:  # Your staging WorkOS API key to authenticate the dev image
      FGA_DEV_TEST_API_KEY: test_key # A mock API key to authenticate FGA requests from your application

volumes:
  fga-dev-volume:
```

#### Usage

1. **Start the server:**

   ```shell
   docker compose up -d
   ```

2. **Configure your app:**

   - Point your application's WorkOS SDK or CLI to the proper host.
   - Use `test_key` as the API key for FGA requests from your app.

     | Environment                 | API Host                         |
     | --------------------------- | -------------------------------- |
     | Local machine               | http://localhost:8001            |
     | Separate Docker container   | http://host.docker.internal:8001 |
     | Same Docker Compose network | http://fga-dev:8001              |

> If you’re using the WorkOS SDK, you can set the API Hostname option to point to your local FGA instance. Since each SDK instance supports only one API Host, you may need to create a separate SDK instance specifically for FGA when testing against the local service.

3. **Develop:**

   Apply schemas, create warrants, and test locally. All data persists in the Docker volume.

   See [Schema Management](/fga/schema-management) for how to apply a schema to your local instance and test authorization checks.

4. **Shut down:**

   ```shell
   docker compose down
   ```

5. **Clear all data (optional):**

   ```shell
   docker volume rm fga-dev-volume
   ```

> Tip: Add a secondary Docker Compose service to seed your local instance with test data on startup.

---

### Option 2: Running a Docker Container

You can also run the `fga-dev` image directly using `docker run` if you prefer not to use Docker Compose.

```shell
docker run -d \
  --name fga-dev \
  -p 8001:8001 \
  -e FGA_DEV_PORT=8001 \
  -e FGA_DEV_AUTH_API_KEY= \
  -e FGA_DEV_TEST_API_KEY=test_key \
  -v fga-dev-volume:/data:rw \
  --user root \
  public.ecr.aws/workos/fga-dev:latest-arm64
```

To stop and remove the container:

```shell
docker stop fga-dev && docker rm fga-dev
```

To remove the volume and reset all data:

```shell
docker volume rm fga-dev-volume
```

---

## Best Practices

Consider the following best practices to ensure a smooth local development experience with FGA:

- **Isolate test data**: Use unique resource IDs to avoid collisions which is especially critical when working with shared or managed instances.
- **Automate environment setup**: Script the schema and warrant creation on first startup. This makes your development and CI pipelines more reliable and repeatable.
- **Clean up regularly**: Tear down and reset your environment when needed to avoid stale data and hidden state, which can lead to confusing behavior.
- **Choose the right environment**: Use a managed instance for shared, persistent testing; use the local fga-dev container for isolated development or CI.

---

### Fine-Grained Authorization (FGA)

Scalable, centralized, fine grained authorization for your application.

## Introduction

WorkOS Fine-Grained Authorization (FGA) is a centralized authorization service for customer applications. Teams can use FGA to implement a custom authorization model tailor-made for their application(s), with the ability to integrate elements of role-based access control (RBAC), relationship-based access control (ReBAC), and attribute-based access control (ABAC) as needed.

## Key features

- Fully managed, centralized authorization service (inspired by Google Zanzibar) for managing and enforcing application authorization
- [Check API](/reference/fga/check) to perform fast access checks from your application (i.e. `Is user:A an editor of document:X?`)
- [Query API](/reference/fga/query) to quickly lookup which resources users have access to from your application (i.e. `Which documents can user:A edit?`)
- Central log of all authorization events & operations to make auditing and debugging of your application(s) easy
- Pre-built templates for common access control patterns like RBAC, multi-tenancy, pricing tiers & feature entitlements, and more

## Common Use Cases

### Role-based access control (RBAC)

One of the most common forms of access control, role-based access control involves 3 main entities: roles, permissions and users. Permissions define _behaviors_ that are grouped together into roles (e.g. admin, owner). Roles are then assigned to users to grant them the ability to perform a group of behaviors. RBAC is common within B2B software and SaaS applications used by enterprises, often being necessary to meet regulatory, compliance, and/or enterprise contract requirements.

### Custom roles

Most applications start by implementing RBAC with a static set of roles. This works well for simple applications used by one customer (single-tenant). However, this model often breaks down in multi-tenant applications (apps used by multiple customers). Different customers might require a different set of roles or a different mapping of roles to permissions. This requirement introduces a new dimension (tenant) on top of existing roles, permissions, and users, requiring a flexible access model to prevent a problem known as _role explosion_.

### Fine-grained access control (FGAC)

Fine-grained access control is a more granular form of access control that is becoming popular in applications today. As opposed to the coarse-grained access control provided by RBAC, which grants access to behaviors across _all resources_, FGAC allows applications to grant users certain behaviors _per resource_.

For example, while a RBAC rule might specify that `[admins] can [edit] [reports]`, a fine grained rule can specify that `[user:1] can [edit] [report:xsd34]`.

### Resource-level RBAC

FGAC can also be used in conjunction with RBAC to enable what we call 'fine-grained RBAC'. This is especially common in SaaS apps and developer tools. For example, let's take a cloud infrastructure multi-tenant SaaS that defines a resource called `customer-application`. A 'customer-application' can have `owners`, `editors` and `viewers`. Now let's say that the users within this SaaS can have multiple 'roles' within their 'tenant' based on their access level. In order to specify an access rule like `all [admins] of [tenant:x] can [edit] [all applications] that belong to [tenant:x]`, we need 'fine-grained RBAC', or the ability to specify resource-level rules by role.

### Collaboration & document sharing

One of the most common use cases for FGAC is to enable access control on user-generated content, similar to Google Docs or Box. With FGAC, you can easily define `owners`, `editors` and `viewers` of your own resources and objects (ex. documents, reports).

### Organization hierarchies

Another common use case for FGAC is to model complex organization hierarchies, often those found within most mid-large scale enterprises. For example, let's say that we'd like to specify a rule within an organization which states that `all [members] of [team:x] can access [report:y87dXfd]`. Furthermore, let's say that membership in `team:x` is driven by org hierarchy and whether a specific person reports to a given manager.

Using a FGA system, we can model the exact org hierarchy as well as easily define rules such as `all [direct reports] of [manager:y] are [members] of [team:x]` and `all [members] of [team:x] can access [report:y87dXfd]` in order to process queries such as `can [user:1] access [report:y87dXfd]` in realtime.

### Regional access control

Similar to enterprise org hierarchies, apps with complex regional hierarchies are a good use case for FGAC. For example, let's say we're building a supply-chain or operations-focused SaaS app where data and functionality is separated by region. We may have `region:east` and `region:west` to distinguish the two core regions with teams and users defined within each region.

Using a FGA system, we can accurately model the regions and easily make queries against it at runtime to ensure that the right users have access to the right data and functionality.

### Pricing tiers & feature entitlements

Although not directly related to security, a common form of access control often used within SaaS is what we call 'pricing tiers & feature entitlements'. Pricing tiers are groups of features within an app, typically assigned based on the end customer's payment tier. Mature SaaS apps often build out their own management and enforcement layer for pricing tiers, in order to support everything from feature overrides and metering to integrations with payment systems.

With a FGAC system, pricing tiers and feature entitlements can be expressed as rules like `[company:x] is on [tier:enterprise]` and `[feature:dashboard] is part of [tier:enterprise]` in order to easily support runtime queries like `can [user:y] which is a member of [company:x] access [feature:dashboard]?`

### Fine-Grained Authorization (FGA)

Scalable fine-grained authorization built for B2B SaaS.

## Introduction

> Coming Q1 2026 - The endpoints and features described on this page are not yet available.

> The previous version of WorkOS Fine-Grained Authorization (FGA) was officially deprecated on November 15, 2025. A fully re-architected FGA is now in development and will be released soon. Please read our [blog post](https://workos.com/blog/fga-how-workos-is-rethinking-authorization-for-the-next-generation-of-saas) for details.

Fine-Grained Authorization (FGA) extends the existing WorkOS RBAC system to handle the complex, fast-changing authorization needs of modern B2B SaaS products.

Most products start with simple, org-level roles like Admin and Member. As adoption grows, the model is forced to account for workspaces, projects, apps, pipelines, nested tenants, custom roles, group-based collaboration, and enterprise exceptions. What used to evolve over a decade can now change in 12–18 months. Teams patch RBAC with special cases, multiply role variants, and eventually face full rewrites.

FGA is designed as the next step in that evolution:

- It keeps the **mental model of RBAC**: roles, permissions, assignments.
- It adds **hierarchical, resource-scoped access control**.
- It integrates **natively with existing WorkOS products**, including RBAC, SSO, Directory Sync/SCIM, AuthKit, and IdP role mapping.
- It can be **adopted incrementally** with no data migration or confusing schema DSL.

The goal is to give SaaS teams a single authorization foundation that adapts as the product and customer requirements change, without introducing a parallel system or forcing conceptual rewrites.

---

## Core concepts

FGA formalizes three building blocks:

- **Subjects** – Users, groups, devices, or agents that can be granted access.
- **Resources** – Business entities in your product (organizations, workspaces, projects, apps, etc.) arranged in a hierarchy.
- **Privileges** – Roles and the permissions contained within them.

The key shift from traditional, org-only RBAC is that **resources and their hierarchy are first-class**. Roles and permissions are scoped to specific resource types and may be assigned at any level of that hierarchy.

---

## Resource model

FGA’s resource model captures how entities in your application relate to one another. It is:

- **Hierarchical** – Up to five layers deep.
- **Typed** – Each layer can define multiple resource types.
- **Single-parent** – Each resource instance has exactly one parent (organization or another resource).

> Note: Resource types and resource instances are distinct. Resource types define the schema of the hierarchy and may specify multiple valid parent types. Resource instances are the actual objects created at runtime, and each instance always has exactly one parent, ensuring predictable inheritance and traversal.

Typical hierarchies:

```text
organization
└─ workspace
   └─ project
      └─ app

organization
└─ account
   └─ dashboard

organization
└─ team
   ├─ repository
   └─ pipeline
```

Resource types and their allowed parent/child relationships are defined in the WorkOS Dashboard. Examples:

- `Organizations`
- `Workspaces`
- `Accounts`
- `Projects`
- `Applications`
- `Pipelines`
- `Spaces`
- `Repositories`
- `Dashboards`

### Resource instances

At runtime, your application registers resource instances as users create them:

```text
Org:acme
 └─ Workspace:finance
     └─ Project:quarterly-plan
         └─ App:forecasting
```

Each instance has:

- A **type** - what kind of resource it is (`workspace`, `project`, …).
- An **id** - a unique identifier for that specific resource instance.
- A **parent** - the organization or resource it belongs under.

This structure drives:

- Where roles can be assigned.
- How permissions inherit down the tree.
- How cascaded cleanup works when a resource is deleted.

The model is optimized for low-cardinality entities like workspaces, accounts, and apps. High-volume application objects—documents, messages, tasks, rows, and similar—should remain in your application’s own source of truth rather than being modeled as FGA resource instances. Syncing these objects into an external authorization store introduces latency, reconciliation issues, and operational overhead.

Some systems attempt to avoid this by querying your database during authorization (“local evaluation”), but this shifts the problem: authorization performance becomes tied to your production database, rule logic becomes tightly coupled to your schema, and developers must maintain custom query filters that scale poorly in multi-tenant environments. Modeling inheritance or hierarchy must also be done manually, which becomes brittle as products evolve.

FGA avoids both patterns. High-cardinality objects remain in your database, but can still participate in authorization by storing a reference to their nearest FGA-managed parent resource. Your application passes that parent during checks, allowing permissions to be evaluated through the hierarchy without syncing every object or embedding authorization logic in database queries.

This keeps authorization fast, predictable, and decoupled from your data model—without the trade-offs required by other approaches.

---

## Roles and permissions

Roles and permissions in FGA are always defined relative to a resource type. This means a role created for a workspace applies only to workspace resources, a project role applies only to projects, and so on. Existing organization-level RBAC roles continue to function exactly as they do today and are automatically scoped to the organization.

A role describes what a subject can do within the scope of a particular resource type. Each role contains one or more permissions, and those permissions may apply either to:

- the same resource type as the role (for example, workspace:view), or
- a child resource type (for example, project:edit), enabling permission inheritance down the hierarchy.

## How scoping works

If a role is scoped to a workspace type, it can grant permissions such as viewing or editing that workspace. If it includes child-type permissions (like project-level actions) those permissions automatically apply to all child resources under that workspace. This prevents role explosion and allows a single workspace-level role to control access across the entire sub-tree beneath it.

Example:

- An `Organization Member` role grants organization-level permissions such as viewing the org or accessing its workspaces.
- A `Workspace Admin` role grants full access to a specific workspace and all projects within it.
- A `Project Editor` role grants edit rights only to a particular project and its apps, without affecting sibling projects.

Through this model, FGA ensures permissions are predictable, type-safe, and aligned with the structure of your application’s resource hierarchy—while preserving all existing RBAC behavior.

### Assignment and inheritance

An assignment binds:

- An [Organization Membership](/authkit/users-organizations/organizations/organization-memberships) (user)
- A [role](/rbac/configuration/configure-roles)
- An [Organization](/authkit/users-organizations/organizations) or resource instance

When a role includes child-type permissions, FGA automatically **propagates** those permissions down to children under that parent resource.

Consider the following hierarchy:

```text
Org
  └─ Project
        └─ App
```

We can configure roles at each level to define the following access patterns:

- A user is `Member` of `Org:1` with `org:view`, `project:view`, and `app:view` permissions. They can view the organization, all of its projects, and all apps under those projects.
- The same user is `Project Editor` for `Project:B` and can edit that project and all of its apps.
- A user is `App Editor` for `App:Finance` and can edit only that app instance.
- Another user is `Project Read-Only` on `Project:A` and can view only that project, not its apps.

![Example resource hierarchy with roles](https://images.workoscdn.com/images/74c1fad7-abe9-4c21-a244-8c2563f1313c.png?auto=format&fit=clip&q=50)

---

## Access evaluation

[AuthKit](/authkit) continues to embed organization-level [roles and permissions in access tokens](/authkit/roles-and-permissions/role-aware-sessions). These roles come from the existing RBAC product and may also include any resource-scoped permissions defined within those org-level roles. They remain the best mechanism for coarse-grained checks—for example, determining whether a user can access an organization at all or perform billing-related actions.

To evaluate access on a specific resource instance, your application calls the Authorization API:

```json
POST /authorization/check
```

The check engine considers:

- Direct assignments on a resource (`project:proj_123`).
- Assignments on parent resources (a project permission inheriting from role assignment on the workspace it belongs to).
- Organization-level roles from the session token that contain permissions for the relevant resource type.

---

## Authorization API (Not yet available - coming Q1 2026)

FGA is exposed through a set of Authorization API endpoints grouped into three concerns: **resources**, **assignments**, and **access checks**.

### Resource instance management

- `GET /authorization/resources/`
- `POST /authorization/resources`
- `PATCH /authorization/resources/`
- `DELETE /authorization/resources/`

### Resource Management using external IDs

- `GET /authorization/organizations//resources//`

> Note: Resource types are defined in the WorkOS Dashboard and are not managed via the API.

### Role assignments

- `POST/DELETE /authorization/assignments`

### Access checks and resource discovery

- `POST /authorization/check`
- `GET /authorization/resources/{resource_id}/organization_memberships`
- `GET /authorization/organization_memberships/{membership_id}/resources`
- `GET /authorization/organization_memberships/{membership_id}/roles`

With resource discovery endpoints, you can implement queries that align with common product features, such as:

- “List members with access to this workspace”
- “All projects under a parent workspace this user can edit”
- “List all assigned roles for a user”

---

## Enterprise identity integration

FGA integrates directly with [SSO](/sso), [Directory Sync](/directory-sync), and IdP [role/attribute mapping](/directory-sync/identity-provider-role-assignment). Organizations can:

- Map IdP groups to resource-level roles, so teams inherit the correct workspace or project access automatically.
- Use IdP attributes to drive assignments, ensuring roles reflect organizational metadata such as department or job function.
- Align internal team structures with FGA resource types, allowing identity changes in the IdP to cascade cleanly across the application’s authorization model.

**Coordinating identity information with a hierarchical authorization system is one of the hardest challenges in modern SaaS architecture—and FGA provides a unified solution that no other provider offers today.**

---

## Performance and scalability

FGA is designed for real-time authorization and heavily optimized. It uses the resource hierarchy to efficiently evaluate permissions, ensuring accurate and fast access decisions.

Key performance characteristics:

- Sub-50 ms p95 access checks.
- Strong consistency.
- High availability.
- Warmed caches.
- Edge caches for low-latency global access (scheduled for a future release).

---

## Adoption and integration with existing products

FGA works **alongside** the existing RBAC product:

- No migrations are required.
- Existing RBAC roles and organization memberships continue working.
- You can adopt FGA incrementally.

A typical rollout:

1. Use current RBAC for org-level access.
2. Define resource types to mirror your product structure.
3. Begin registering resource instances.
4. Introduce scoped roles like `workspace_admin` or `project_editor`.
5. Replace custom logic with Authorization API checks.
6. Map IdP groups and attributes to resource-scoped roles.

---

## Handling high-cardinality resources

High cardinality resource types introduce a subtle but serious anti-pattern in Zanzibar inspired systems: syncing millions of rapidly changing resource instances to an external authorization system. As cardinality increases, so does the likelihood of data inconsistencies and update failures, especially when resources sit in the application's hot path. Pushing resource updates over the network to a third-party system adds latency and instability in the application's critical path.

WorkOS FGA takes a different approach. Instead of treating every individual resource as an external entity that must be synced, applications store high-cardinality resource types locally and register only the stable parent resource types inside WorkOS. This keeps authorization fast, consistent, and close to the application's core workflows while offloading complex hierarchy management to WorkOS. The result is an expressive model that avoids remote bottlenecks and an architecture that stays performant, resilient, and easy to evolve as the product grows.

---

## Release Timeline

| Phase                | Features                                                 | Target Date             |
| -------------------- | -------------------------------------------------------- | ----------------------- |
| Restricted Preview   | Core Authorization API and dashboard modeling            | January – February 2026 |
| General Availability | Refinements based on early customer feedback             | February – March 2026   |
| Enhancements         | User groups, advanced IdP mapping, widgets, custom roles | Q2 2026                 |
| Global Access        | Edge caching and streaming for low-latency checks        | Q4 2026                 |

If you are interested in participating in the restricted preview, please reach out to WorkOS support.

### Identity Provider Sessions

Learn how to configure FGA to use your identity provider's ID tokens.

## Overview

Fine-Grained Authorization (FGA) is commonly used to enforce detailed authorization on your application's backend. However, it can also be utilized on the frontend to perform access checks directly within your client application. FGA supports the use of ID tokens issued by identity providers, allowing you to make user-specific authorization decisions on the frontend. This not only improves the security of your application but also enables you to present a customized user interface and experience based on the access levels of different users.

## Before getting started

To get the most out of this guide, you’ll need:

- A [WorkOS account](https://dashboard.workos.com/)
- Your WorkOS [Client ID](/glossary/client-id)
- The JSON Web Key Set (JWKS) endpoint of your identity provider. ([AuthKit](/reference/authkit/session-tokens/jwks))
- A schema set up in a FGA environment. If you haven't done so, check out our [Quick Start](/fga/quick-start) to create one.

---

## (1) Configure your JWKS URL

A JWKS URL is an endpoint that contains the set of public keys used to verify any JSON Web Tokens (JWTs) issued by your provider. Currently, FGA only supports JWTs that are signed using the **RS256** signing algorithm.

Common identity provider JWKS URLs:

- **WorkOS AuthKit**: `https://api.workos.com/sso/jwks/{clientId}`
- **Auth0**: `https://{yourDomain}/.well-known/jwks.json`
- **Google/Firebase**: `https://www.googleapis.com/oauth2/v3/certs`

You can set your JWKS URL in the _Configuration_ section of the [FGA Dashboard](https://fga.workos.com/configuration).

![FGA JWKS Configuration](https://images.workoscdn.com/images/35f59a84-d1ad-4c78-8be4-210678a6c161.png?auto=format&fit=clip&q=50)

## (2) Create a context for FGA

Next, let's create a [context](https://react.dev/learn/passing-data-deeply-with-context) for FGA that will allow us to make checks from anywhere in our application.

The FGA context will set and track the user's session token and expose a `check` method that we can access anywhere in our application where we need to make an access check before displaying a UI element or performing an action.




## (3) Set the session token when a user logs in

Before we begin making access checks in our application, we need to provide a server-generated session token and set it in our FGA context.



## (4) Make check requests from your app

Now that we've created our FGA context and set the session token, we can start making check requests from our client application.

The main difference here from regular check requests is that we don't need to provide a subject in our checks because all checks will be scoped to the user specified by the user ID in the session token.

Let's make a check to see if the user has the `viewer` relation on `report:7` before displaying the report's data.



---

## Summary

In this guide, we demonstrated how to perform authorization checks directly in a client application using ID tokens from our identity provider. We created a context to manage the user's session token upon login, which is then used for subsequent access checks. This approach allows us to deliver a secure and personalized experience to users within our application, leveraging FGA for fine-grained access control.

### User Groups

Learn how to make user group abstractions to manage permissions at scale.

> Explore the example from this guide [in the FGA Playground](https://explore.fga.workos.com/playground?example=user_groups), where you can interact with the schema, warrants, and access checks in real-time!

User groups in Fine-Grained Authorization (FGA) allow you to manage permissions at scale by grouping users and granting access to those groups. This is particularly useful in large organizations where managing individual user permissions can become cumbersome.

## When to Use It?

You should consider using user groups in the following scenarios:

- **Large Organizations**: When you have a large number of users and resources, managing permissions individually can be inefficient.
- **Dynamic User Base**: If your user base changes frequently (e.g., employees joining or leaving), management groups can simplify the process of updating permissions.
- **Hierarchical Structures**: When your organization has a hierarchical structure (e.g., departments, teams), management groups can help you define permissions at different levels of the hierarchy without duplicating effort.

## Example Applications

Management groups can be applied in various scenarios, including:

- **Enterprise Applications**: In large enterprises, you can create groups for different departments (e.g., Sales, Engineering) and assign permissions to these groups rather than individual users.
- **Multi-Tenant SaaS Applications**: For SaaS applications serving multiple organizations, you can create groups for each tenant and manage permissions for users within those tenants.

## Schema

```fga
version 0.3

type user

type organization
  relation admin [user]
  relation document_viewer [user]
  relation document_manager [user]

  inherit document_manager if
    relation admin // admins are also document managers

  inherit document_viewer if
    relation document_manager // document managers are also viewers

type document
  // A document has a parent organization
  relation parent [organization]
  relation edit [user]
  relation view [user]

  // Allow users to edit the document if they
  //  are in the document manager group on the organization that owns it
  inherit edit if
    relation document_manager on parent [organization]

  // Allow users to view the document if they
  //  are in the document viewer group on the organization that owns it
  inherit view if
    relation document_viewer on parent [organization]
```

## Example

### (1) Apply the schema

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

> Note: make sure to select the correct environment with the [CLI](https://github.com/workos/workos-cli?tab=readme-ov-file#usage)

```shell
workos fga schema apply schema.txt
```

---

### (2) Create warrants

Create warrants that associate organizations and documents. Add a users to a `document_viewer` / `document_manager` groups.



---

### (3) Check access

With our environment setup, we can check the user's permission to view items.



---

### Superusers

Learn how to use policies to create superuser overrides.

> Explore the example from this guide [in the FGA Playground](https://explore.fga.workos.com/playground?example=superusers), where you can interact with the schema, warrants, and access checks in real-time!

Superuser policies allow specific users to override inheritance rules to grant broad access to many resources. This is useful for granting elevated privileges to trusted users, such as administrators, support engineers, or internal employees.

## When to Use It?

Use superuser policies when you need to:

- Provide emergency access to a resource without modifying existing permissions.
- Allow internal employees to manage resources without explicitly assigning them to each one.
- Implement organization-wide administrative roles that apply across multiple resources.

## Example Applications

Many applications implement superuser policies, including:

- **E-commerce platforms**: Store administrators or support agents need access to all stores for troubleshooting.
- **Multi-tenant SaaS applications**: Internal employees may need to access any tenant's data for support purposes.
- **Content management systems**: Superusers may need the ability to edit or review content across multiple projects.

## Schema

```fga
version 0.3

type user

type store
  relation editor [user]
  relation viewer [user]

  // Editors of a store are either
  //   Assigned directly as an editor of the store
  //   Or superusers who can edit any store (via is_superuser policy)
  inherit editor if
      policy is_superuser

  // Any editor can also view the store
  inherit viewer if
    relation editor

policy is_superuser(user_attributes map) {
  user_attributes.superuser == true &&
    user_attributes.email endsWith "@internal-domain.com"
}
```

## Example

### (1) Apply the schema

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

> Note: make sure to select the correct environment with the [CLI](https://github.com/workos/workos-cli?tab=readme-ov-file#usage)

```shell
workos fga schema apply schema.txt
```

---

### (2) Check access

With our environment setup, we can check the user's permission to view a document.



---

### Google Docs

Build a Google Docs-like authorization model in which users have varying levels of access to documents they can collaborate on with each other.

> Explore the example from this guide [in the FGA Playground](https://explore.fga.workos.com/playground?example=google_docs), where you can interact with the schema, warrants, and access checks in real-time!

Implement an authorization model similar to Google Docs document sharing. Allow users to grant read and/or write access to other users on individual documents and folders containing other nested documents and/or folders.

## When to Use it

Consider this authorization model for:

- **User Generated Content**: Your application supports user-generated content (e.g. documents, notes, images, etc.) and users can share access to this content with each other
- **Collaboration**: You want to allow users to collaborate on content or resources together

## Schema

```fga title="schema.txt"
version 0.3

type user

type document
  // Note: folders are modeled as documents.
  // They can be parents of other documents.
  relation parent [document]
  relation role_owner [user]
  relation role_editor [user]
  relation role_viewer [user]
  relation can_write_users []
  relation can_read_users []
  relation can_write_content []
  relation can_read_content []

  inherit role_owner if
    relation role_owner on parent [document]

  inherit role_editor if
    any_of
      relation role_owner
      relation role_editor on parent [document]

  inherit role_viewer if
    any_of
      relation role_editor
      relation role_viewer on parent [document]

  inherit can_write_users if
    relation role_owner

  inherit can_read_users if
    any_of
      relation role_viewer
      relation can_write_users

  inherit can_write_content if
    relation role_editor

  inherit can_read_content if
    any_of
      relation role_viewer
      relation can_write_content

```

## Example

### (1) Apply the schema

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

> Note: make sure to select the correct environment with the [CLI](https://github.com/workos/workos-cli?tab=readme-ov-file#usage)

```shell
workos fga schema apply schema.txt
```

---

### (2) Create warrants

Create warrants that associate users and documents. The example schema defines the following relationships:

- documents with other documents (i.e. folders)
- users with documents (using one of the defined roles: `owner`, `editor`, or `viewer`)

Let's create a few warrants between documents `doc-1`, `doc-2`, `doc-3`, `folder-1`, `folder-f2`, and user `user_2oDscjroNWtzxzYEnEzT9P7VYEe`:



---

### (3) Check access

With our environment setup, we can check whether the user can read a document's contents.



---

### Public Access

Model public document access using FGA policies.

> Explore the example from this guide [in the FGA Playground](https://explore.fga.workos.com/playground?example=public_access), where you can interact with the schema, warrants, and access checks in real-time!

Public access allows users to view resources without requiring a direct relationship or explicit grant. This is useful for cases where content is meant to be openly accessible but still requires a basic set of conditions, such as being published or flagged as public.

## Example Applications

- **Document Management**: Public reports or documents.
- **Education Platforms**: Make certain course materials or syllabus open access.
- **Media & Publishing**: Allow public access to some articles while gating premium ones.
- **E-Commerce**: Public product listings with private admin dashboards or private draft listings.

## Schema

```fga
version 0.3

type user

type document
  relation viewer [user]

  inherit viewer if
    policy is_public_document

policy is_public_document(document_attributes map) {
  document_attributes.public == true && document_attributes.status == "published"
}
```

> Note: Public access can also be modeled with [wildcard warrants](/fga/warrants/wildcard-warrants). This example focuses on using policies for more control over access conditions.

## Example

### (1) Apply the schema

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

> Note: make sure to select the correct environment with the [CLI](https://github.com/workos/workos-cli?tab=readme-ov-file#usage)

```shell
workos fga schema apply schema.txt
```

---

### (2) Check access

With our environment setup, we can check the user's permission to view a document.



---

### Policy Context

Learn how to pass context to policies in FGA.

Policies in FGA allow you to define complex access control rules based on the context of the request. This context can include resource attributes, location and temporal data, or any other relevant information that can help determine access to a specific resource.

This guide will walk you through the process of creating a policy that pulls context in two different ways: check context and injected context.

## When to Use it

Use policy context when:

- **Dynamic Access**: You need to make access decisions based on runtime attributes such as location, time of day, IP address, device type, or authentication method.
- **Resource Attribute-Based Access**: You want to enforce permissions based on properties of the resource itself such as a course’s level, a document’s classification, or user data.
- **Complex Policies**: You need to evaluate multiple attributes or conditions together to enforce advanced access rules.

## Check Context

In this approach, you pass context directly in the check request. These values are made available to the policy as named parameters and must be explicitly defined in the policy function signature within your schema.

```fga
version 0.3

type user

type course
  relation editor [user]
  relation viewer [user]
  relation instructor [user]

  relation edit []
  relation view_materials []
  relation moderate_discussion []

  inherit edit if
    all_of
      relation editor
      policy can_edit_course
      policy has_security_compliance

  inherit view_materials if
    any_of
        all_of
          relation viewer
          policy can_access_materials
        relation edit

  inherit moderate_discussion if
    all_of
      relation instructor
      policy can_moderate_discussion


policy can_edit_course(check_data map, user_attr map) {
  check_data.resource_type == "course" &&
  check_data.resource_id in user_attr.assigned_course_ids &&
  user_attr.role == "instructor"
}

policy can_access_materials(user_attr map, course_attr map) {
  user_attr.is_enrolled == true &&
  user_attr.org_id == course_attr.org_id
}

policy can_moderate_discussion(user_attr map, course_attr map) {
  user_attr.verified == true &&
  course_attr.discussion_enabled == true &&
  course_attr.course_level == "advanced"
}

policy has_security_compliance(security_info map) {
  security_info.mfa_enabled == true &&
  date(security_info.last_password_change) > now() - duration("90d")
}
```

### (1) Apply the schema

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

```shell
workos fga schema apply schema.txt
```

---

### (2) Create warrants

Create warrants that associate users with courses. We'll make a user an editor of a course:



---

### (3) Check access

With our environment setup, we can check the user's permission to `view_materials` on a course.



In this example, the check context includes `check_data`, `user_attr`, `course_attr`, and `security_info`. The policy will evaluate these attributes to determine if the user has access to view materials for the course.

> A drawback with this approach is the size of the context in the check request. This method of passing context requires no state in FGA (other than warrant data), but it starts to break down with complex schemas that require large sets of context data. Consider using injected context for more complex schemas.

## Injected Context

In this method, you can use context injected by the FGA service. Use injected context to fetch resource metadata in your policy so that you don't have to pass it in the check request.

This is useful when your schema requires large context objects, when the context is not known at the time of the check, or when you want to change schemas without updating context in the check request.

Read more about injected context and helper functions in the [policy documentation](/fga/policies/advanced-usage).

```fga
version 0.3

type user

type course
  relation editor [user]
  relation viewer [user]
  relation instructor [user]

  relation edit []
  relation view_materials []
  relation moderate_discussion []

  inherit edit if
    all_of
      relation editor
      policy can_edit_course
      policy has_security_compliance

  inherit view_materials if
    any_of
      all_of
        relation viewer
        policy can_access_materials
      relation edit

  inherit moderate_discussion if
    all_of
      relation instructor
      policy can_moderate_discussion

policy can_edit_course() {
  let user_metadata = get_metadata(check_ctx.subject_type, check_ctx.subject_id);

  let is_user = check_ctx.subject_type == "user";
  let is_course = check_ctx.resource_type == "course";
  let is_assigned = check_ctx.resource_id in user_metadata.assigned_course_ids;
  let is_instructor = user_metadata.role == "instructor";

  is_user && is_course && is_assigned && is_instructor
}

policy can_access_materials() {
  let user_metadata = get_metadata(check_ctx.subject_type, check_ctx.subject_id);
  let course_metadata = get_metadata(check_ctx.resource_type, check_ctx.resource_id);

  let is_user = check_ctx.subject_type == "user";
  let is_enrolled = user_metadata.is_enrolled == true;
  let same_org = user_metadata.org_id == course_metadata.org_id;

  is_user && is_enrolled && same_org
}

policy can_moderate_discussion() {
  let user_metadata = get_metadata(check_ctx.subject_type, check_ctx.subject_id);
  let course_metadata = get_metadata(check_ctx.resource_type, check_ctx.resource_id);

  let is_user = check_ctx.subject_type == "user";
  let is_verified = user_metadata.verified == true;
  let discussion_enabled = course_metadata.discussion_enabled == true;
  let is_advanced = course_metadata.course_level == "advanced";

  is_user && is_verified && discussion_enabled && is_advanced
}

policy has_security_compliance() {
  let user_metadata = get_metadata(check_ctx.subject_type, check_ctx.subject_id);

  let is_user = check_ctx.subject_type == "user";
  let mfa_enabled = user_metadata.mfa_enabled == true;
  let recent_password = date(user_metadata.last_password_change) > now() - duration("90d");

  is_user && mfa_enabled && recent_password
}
```

### (1) Apply the schema

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

```shell
workos fga schema apply schema.txt
```

---

### (2) Create warrants

Create warrants that associate users with courses. We'll make a user an editor of a course:



---

### (3) Update app code to sync resource metadata

In order to pull resource metadata from our policies, we need to update our app code to sync resource metadata with the FGA service. This is done by calling the [update resource](/reference/fga/resource/update) endpoint in the FGA API.



---

### (4) Check access

With our environment setup, we can check the user's permission to `view_materials` on a course.

### Org Roles & Permissions

Create org-scoped roles based on common user personas and map them to a static set of permissions that grant capabilities in your application.

> Explore the example from this guide [in the FGA Playground](https://explore.fga.workos.com/playground?example=org_roles_permissions), where you can interact with the schema, warrants, and access checks in real-time!

Build a role-based access control (RBAC) that scopes each user's role and permission assignments to a specific organization.

## When to Use it

Implement org roles and permissions when:

- **Role-based access control**: Your application's requirements call for role-based access control (RBAC)
- **Org-specific roles**: Your customers want to grant their users privileges based on their role within a specific organization.

## Schema

```fga title="schema.txt"
version 0.3

type user

type organization
    relation role_admin [user]
    relation role_read_only [user]
    inherit role_read_only if
        relation role_admin

    relation can_read_company_info [role]
    relation can_write_company_info [role]
    relation can_read_reports [role]
    relation can_write_reports [role]

    inherit can_read_company_info if
        any_of
            relation can_write_company_info
            relation role_read_only

    inherit can_write_company_info if
        relation role_admin

    inherit can_read_reports if
        any_of
            relation can_write_reports
            relation role_read_only

    inherit can_write_reports if
        relation role_admin
```

## Example

### (1) Apply the schema

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

> Note: make sure to select the correct environment with the [CLI](https://github.com/workos/workos-cli?tab=readme-ov-file#usage)

```shell
workos fga schema apply schema.txt
```

---

### (2) Create warrants

Create warrants that associate organizations, roles, and users. The example schema defines the following relationships:

- users with organizations
- users with custom roles (e.g. `org:acme:read-only`)

Let's create a few warrants between organization `acme`, role `org:acme:read-only`, and user `user_2oDscjroNWtzxzYEnEzT9P7VYEe`:



---

### (3) Check access

With our environment setup, we can check the user's permission to read company info.



---

### Managed Service Provider

Model a managed service provider (MSP) that provides services to clients and manages projects, tasks, and assets.

> Explore the example from this guide [in the FGA Playground](https://explore.fga.workos.com/playground?example=managed_service_provider), where you can interact with the schema, warrants, and access checks in real-time!

In a managed service provider (MSP) scenario, a client organization grants access to an external provider to perform services or manage resources on its behalf, while retaining control over access by assigning roles to the provider and its personnel.

## When to Use It?

This model is ideal when you need to grant limited access to external service providers without compromising internal access controls. It’s particularly useful in scenarios where external teams (like IT consultants, marketing agencies, or law firms) are brought in to manage specific projects or assets.

- **IT services**: Clients delegate infrastructure or helpdesk support to an MSP.
- **Marketing agencies**: Agencies manage campaigns and related assets for clients.
- **Law firms**: External legal teams manage cases and documents for clients.
- **Project management**: Providers handle maintenance tasks and asset management for clients.
- **Warehousing**: Providers manage inventory and logistics for clients.

## Schema

```fga title="schema.txt"
version 0.3

type user

// A client is a customer of the provider
type client
    relation admin [user]

// A provider is a service provider managed by the client
type provider
    relation admin [user]
    relation technician [user]

    inherit technician if
        relation admin

// A project is a project managed by the client and assigned a provider
type project
    relation client [client]
    relation provider [provider]
    relation editor [user]
    relation viewer [user]

    inherit editor if
        any_of
            relation admin on client [client]
            relation admin on provider [provider]
            relation technician on provider [provider]

    inherit viewer if
        any_of
            relation editor

type task
    relation assignee [user]
    relation project [project]
    relation edit []
    relation view []

    inherit edit if
        any_of
            relation assignee
            relation editor on project [project]

    inherit view if
        any_of
            relation edit
            relation viewer on project [project]

type asset
    relation manager [user]
    relation project [project]
    relation edit []
    relation view []

    inherit edit if
        any_of
            relation manager
            relation editor on project [project]

    inherit view if
        any_of
            relation edit
            relation viewer on project [project]

```

## Example

### (1) Apply the schema

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

> Note: make sure to select the correct environment with the [CLI](https://github.com/workos/workos-cli?tab=readme-ov-file#usage)

```shell
workos fga schema apply schema.txt
```

---

### (2) Create warrants

Create warrants that associate users, clients, providers, and projects. The example schema defines the following relationships:

- clients and providers with projects
- tasks and assets as children of projects
- users with clients or providers (using one of the defined roles: `admin` or `technician`)

Let's create a few warrants between client `client-1`, provider `provider-1`, project `project-1`, and users:



---

### (3) Check access

With our environment setup, we can check whether the user can view an asset.



---

### Feature Entitlements

Restrict access to features in your SaaS application based on subscription tier using FGA policies and relation-based access control.

> Explore the example from this guide [in the FGA Playground](https://explore.fga.workos.com/playground?example=entitlements), where you can interact with the schema, warrants, and access checks in real-time!

In SaaS applications, it's common to control access to product features based on a subscription tier. This approach allows product teams to define distinct experiences for different customer segments—like offering basic tools to free users/organizations and premium features to paying ones.

For example, a design tool might offer a `Free` tier with limited capabilities and a `Pro` tier that unlocks collaboration and team-based workflows.

## When to Use It?

Use feature entitlements when:

- Your product has multiple pricing tiers with different access levels.
- You want to gate advanced features behind specific subscription plans.
- Fine-grained resource access is controlled by subscription level.

Use this approach when you need dynamic, policy-driven access control for features across different plans or user types. It’s especially helpful in multi-tenant SaaS apps where access logic needs to scale cleanly and stay centralized.

## Example Applications

- **B2B SaaS Platforms**: Unlock additional collaboration tools for premium customers.
- **Design Tools**: Offer project and team management to higher-tier subscribers.
- **Analytics Services**: Gate advanced reporting or integrations behind Enterprise plans.
- **Productivity Software**: Provide shared team workspaces for Pro users.

## Schema

```fga
version 0.3

type user

type organization
  relation admin [user]
  relation member [user]

  inherit member if
    relation admin

  // Tiers are defined by subscription attributes
  relation pro_subscriber []
  inherit pro_subscriber if
    all_of
      relation admin // In this example, you must be an admin on the org to get access to pro features
      policy is_pro_subscriber

  relation free_subscriber []
  inherit free_subscriber if
    any_of
      policy is_free_subscriber
      policy is_pro_subscriber // Pro subscribers can also access free features

  // Feature access based on subscription tier
  relation feature_projects []
  inherit feature_projects if
    all_of
      relation member
      relation free_subscriber

  relation feature_teams []
  inherit feature_teams if
    relation pro_subscriber

// Teams and Projects demonstrate how you can utilize ReBAC permissions
//  to control access to features based on org subscription tiers
type team
  relation owner [organization]

  relation view []
  inherit view if
    relation feature_teams on owner [organization]

type project
  relation owner [organization]

  relation view []
  inherit view if
    relation feature_projects on owner [organization]

// Policies check subscription attributes passed from a third party integration
policy is_pro_subscriber(subscription_attrs map) {
  subscription_attrs.subscription_tier == "pro"
}

policy is_free_subscriber(subscription_attrs map) {
  subscription_attrs.subscription_tier == "free"
}
```

> Note: Feature access is determined entirely by an organization’s subscription attributes, which are evaluated by policy. This approach enables dynamic, attribute-based access control without manually managing feature grants.

---

## Example

### (1) Apply the schema

Create a file called `schema.txt` with the schema above, and apply it to your FGA environment using the CLI.

```shell
workos fga schema apply schema.txt
```

---

### (2) Add warrants

Create warrants that associate users to organizations and add teams / projects.



### (3) Check access

Once everything is set up, check if a user can access specific features.



---

### Custom Roles

Allow B2B customers to create org-scoped custom roles and map them to a static set of permissions that grant capabilities in your application.

> Explore the example from this guide [in the FGA Playground](https://explore.fga.workos.com/playground?example=custom_roles), where you can interact with the schema, warrants, and access checks in real-time!

Customizable, role-based access control gives customers the freedom to define their own custom roles and map each one to a subset of the permissions offered by your application.

## When to Use it

Implement custom roles when:

- **Role-based access control**: Your application's requirements call for role-based access control (RBAC).
- **Custom roles**: Your customers need the ability to define custom roles that are scoped to their organization and map them to a static set of permissions in your application.

## Schema

```fga title="schema.txt"
version 0.3

type user

type role
  relation member [user]

type organization
  relation can_read_company_info [role]
  relation can_write_company_info [role]
  relation can_read_reports [role]
  relation can_write_reports [role]

  inherit can_read_company_info if
    any_of
      relation can_write_company_info
      relation member on can_read_company_info [role]

  inherit can_write_company_info if
    relation member on can_write_company_info [role]

  inherit can_read_reports if
    any_of
      relation can_write_reports
      relation member on can_read_reports [role]

  inherit can_write_reports if
    relation member on can_write_reports [role]

```

## Example

### (1) Apply the schema

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

> Note: make sure to select the correct environment with the [CLI](https://github.com/workos/workos-cli?tab=readme-ov-file#usage)

```shell
workos fga schema apply schema.txt
```

---

### (2) Create warrants

Create warrants that associate organizations, roles, and users. The example schema defines the following relationships:

- users with organizations
- users with custom roles (e.g. `org:acme:read-only`)

Let's create a few warrants between organization `acme`, role `org:acme:read-only`, and user `user_2oDscjroNWtzxzYEnEzT9P7VYEe`:



---

### (3) Check access

With our environment setup, we can check the user's permission to read company info.



---

### Conditional Roles

Combine relationship-based access control (ReBAC) with attribute-based access control (ABAC) to create conditional roles.

> Explore the example from this guide [in the FGA Playground](https://explore.fga.workos.com/playground?example=conditional_roles), where you can interact with the schema, warrants, and access checks in real-time!

Use FGA to combine **Relationship-Based Access Control (ReBAC)** and **Attribute-Based Access Control (ABAC)**. Define roles that are bound to specific resources and change based on specific conditions. This allows for more granular control over who can do what, when, and under which circumstances.

## When to Use It

Use conditional roles when you cannot determine access by relationships alone. For example, a team member may be allowed to approve some expenses, but only if they are below a certain amount or belong to specific cost centers. As systems grow in complexity, pure ReBAC or ABAC models may become limiting. Conditional roles help bridge that gap with clear, composable rules.

## Example Applications

- **Expense Management**: Finance managers can approve expense reports only if the amount is below a defined threshold and aligned with their assigned cost centers.
- **Procurement**: Department heads may approve purchase orders only after completing mandatory compliance or budget authorization training.
- **Healthcare Systems**: Authorized clinicians can access sensitive health records only if the individual is assigned to their care team and the access occurs during regulated working hours.

## Schema

```fga
version 0.3

type user

type team
  relation finance_admin [user]
  relation finance_manager [user]

  inherit finance_manager if
      relation finance_admin

type expense
  relation approval_team [team]
  relation submitter [user]

  relation approve []
  inherit approve if
    any_of
      all_of
        relation finance_manager on approval_team [team]
        policy can_approve_amount
      all_of
        relation finance_admin on approval_team [team]
        policy is_high_value_expense

policy can_approve_amount(expense_attributes map, user_attributes map) {
  let can_approve_cost_center = expense_attributes.cost_center in user_attributes.approved_cost_centers;
  let can_approve_amount = expense_attributes.amount <= 1000;

  can_approve_cost_center && can_approve_amount
}

policy is_high_value_expense(expense_attributes map) {
  expense_attributes.amount > 1000
}
```

## Example

### (1) Apply the schema

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

> Note: make sure to select the correct environment with the [CLI](https://github.com/workos/workos-cli?tab=readme-ov-file#usage)

```shell
workos fga schema apply schema.txt
```

---

### (2) Create warrants

Create warrants that associate users, teams, and expenses. The example schema defines the following relationships:

- users with teams (using the `finance_admin` or `finance_manager` roles)
- teams with expenses (using the `approval_team` relation)

Let's create a few warrants between team `finance-1`, expense `expense-1`, and user `user_2oDscjroNWtzxzYEnEzT9P7VYEe`:



---

### (3) Check access

With our environment setup, we can check the user's permission to approve expenses.



---

### Blocklists

Blocklist users from accessing certain resources based on specific attributes or warrants

> Explore the example from this guide [in the FGA Playground](https://explore.fga.workos.com/playground?example=blocklist), where you can interact with the schema, warrants, and access checks in real-time!

A blocklist allows systems to deny access to specific users or sessions based on contextual data or warrants.

## When to Use It?

- A user IP address is associated with suspicious behavior
- A user is flagged for abuse
- A user is subject to temporary access restrictions (e.g., after multiple failed login attempts)

This approach combines relationship-based access control (ReBAC) with attribute-based access control (ABAC), giving you fine-grained control without complicating your core permissions model.

## Example Applications

- **Content Moderation**: Block users from viewing or interacting with content based on their IP address.
- **E-commerce Systems**: Block users from purchasing or viewing products based on behavior patterns.
- **Banking and Finance**: Deny access based on fraud scores or geolocation mismatches.

## Schema

```fga
version 0.3

type user

type store
  relation member [user]

type item
  relation owner [store]
  relation blocked [user]

  relation view []
  inherit view if
    all_of
      relation member on owner [store]
      // Users are blocked either explicitly or with the ip_not_allowed policy
      none_of
        relation blocked
        policy ip_not_allowed


policy ip_not_allowed(ip_risk_score integer) {
  ip_risk_score > 75
}
```

## Example

### (1) Apply the schema

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

> Note: make sure to select the correct environment with the [CLI](https://github.com/workos/workos-cli?tab=readme-ov-file#usage)

```shell
workos fga schema apply schema.txt
```

---

### (2) Create warrants

Create warrants that associate users, stores, and items. Add a blocked user to an item.



---

### (3) Check access

With our environment setup, we can check the user's permission to view items.



---

### Attribute-Based Access Control (ABAC)

Learn how to use policies to implement a pure attribute-based access control (ABAC) model in Fine-Grained Authorization (FGA).

> Explore the example from this guide [in the FGA Playground](https://explore.fga.workos.com/playground?example=abac), where you can interact with the schema, warrants, and access checks in real-time!

Attribute-Based Access Control (ABAC) is an authorization model that grants access based on attributes of users, resources, environments, and other contextual factors.

FGA allows you to implement a pure ABAC model, where permissions rely solely on attributes without requiring warrant data. By centralizing authorization policies, FGA eliminates hardcoded access logic, making your system more scalable and maintainable.

> **Note**: Starting with a pure ABAC model can be an effective way to remove hardcoded authorization logic while keeping policies flexible. As your needs evolve, you can seamlessly integrate Relationship-Based Access Control (ReBAC) to support permissions based on user-resource relationships, such as team memberships, delegated roles, or hierarchical access.

## When to Use Pure ABAC?

ABAC is ideal when access rules are complex and depend on multiple dynamic factors such as:

- **Entitlements**: feature access based on plan level.
- **Feature flags**: enabling experimental features for specific groups.
- **Domain-specific data**: security constraints based on specific resource data attributes.
- **Role membership**: access based on user roles or attributes that are not strictly hierarchical.
- **Temporal data**: granting temporary access based on time-based or location-based policies.

## Schema

```fga
version 0.3

type user

type organization
  relation view_financial_records []
  inherit view_financial_records if
    // Policies can be combined with inheritance rules
    all_of
      policy user_in_organization
      policy is_finance_manager

  relation view_research_data []
  inherit view_research_data if
    all_of
      policy user_in_organization
      policy is_assigned_researcher
      policy is_within_working_hours

type document
  relation edit []
  inherit edit if
    policy edit_document

policy user_in_organization(user_attributes map, organization_id string) {
  user_attributes.organization_id == organization_id
}

policy is_finance_manager(user_attributes map) {
  user_attributes.department == "finance" &&
  "manager" in user_attributes.roles
}

policy is_assigned_researcher(user_attributes map, project_id string) {
  user_attributes.role == "manager" &&
  project_id in user_attributes.assigned_projects
}

policy is_within_working_hours(access_time_epoch_seconds integer) {
    let second_since_midnight = access_time_epoch_seconds % 86400;

    // 9 AM (32400s) to 5 PM (61200s)
    second_since_midnight >= 32400 && second_since_midnight <= 61200
}

policy edit_document(user_attributes map, document_attributes map) {
    let user_is_document_editor = "document_editor" in user_attributes.roles;

    let draft_status = document_attributes.status == "draft";

    let user_can_access_document = document_attributes.organization_id == user_attributes.organization_id;

    user_is_document_editor && draft_status && user_can_access_document
}

```

## Example

### (1) Apply the schema

Create a file called `schema.txt` containing the schema definition from above. Then use the CLI to apply this schema to your WorkOS FGA environment.

> Note: make sure to select the correct environment with the [CLI](https://github.com/workos/workos-cli?tab=readme-ov-file#usage)

```shell
workos fga schema apply schema.txt
```

---

### (2) Check access

With our environment setup, we can check the user's permissions.



---


## Feature Flags {#feature-flags}

### Slack Notifications

Get notifications about feature flag changes in your Slack workspace.

## Introduction

Feature flags give teams precise control over feature releases. The WorkOS app for Slack sends real-time notifications throughout your feature flags' lifecycle, from creation and enabling to deletion. This keeps all stakeholders informed about critical changes, such as when a feature flag is enabled for specific customers or organizations.

---

## Configure your Slack connection

To set up Slack notifications, navigate to [_Feature Flags_](https://dashboard.workos.com/environment/flags) and click _Enable Slack notifications_.

![A screenshot showing the WorkOS Dashboard Feature Flags page](https://images.workoscdn.com/images/840a7450-12bf-4d8d-ba12-b30da70912d7.png?auto=format&fit=clip&q=50)

Next, click _Connect to Slack_ to go to the Slack Installation page.

![A screenshot showing the WorkOS Dashboard Slack notifications dialog when no connection exists](https://images.workoscdn.com/images/7b873377-4847-43ae-a7ba-bf50b25d9f5e.png?auto=format&fit=clip&q=50)

Finally, select the channel that you'd like to get your notifications in. By default, notifications are sent for all production environments in your WorkOS account.

![A screenshot showing the Slack installation page](https://images.workoscdn.com/images/83ed7c7f-1e27-4b52-b20e-6439cec854a9.png?auto=format&fit=clip&q=50)

---

## Slack notifications

Once your Slack notifications are enabled, you'll start to receive messages in the configured channel for all feature flag events.

### Flag lifecycle events

- A flag is created
- A flag's details are updated (name, description, tags)
- A flag is deleted

![Sample message of a flag created event](https://images.workoscdn.com/images/1bc973f6-f879-4c71-8f0a-fd3eece4f252.png?auto=format&fit=clip&q=50)

### Rule updates and targeting changes

- A flag is enabled or disabled
- Targeting is changed between All, Some, or None
- Specific users or organizations are added or removed

![Sample message of a flag enabled for some event](https://images.workoscdn.com/images/9613033e-f313-449d-bbd3-9bcff85af2c2.png?auto=format&fit=clip&q=50)

---

## Disconnect an existing connection

To disable notifications or to change your configured Slack channel, you must disconnect the existing connection. To start, navigate to [_Feature Flags_](https://dashboard.workos.com/environment/flags) and click _Connected to Slack_.

![A screenshot showing the WorkOS Dashboard Slack notifications dialog for an existing connection](https://images.workoscdn.com/images/1c2e2fad-af7a-48a4-8b93-75b93653ed2b.png?auto=format&fit=clip&q=50)

Next, click _Disconnect_ and confirm to disable Slack notifications to the listed channel.

### Feature Flags

Manage rollout of new features for specific users and organizations with Feature Flags.

## Overview

Feature flags are a tool that allows teams to control the rollout of features in real time. They enable businesses to separate feature delivery from code deployment, creating a more agile and risk-managed approach to launching and managing product experiences.

WorkOS Feature Flags provides a developer-friendly solution that integrates seamlessly with your existing authentication flow. Create and manage flags through the dashboard then access them through a user's access token. Feature flags can target organizations or individual users. This approach lets you safely roll out new functionality, enable beta programs for select customers, and manage premium feature access without deploying code changes.

## Use cases

- **Targeted rollouts:** Enable features for specific organizations before a general release
- **Beta programs:** Allow early access to new features for select customers
- **Premium features:** Restrict advanced functionality to organizations on higher-tier plans

## Before getting started

To get the most out of these guides, you’ll need:

- A [WorkOS account](https://dashboard.workos.com/)

- An existing organization in your WorkOS Dashboard

![WorkOS Dashboard UI showing organization creation](https://images.workoscdn.com/images/1c69fd98-01be-491d-9255-58363bc6a983.png?auto=format&fit=clip&q=50)

## API object definitions

[Organization](/reference/organization)
: Describes an organization whose users sign in with a SSO Connection, or whose users are synced with a Directory Sync Connection.

[User](/reference/authkit/user)
: Describes a user who can be targeted with feature flags.

## (1) Create a feature flag from the WorkOS dashboard

- Sign in to your [WorkOS dashboard](https://dashboard.workos.com/) account and navigate to the Feature Flags page.
- Click the `Create feature flag` button and enter a name, slug, and description.

![A screenshot showing the WorkOS dashboard feature flags page.](https://images.workoscdn.com/images/9be5d8f6-8956-47fc-aca6-66478bb37881.png?auto=format&fit=clip&q=80)

Feature flags are created across all environments, allowing you to test your feature flag in a sandbox environment before enabling it in production.

---

## (2) Set the users and organizations that should have access

To edit which set of users and organizations should have the feature flag enabled, click `Edit` on the rule for the environment you want to edit. Next, select your desired rule setting between `None`, `Some`, and `All`. Selecting `Some` will allow you select specific users and organizations.

To edit a feature flag's rules in other environments, click the `Edit in X` button which will update your active dashboard environment to the selected environment, allowing you to update rules in the chosen environment.

![A screenshot showing the configuration of a feature flag organization rule.](https://images.workoscdn.com/images/bf958da9-1288-464c-b087-b54f60f03171.png?auto=format&fit=clip&q=80)

![A screenshot showing the configuration of a feature flag user rule.](https://images.workoscdn.com/images/32f8b6da-d357-4ac7-b9b3-96c9cf3ef60f.png?auto=format&fit=clip&q=80)

---

## (3) Enable the feature flag

Once you're ready to enable the feature for the configured set of organizations and users, toggle the flag on to start including it in a user's access token when they authenticate for a configured organization or when the user is individually targeted.

![A screenshot showing the enabling of a feature flag.](https://images.workoscdn.com/images/f526ab53-0ec5-4261-abe5-24f05e92cdd8.png?auto=format&fit=clip&q=80)

---

## (4) Use the feature flags in your application

The access token includes the `feature_flags` claim, containing the user’s entitlements. You can use this information to gate access to features in your application.

Feature flags will show up in the access token the next time the user logs in or the session is refreshed. You can manually [refresh the session](reference/authkit/authentication/refresh-token) after granting the organization access in the dashboard.


## Events {#events}

### Events

Respond to activity that occurs within WorkOS and third-party providers.

Events represent activity that has occurred within WorkOS or within third-party identity and directory providers. Your app can [sync the data](/events/data-syncing) via either the events API or webhooks.

#### Event object

All event objects share a similar structure.

| Attribute    | Description                                                                |
| ------------ | -------------------------------------------------------------------------- |
| `event`      | A string that distinguishes the event type.                                |
| `id`         | Unique identifier for the event.                                           |
| `data`       | Event payload. Payloads match the corresponding [API objects](/reference). |
| `created_at` | Timestamp of when the event occurred.                                      |
| `context`    | An optional object of extra information relevant to the event.             |

## API key events {{ "url": "api-key" }}

Events emitted when [API keys](/authkit/api-keys) are created or revoked.


  
    
  </Event.Details>
  Triggered when an API key is created.</Event.Description>
</Event.Root>


  
    
  </Event.Details>
  Triggered when an API key is revoked.</Event.Description>
</Event.Root>

## Authentication events {{ "url": "authentication" }}

Each step in the [authentication](/reference/authkit/authentication) flow emits an authentication event. Authentication success events are emitted even when additional steps, such as MFA, are required to complete the process.


  
    
  </Event.Details>
  
    Triggered when a user fails to verify their email.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user successfully verifies their email.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user fails to authenticate via Magic Auth.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user successfully authenticates via Magic Auth.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user fails to authenticate with a multi-factor
    authentication code.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user successfully authenticates with a multi-factor
    authentication code.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user fails to authenticate via OAuth.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user successfully authenticates via OAuth.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user fails to authenticate with password credentials.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user successfully authenticates with password credentials.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user fails to authenticate with a passkey.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user successfully authenticates with a passkey.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user fails to authenticate with Single Sign-On.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a user successfully authenticates with Single Sign-On.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when an authentication succeeds but is flagged by Radar. For
    example, the authentication may have succeeded at passing a Radar challenge.
  </Event.Description>
</Event.Root>

## Connection events {{ "url": "connection" }}

Events emitted when Single Sign-On connections are activated, deactivated, or deleted. Also emitted when a SAML certificate is renewed for the connection.


  
    
    
      Payload `data` corresponds to the [Connection](/reference/sso/connection)
      object.
    </Event.Description>
  </Event.Details>
  
    Triggered when a connection is activated.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Connection](/reference/sso/connection)
      object.
    </Event.Description>
  </Event.Details>
  
    Triggered when a connection is deactivated.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Connection](/reference/sso/connection)
      object.
    </Event.Description>
  </Event.Details>
  
    Triggered when a connection is deleted. The `state` attribute indicates
    connection state before deletion.
  </Event.Description>
</Event.Root>


  
    
    
      The `certificate_type` can be one of `ResponseSigning`, `RequestSigning`,
      or `ResponseEncryption`.
    </Event.Description>
  </Event.Details>
  
    Triggered when a SAML certificate is renewed either in the Dashboard or
    Admin Portal.
  </Event.Description>
</Event.Root>


  
    
    
      The `certificate_type` can be one of `ResponseSigning`, `RequestSigning`,
      or `ResponseEncryption`.
    </Event.Description>
  </Event.Details>
  
    Triggered when a SAML certificate is expiring (multiple events are sent out
    as it approaches expiry), or expired (once every 7 days after expiry).
  </Event.Description>
</Event.Root>

## Directory Sync events {{ "url": "directory-sync" }}

Events emitted when directory-related resources are changed. To learn what exactly each of these events represents, see the [in-depth Directory Sync events guide](/directory-sync/understanding-events).


  
    
    
      Payload `data` is based on the
      [Directory](/reference/directory-sync/directory) object, but the `domain`
      property is replaced with a `domains` array of [Organization
      Domain](reference/organization-domain).
    </Event.Description>
  </Event.Details>
  
    Triggered when a [directory is
    activated](/directory-sync/understanding-events/directory-events/dsync-activated).
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` is based on the
      [Directory](/reference/directory-sync/directory) object, except the
      `domain` property is omitted.
    </Event.Description>
  </Event.Details>
  
    Triggered when a [directory is
    deleted](/directory-sync/understanding-events/directory-events/dsync-deleted).
    The `state` attribute indicates directory state before deletion.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Directory
      Group](/reference/directory-sync/directory-group) object.
    </Event.Description>
  </Event.Details>
  
    Triggered when a [directory group is
    created](/directory-sync/understanding-events/directory-group-events/dsync-group-created).
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Directory
      Group](/reference/directory-sync/directory-group) object.
    </Event.Description>
  </Event.Details>
  
    Triggered when a [directory group is
    deleted](/directory-sync/understanding-events/directory-group-events/dsync-group-deleted).
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Directory
      Group](/reference/directory-sync/directory-group) object.
    </Event.Description>
  </Event.Details>
  
    Triggered when a [directory group is
    updated](/directory-sync/understanding-events/directory-group-events/dsync-group-updated).
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` contains a `user` which corresponds to the [Directory
      User](/reference/directory-sync/directory-user) object and a `group` which
      corresponds to the [Directory
      Group](/reference/directory-sync/directory-group) object. The `groups`
      field is omitted from the `user` object to avoid performance issues in
      large directories.
    </Event.Description>
  </Event.Details>
  
    Triggered when a [directory group user is
    added](/directory-sync/understanding-events/directory-group-events/dsync-group-user-added).
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` contains a `user` which corresponds to the [Directory
      User](/reference/directory-sync/directory-user) object and a `group` which
      corresponds to the [Directory
      Group](/reference/directory-sync/directory-group) object. The `groups`
      field is omitted from the `user` object to avoid performance issues in
      large directories.
    </Event.Description>
  </Event.Details>
  
    Triggered when a [directory group user is
    removed](/directory-sync/understanding-events/directory-group-events/dsync-group-user-removed).
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Directory
      User](/reference/directory-sync/directory-user) object. The `groups` field
      is omitted to avoid performance issues in large directories.
    </Event.Description>
  </Event.Details>
  
    Triggered when a [directory user is
    created](/directory-sync/understanding-events/directory-user-events/dsync-user-created).
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Directory
      User](/reference/directory-sync/directory-user) object. The `groups` field
      is omitted to avoid performance issues in large directories.
    </Event.Description>
  </Event.Details>
  
    Triggered when a [directory user is
    deleted](/directory-sync/understanding-events/directory-user-events/dsync-user-deleted).
    The `state` attribute indicates directory user state at time of deletion.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Directory
      User](/reference/directory-sync/directory-user) object. The `groups` field
      is omitted to avoid performance issues in large directories.
    </Event.Description>
  </Event.Details>
  
    Triggered when a [directory user is
    updated](/directory-sync/understanding-events/directory-user-events/dsync-user-updated).
  </Event.Description>
</Event.Root>

## Email verification events {{ "url": "email-verification" }}

Events emitted when a user is required to verify their email.


  
    
    
      Payload `data` corresponds to the [Email
      verification](/authkit/email-verification) object with the `code` omitted.
    </Event.Description>
  </Event.Details>
  
    Triggered when a user is required to verify their email and a code is
    created.
  </Event.Description>
</Event.Root>

## Feature flag events {{ "url": "feature-flags" }}

Events emitted when WorkOS feature flags are created, updated, deleted, or their rules are updated.


  
    
    
      Payload `data` corresponds to the [Feature Flag](/reference/feature-flags)
      object.
    </Event.Description>
  </Event.Details>
  
    Triggered when a feature flag is created.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Feature Flag](/reference/feature-flags)
      object.
    </Event.Description>
  </Event.Details>
  
    Triggered when a feature flag is updated.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Feature Flag](/reference/feature-flags)
      object.
    </Event.Description>
  </Event.Details>
  
    Triggered when a feature flag is deleted.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Feature Flag](/reference/feature-flags)
      object.
    </Event.Description>
  </Event.Details>
  
    Triggered when a feature flag's rules are modified.
  </Event.Description>
</Event.Root>

## Invitation events {{ "url": "invitation" }}

Events emitted when an [AuthKit user](/reference/authkit/user) is invited to join an organization.


  
    
    
      Payload `data` corresponds to the
      [Invitation](/reference/authkit/invitation) object with the `token` and
      `accept_invitation_url` omitted.
    </Event.Description>
  </Event.Details>
  
    Triggered when a user accepts an invitation.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the
      [Invitation](/reference/authkit/invitation) object with the `token` and
      `accept_invitation_url` omitted.
    </Event.Description>
  </Event.Details>
  
    Triggered when a user is invited to sign up or to join an organization.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the
      [Invitation](/reference/authkit/invitation) object with the `token` and
      `accept_invitation_url` omitted.
    </Event.Description>
  </Event.Details>
  Triggered when an invitation is resent.</Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the
      [Invitation](/reference/authkit/invitation) object with the `token` and
      `accept_invitation_url` omitted.
    </Event.Description>
  </Event.Details>
  
    Triggered when an invitation is revoked.
  </Event.Description>
</Event.Root>

## Magic Auth events {{ "url": "magic-auth" }}

Events emitted when a user requests a Magic Auth code.


  
    
    
      Payload `data` corresponds to the [Magic
      Auth](/reference/authkit/magic-auth) object with the `code` omitted.
    </Event.Description>
  </Event.Details>
  
    Triggered when a user initiates Magic Auth and an authentication code is
    created.
  </Event.Description>
</Event.Root>

## Organization events {{ "url": "organization" }}

Events emitted when WorkOS organizations are created, updated, or deleted.


  
    
    
      Payload `data` corresponds to the [Organization](/reference/organization)
      object.
    </Event.Description>
  </Event.Details>
  
    Triggered when an organization is created.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Organization](/reference/organization)
      object.
    </Event.Description>
  </Event.Details>
  
    Triggered when an organization is updated.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Organization](/reference/organization)
      object.
    </Event.Description>
  </Event.Details>
  
    Triggered when an organization is deleted
  </Event.Description>
</Event.Root>

## Organization domain events {{ "url": "organization-domain" }}

Events emitted when organization domains are created, updated, deleted, or their verification status changes.


  
    
    
      Payload `data` corresponds to the [Organization
      Domain](/reference/domain-verification) object.
    </Event.Description>
  </Event.Details>
  
    Triggered when an organization domain is created.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Organization
      Domain](/reference/domain-verification) object.
    </Event.Description>
  </Event.Details>
  
    Triggered when an organization domain is updated.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Organization
      Domain](/reference/domain-verification) object.
    </Event.Description>
  </Event.Details>
  
    Triggered when an organization domain is deleted.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Organization
      Domain](/reference/domain-verification) object.
    </Event.Description>
  </Event.Details>
  
    Triggered when an organization domain is verified.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` contains a `reason` and an `organization_domain` which
      corresponds to the [Organization Domain](/reference/domain-verification)
      object.
    </Event.Description>
  </Event.Details>
  
    Triggered when an organization domain verification fails.
  </Event.Description>
</Event.Root>

## Organization membership events {{ "url": "organization-membership" }}

Events emitted when an [AuthKit user](/reference/authkit/user) joins or leaves an organization.


  
    
    
      Payload `data` corresponds to the [Organization
      Membership](/reference/authkit/organization-membership) object.
    </Event.Description>
  </Event.Details>
  
    Triggered when an organization membership is created.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Organization
      Membership](/reference/authkit/organization-membership) object.
    </Event.Description>
  </Event.Details>
  
    Triggered when an organization membership is deleted.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Organization
      Membership](/reference/authkit/organization-membership) object.
    </Event.Description>
  </Event.Details>
  
    Triggered when an organization membership is updated.
  </Event.Description>
</Event.Root>

## Password reset events {{ "url": "password-reset" }}

Events emitted when a user requests to reset their password.


  
    
    
      Payload `data` corresponds to the [Organization
      Membership](/reference/authkit/password-reset) object with the `token`
      omitted.
    </Event.Description>
  </Event.Details>
  
    Triggered when a user requests to reset their password.
  </Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [Password
      Reset](/reference/authkit/password-reset) object with the `token` omitted.
    </Event.Description>
  </Event.Details>
  
    Triggered when a user successfully resets their password.
  </Event.Description>
</Event.Root>

## Role events {{ "url": "role" }}

Events emitted when roles are created or deleted in the WorkOS dashboard.


  
    
  </Event.Details>
  Triggered when a role is created.</Event.Description>
</Event.Root>


  
    
  </Event.Details>
  Triggered when a role is deleted.</Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when a role's permissions are updated.
  </Event.Description>
</Event.Root>

## Session events {{ "url": "session" }}

Events emitted when AuthKit sessions are created.


  
    
  </Event.Details>
  
    Triggered when a session is created. Sessions started using
    [impersonation](/authkit/impersonation) will include an additional
    `impersonator` field with data about the impersonator.
  </Event.Description>
</Event.Root>


  
    
  </Event.Details>
  
    Triggered when an issued session is revoked for a user.
  </Event.Description>
</Event.Root>

## User events {{ "url": "user" }}

Events emitted when [AuthKit users](/reference/authkit/user) are created, updated, or deleted.


  
    
    
      Payload `data` corresponds to the [User](/reference/authkit/user) object.
    </Event.Description>
  </Event.Details>
  Triggered when a user is created.</Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [User](/reference/authkit/user) object.
    </Event.Description>
  </Event.Details>
  Triggered when a user is deleted.</Event.Description>
</Event.Root>


  
    
    
      Payload `data` corresponds to the [User](/reference/authkit/user) object.
    </Event.Description>
  </Event.Details>
  Triggered when a user is updated.</Event.Description>
</Event.Root>

### Stream events to Datadog

Stream and analyze WorkOS activity in Datadog.

![WorkOS Datadog dashboard showing various metrics and graphs describing authentication events and user activity](https://images.workoscdn.com/images/9ec8c9ce-e087-4967-8b66-9311aaf13902.png?auto=format&fit=clip&q=50)

WorkOS supports real-time streaming of events to Datadog. By analyzing WorkOS activity directly in Datadog, you are able to:

- View trends in user sign-ins, user growth, new SSO connections and more.
- Debug customer issues related to sign-in, email verification, password resets and more.
- Generate reports of user activity per customer organization.
- Set alerts for unexpected activity, such as sudden spike in failed password attempts.

See all of the WorkOS events that stream to Datadog in the [event types](/events) documentation.

---

## Introduction

Setting up real-time streaming of WorkOS events to Datadog only takes a few minutes and can be done in three simple steps.

---

## (1) Create a Datadog API key

First, create a new Datadog API key to give WorkOS permission to send event activity as logs to your Datadog account. While you can use an existing API key, WorkOS recommends creating a new key that will only be used for WorkOS event streaming.

1. Sign in to your [Datadog account](https://app.datadoghq.com/).
2. Navigate to the [Organization Settings → API Keys](https://app.datadoghq.com/organization-settings/api-keys) page.
3. Choose the **New Key** button
4. Enter a name for your new API key.
5. Choose the **Create Key** button.
   ![A screenshot showing how to create an API key in the Datadog dashboard.](https://images.workoscdn.com/images/d69f49e9-6e8b-444a-8736-0cc2db98cf72.png?auto=format&fit=clip&q=50)

---

## (2) Configure event streaming in WorkOS

The next step is to configure event streaming in the [WorkOS Dashboard](https://dashboard.workos.com/) using the Datadog API key that was created in the previous step.

1. Sign in to the [WorkOS Dashboard](https://dashboard.workos.com/).
2. Navigate to the **Events** page.
3. Choose the **Stream to Datadog** button.

![A screenshot showing how setup streaming events to Datadog in the WorkOS Dashboard.](https://images.workoscdn.com/images/0259f8e3-6fb2-4b3a-819a-f98d128c1c79.png?auto=format&fit=clip&q=50)

4. Enter the Datadog API key.
5. Select your Datadog region.
6. Choose the **Save Log Stream Details** button.

![A screenshot showing how to enter a Datadog API key in WorkOS Dashboard.](https://images.workoscdn.com/images/e1d4d7bb-e076-492f-971f-e116ffe2de0e.png?auto=format&fit=clip&q=50)

With event streaming configured, when new events occur, WorkOS will send the events to Datadog with the source `workos`.

---

## (3) Add the WorkOS Datadog dashboard

The final step is to add the WorkOS Datadog dashboard to your Datadog account.

1. Sign in to your [Datadog account](https://app.datadoghq.com/).
2. Navigate to the [Dashboard List](https://app.datadoghq.com/dashboard/lists) page.
3. Choose the **+ New Dashboard** button.

![A screenshot showing how to create a new dashboard in Datadog.](https://images.workoscdn.com/images/feee6689-2477-4711-bf0e-10c917cc02f7.png?auto=format&fit=clip&q=50)

4. Enter a dashboard name.
5. Choose the **New Dashboard** button.
6. In the new dashboard, choose the **Configure** button.
7. Download the [WorkOS Datadog dashboard JSON file](/docs/assets/workos-datadog-dashboard.json)
8. Scroll down in the context menu and choose **Import dashboard JSON**.
9. Upload the WorkOS Datadog dashboard JSON file downloaded in the previous step.

![A screenshot showing how to import a JSON definition of a Dashboard into Datadog.](https://images.workoscdn.com/images/3dc7f949-67ff-470e-84f1-8a5a8880114d.png?auto=format&fit=clip&q=50)

### Sync data with webhooks

A step-by-step guide on how to start syncing data using webhooks.

## What you’ll build

In this guide, we will walk you through what you will need to set up webhooks:

- Create your endpoint to receive webhook events
- Register your endpoint with WorkOS
- Process the events received from WorkOS
- Test your endpoint

---

## (1) Set up your webhook endpoint

Create a public endpoint that WorkOS can send events to. This endpoint should use HTTPS and should accept POST requests with the `workos-signature` header.



> WorkOS sends the header as `WorkOS-Signature`, but many web servers normalize HTTP request headers to their lowercase variants.

---

## (2) Register your endpoint

Set and save the webhook URL in the [WorkOS Dashboard](https://dashboard.workos.com/), so WorkOS knows where to deliver the events. Your webhook endpoints should only be configured to receive the ones required by your integration. Receiving all event types can put undue strain on your servers and is not recommended.

![WorkOS Dashboard Webhooks UI](https://images.workoscdn.com/images/a6bebfe6-d5db-475c-bf34-a5bdf35433e0.png?auto=format&fit=clip&q=90)

---

## (3) Process the events

In order to avoid unnecessary retry requests hitting your webhook handler, we recommend using two concurrent processes for handling events: one for receiving the event, and the other for processing it.

### Respond with HTTP 200 OK

On receiving an event, you should respond with an `HTTP 200 OK` to signal to WorkOS that the event was successfully delivered. Otherwise, WorkOS will consider the event delivery a failure and retry up to 6 times, with exponential backoff over 3 days. You do not need to signal to WorkOS whether or not the event was processed successfully.

### (A) Validate the requests using the SDK

Before processing the request payload, verify the request was sent by WorkOS and not an unknown party.

WorkOS includes a unique signature in each webhook request that it sends, allowing you to verify the authenticity of the request. In order to verify this signature, you must obtain the secret that is generated for you when you set up your webhook endpoint in the WorkOS dashboard. Ensure that this secret is stored securely on your webhook endpoint server as an environment variable.

The SDKs provide a method to validate the timestamp and signature of a webhook. Examples using these methods are included below. The parameters are the payload (raw request body), the request header, and the webhook secret.



There is an optional parameter, tolerance, that sets the time validation for the webhook in seconds. The SDK methods have default values for tolerance, usually 3–5 minutes.

### (B) Validate the requests manually

If implementing webhook validation yourself, you’ll need to use the following steps:

First, extract the timestamp and signature from the header. There are two values to parse from the `WorkOS-Signature` header, delimited by a `,` character.

| Key                | Value                                                                                           |
| ------------------ | ----------------------------------------------------------------------------------------------- |
| `issued_timestamp` | The number of milliseconds since the epoch time at which the event was issued, prefixed by `t=` |
| `signature_hash`   | The HMAC SHA256 hashed signature for the request, prefixed by `v1=`                             |

To avoid replay attacks, we suggest validating that the `issued_timestamp` does not differ too much from the current time.

Next, construct the expected signature. The expected signature is computed from the concatenation of:

1. `issued_timestamp`
2. The `.` character
3. The request’s body as a utf-8 decoded string

Hash the string using HMAC SHA256, using the webhook secret as the key. The expected signature will be the hex digest of the hash. Finally, compare signatures to make sure the webhook request is valid.

Once you’ve determined the event request is validly signed, it’s safe to use the event payload in your application’s business logic.

### Create an IP allowlist

WorkOS sends webhooks from a fixed set of IP addresses. It’s recommended to restrict access to your webhook endpoint to only these IP addresses:

```plain title="WorkOS IP addresses"
3.217.146.166
23.21.184.92
34.204.154.149
44.213.245.178
44.215.236.82
50.16.203.9
52.1.251.34
52.21.49.187
174.129.36.47
```

---

## (4) Test your endpoint

From the dashboard, you can send test webhook events after configuring an endpoint. Go to the webhook endpoint detail page and click the **Send test event** button. The types of events that you have configured for your endpoint are available for you to send sample payloads.

![A screenshot showing how to send a test webhook in the WorkOS dashboard.](https://images.workoscdn.com/images/bda8fdc7-becb-494e-a9b6-f8295e5998a4.png?auto=format&fit=clip&q=90)

If you would like to test against your local development environment, we recommend using a tool like [ngrok](https://ngrok.com) to create a secure tunnel to your local machine, and sending test webhooks to the public endpoint generated with ngrok. See our [blog post](https://workos.com/blog/test-workos-webhooks-locally-ngrok) to get more details on how you may want to test webhooks locally with ngrok.

---

## Best practices

### Respond to events immediately

To avoid webhook requests potentially stressing your system, WorkOS strongly recommends that you respond to a webhook request with a 200 OK response as quickly as possible once received.

If you process the event before responding, your system may not be able to handle a spike of requests. This may cause requests to timeout and result in missing important updates.

A common pattern is to store the request payload on a message queue, respond with a 200 OK response, and use a background worker to process the messages in the queue.

### Recover from failed events

If your endpoint fails to respond to a webhook request with a `2xx` response, WorkOS will automatically retry the event with exponential back-off for up to 3 days in production environments. If for some reason your endpoint is still unable to respond successfully to events during that period, the event will be considered failed, and we will no longer retry sending it. You can reconcile your data using our [Directory Sync endpoints](/reference/directory-sync) to update your data.

> In staging environments, WorkOS only retries failed webhooks for several minutes before giving up. You can, however, manually retry webhooks using the WorkOS Dashboard for these environments.

### Handle out-of-sequence events

WorkOS does not guarantee that events are delivered in the same sequence that they are generated. For example, when syncing a directory you may receive:

- `dsync.group.created`
- `dsync.user.created`
- `dsync.group.user_added`

Your endpoint should handle cases when these events are delivered out of order. Each event includes the full payload of the objects involved, so you can perform an upsert using the payload data.

It is also possible that event data can be stale due to a retry of an older event being delivered after a newer event for the same object. Therefore, we recommend checking the timestamp of the incoming webhook data against the timestamp of the data in your system to ensure you do not overwrite your data with stale data. Each object in the payload includes a `created_at` field and an `updated_at` field.

### Ignore duplicate events

It is possible to receive the same event more than once. WorkOS recommends that you handle webhook events using idempotent operations. One way of doing this is logging the ID of webhook events that you have processed and ignoring subsequent requests with the same ID.

### Obfuscate your endpoint URL

A small security measure you can incorporate is to make your webhook endpoint difficult to guess. Including a token comprised of series of random numbers and letters to your endpoint URL can prevent malicious actors from easily guessing your endpoint. For example: `https://api.example.com/webhooks/n0dbga5x…` is much more difficult to guess than `https://api.example.com/webhooks`

### Data syncing

Keep your app in sync with WorkOS.

## Introduction

Syncing your app data with WorkOS is done using events. Events represent activity that has occurred within WorkOS or within third-party identity and directory providers that interact with WorkOS.

When important activity occurs, we record an event. For example, a new SSO connection being activated is an event. A user being created, assigned membership to an organization, or successfully signing in are all events as well. Events are activity that your application might be interested in for the purposes of syncing data or extending your application's business logic.

Your app can consume events from WorkOS via either the events API or webhooks.

```json language="json" title="A sample event"
{
  "object": "event",
  "id": "event_07FKJ843CVE8F7BXQSPFH0M53V",
  "event": "dsync.user.updated",
  "data": {
    "id": "directory_user_01E1X1B89NH8Z3SDFJR4H7RGX7",
    "directory_id": "directory_01ECAZ4NV9QMV47GW873HDCX74",
    "organization_id": "org_01EZTR6WYX1A0DSE2CYMGXQ24Y",
    "idp_id": "8931",
    "first_name": "Lela",
    "last_name": "Block",
    "email": "lela.block@example.com",
    "state": "active",
    "created_at": "2021-06-25T19:07:33.155Z",
    "updated_at": "2021-06-25T19:07:33.155Z",
    "custom_attributes": {
      "department": "Engineering",
      "job_title": "Software Engineer"
    },
    "role": { "slug": "member" },
    "raw_attributes": {}
  },
  "created_at": "2023-04-28 20:05:31.093"
}
```

---

## Sync using the events API

With the events API, your application retrieves events from WorkOS. The events API offers a more robust data synchronization solution compared to webhooks, ensuring seamless synchronization of your system state with WorkOS. To sync data using the events API, continue to the [events API guide](/events/data-syncing/events-api).

---

## Sync using webhooks

With webhooks, WorkOS automatically notifies your app when an event occurs by invoking an endpoint hosted within your application. To sync data using webhooks, continue to the [webhooks guide](/events/data-syncing/webhooks).

---

## API vs. webhooks

We recommend using the Events API instead of webhooks to keep your data in sync—especially for [user](/events/user) and [directory](/events/directory-sync) events. With the Events API, you control how often and how much data you ingest. Webhooks, on the other hand, require your endpoint to handle unpredictable spikes in event volume, which can make them harder to manage at scale. That said, webhooks may still be the better fit depending on your use case. Here’s how the two compare:

| Aspect         | Events API                                                                | Webhooks                                                                        |
| -------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------- |
| Timing         | Controlled by your app. Your server can process events at its own pace.   | Real-time. Webhooks trigger as soon as an event occurs.                         |
| Order          | A consistent order is guaranteed.                                         | No guarantee of order on receipt. Events contain timestamps to determine order. |
| Reconciliation | Replayable. Can go back to a specific point in time and reprocess events. | Failed requests are retried with exponential back-off for up to 3 days.         |
| Security       | Authentication, confidentiality, and integrity protection by default.     | You must expose a public endpoint and validate webhook signatures.              |

### Sync data using the events API

A step-by-step guide on how to start syncing data using the API.

## What you’ll build

In this guide, we will walk you through what you will need to integrate with the [events API](/reference/events):

- Create a _cursor_ for use with the events API
- Update your cursor
- Choose a cursor if you lose yours
- Handle event replay in your app

## Before getting started

To get the most out of this guide, you’ll need:

- A [WorkOS account](https://dashboard.workos.com/)
- An [SSO](/sso/1-add-sso-to-your-app) or [directory](/directory-sync/quick-start/1-create-a-new-directory-connection) connection configured in order to generate events

---

## (1) Integrate the events API SDK

WorkOS offers native SDKs in several popular programming languages. Choose a language below to see instructions in your app’s language.



### Set secrets

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.

```plain title="Environment variables"
WORKOS_API_KEY='sk_example_123456789'
WORKOS_CLIENT_ID='client_123456789'
```

> The code examples use your staging API keys when [signed in](https://dashboard.workos.com)

---

## (2) Start consuming events

Your app can start consuming events once it integrates the WorkOS SDK. The first thing to do is to pick a starting place in the data set.

### Keep a cursor

A _cursor_ is a bookmark to track your app’s position in the events list. The very first call to the events API won’t have a cursor. Subsequent requests to WorkOS should include the updated cursor using the `after` parameter. You will need to update and store your cursor after processing an event.

### Avoid overwriting newer data

To avoid repeating an update, store the `updated_at` timestamp provided by WorkOS for each object. Extract this tag from the data object in the event. If the `updated_at` timestamp in the event is newer, update the local state with the latest event data. Otherwise, you can skip processing that event.

---

## (3) Select event types

Determine the [event types](/events) you want to consume. Choose the relevant event types that align with your app’s functionality and integration with WorkOS.



Retrieve events from the API using cursor pagination. To fetch the next set of events, provide the ID of the latest processed event in the `after` parameter.

---

## (4) Handle event replay

In some cases, it may be necessary to go back in time and “replay” the events. When designing your app logic to handle events replay it is important to design your event handling logic in a way that can safely accommodate it without undesired effects.

To achieve this, focus on separating your app’s data handlers from transactional business logic like sending emails, communicating to 3rd party APIs, etc. By implementing separate data handling, you can replay events without side effects.

WorkOS recommends processing events synchronously, handling them in the order they occurred.

> The events API returns events up to 90 days old. You can query for up to 30 days of events per request.

### If your app stops processing events

When resuming event processing, you have two options to pick up where you left off:

- **Using the latest known cursor:** Retrieve the most recent cursor that was successfully processed and use it as the starting point for event resumption.
- **Using a timestamp:** Alternatively, you can make an API call with the `range_start` parameter and then use the cursor. Utilize the `updated_at` timestamp to prevent overwrites.

---

## Scaling recommendations

### Single consumer

WorkOS recommends that your app starts with a single worker. Process events in a separate thread or process from your app’s main execution thread. Deploying a single worker responsible for handling events simplifies and streamlines event consumption.

This approach ensures serial event processing. After completing the processing of events on the current page, request the next page of events to maintain progress.

### Parallel processing

For onboarding large organizations, divide events into independent queues for parallel processing when calling the events API from a single worker.

Concurrently processing events from different organizations is safe, but for consistency and integrity, it is recommended to sequentially process events within a single organization.

---

## Migrating from webhooks

You can migrate to the events API if you already use webhooks. To migrate, start querying the events API using the `range_start` parameter that corresponds to the time you’d want to start syncing from. The event IDs passed in webhook bodies are the same as those returned by the events API.

### Data reconciliation

Keep your app in sync with WorkOS.

## Introduction

While the events API makes it easier to keep your app in sync with WorkOS, there may still be cases where your app gets out of sync. For example, your app may have a bug in its event processing logic or in rarer cases, may experience some data loss.

Data reconciliation refers to the process of comparing and aligning the state of objects between WorkOS and your app to ensure consistency. Depending on the scope of the issue, you can reconcile your app state by either replaying events from the [events API](/reference/events) or by using the WorkOS [state API](/reference).

## Definitions

**Data reconciliation**
: Refers to the process of comparing and aligning data from different sources or systems to ensure consistency and accuracy. The goal of data reconciliation is to ensure that all relevant data sources are synchronized and reflect the same information.

**Event replay**
: Is the act of reprocessing recorded events in an app. It is used to recreate past event sequences for debugging, testing, auditing, or ensuring data consistency.

**Side effects**
: These are secondary consequences that arise from data modifications in an app. They can alter related data, trigger additional processes, update external systems, or affect the app’s overall state. e.g., Sending an email on a user’s profile change.

**Periodic reconciliation**
: Is the regular process of comparing and synchronizing data between systems to ensure accuracy and consistency. It involves scheduled checks to identify and resolve discrepancies in data integrity.

## Reconciling via the events API

In general, reconciling state changes between WorkOS and your app using the events API is simplest. Pick your cursor, which is usually the last known cursor you have processed, and paginate through events using the `after` parameter.

For special cases such as webhook migration or event replay, you can specify a starting time for event consumption using the `range_start` parameter.

### Handling side effects in the case of event replay

Side effects, such as sending emails, updating 3rd party APIs, or performing other actions specific to your app, present challenges during event replay.

Separating data handling from business logic allows you to exercise control over what actions you want your app to make. This allows your app to replay events to sync data but bypass transactional logic e.g., not sending out the same email twice.

## Reconciling via the WorkOS state API

Your app may perform data reconciliation by syncing state via the WorkOS [state APIs](/reference) e.g., in disaster recovery scenarios.

Data reconciliation using state APIs requires performing diffs to identify deletions to ensure the correct state is maintained. This introduces additional complexity, making it essential to carefully design and test the reconciliation process.

The general approach for reconciling data via the state API is as follows:

1. Pull state from WorkOS API for the objects your app is interested in.
2. Update based on `updated_at`. If the timestamp is out of date, update the object.
3. Identify deactivated objects or deletions and sync that state.

If you need to force all objects to update state, perform a complete resynchronization of the affected data instead of relying solely on the `updated_at` timestamp. Update all objects regardless of the individual `updated_at` timestamp.

### Considerations for periodic reconciliation

In some cases, you may want to run periodic reconciliation jobs to proactively check and reconcile the state between WorkOS and your app. When implementing such jobs, it is important to account for potential race conditions for concurrent updates. Additionally, consider the specific characteristics of your app to determine the frequency and scope of periodic reconciliation.


## Domain Verification {#domain-verification}

### Domain Verification

Self-serve domain verification