Built-in IdPPreview
Managing multiple identity providers can be a hassle. The Built-in IdP offers a native solution within the Tailor Platform, eliminating the need for external providers and seamlessly integrating with your Auth service. In this guide, you’ll learn how to set it up, configure it, and integrate it with your applications in just a few steps.
Consistent User Experience: The usability of authentication and authorization remains unchanged whether using Built-in IdP or external identity providers. Users will experience the same authentication flows and access controls regardless of your IdP choice.
Prerequisites
Before setting up Built-in IdP, ensure you have:
- A Tailor Platform workspace
- Auth service configured in your application
Configuration
Built-in IdP requires several resources working together to provide complete authentication functionality. The setup involves creating an IdP service, client configuration, secret management, and Auth service integration.
All Built-in IdP GraphQL operations require authentication by default.
Access must be explicitly granted by defining an authorization rule using a CEL expression in the authorization block.
<span><span style="color: var(--shiki-token-comment)"># Create the IdP service</span></span>
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_idp" "builtin_idp" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span><span style="color: var(--shiki-color-text)"> namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"builtin-idp"</span></span>
<span><span style="color: var(--shiki-color-text)"> </span></span>
<span><span style="color: var(--shiki-color-text)"> authorization </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)"># CEL expression to restrict access to admin users</span></span>
<span><span style="color: var(--shiki-color-text)"> expr </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"user.role == 'admin'"</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> </span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)"># Optional: Configure user authentication policy</span></span>
<span><span style="color: var(--shiki-color-text)"> user_auth_policy </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> use_non_email_identifier </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">false</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)"># Set to true to allow username-based authentication</span></span>
<span><span style="color: var(--shiki-color-text)"> allow_self_password_reset </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)"># Enables "Forgot Password?" on sign-in screen</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Create IdP client for authentication</span></span>
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_idp_client" "builtin_idp_client" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span><span style="color: var(--shiki-color-text)"> namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_idp.builtin_idp.namespace</span></span>
<span><span style="color: var(--shiki-color-text)"> name </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"main-client"</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Create vault for storing secrets</span></span>
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_secretmanager_vault" "builtin_idp_vault" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span><span style="color: var(--shiki-color-text)"> name </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"builtin-idp-vault"</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Store client secret</span></span>
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_secretmanager_secret" "builtin_idp_client_secret" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span><span style="color: var(--shiki-color-text)"> vault_name </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_secretmanager_vault.builtin_idp_vault.name</span></span>
<span><span style="color: var(--shiki-color-text)"> name </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"client-secret"</span></span>
<span><span style="color: var(--shiki-color-text)"> value_wo </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_idp_client.builtin_idp_client.client_secret</span></span>
<span><span style="color: var(--shiki-color-text)"> value_wo_version </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">1</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)"># Configure Auth service to use Built-in IdP</span></span>
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_auth_idp_config" "builtin_idp_config" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span><span style="color: var(--shiki-color-text)"> namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_auth.main_auth.namespace</span></span>
<span><span style="color: var(--shiki-color-text)"> name </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"builtin-idp-config"</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> oidc_config </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> client_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_idp_client.builtin_idp_client.client_id</span></span>
<span><span style="color: var(--shiki-color-text)"> provider_url </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_idp.builtin_idp.provider_url</span></span>
<span><span style="color: var(--shiki-color-text)"> username_claim </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"name"</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)"># Required for Built-in IdP integration</span></span>
<span><span style="color: var(--shiki-color-text)"> client_secret </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> vault_name </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_secretmanager_vault.builtin_idp_vault.name</span></span>
<span><span style="color: var(--shiki-color-text)"> secret_name </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_secretmanager_secret.builtin_idp_client_secret.name</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>Architecture Overview
The Built-in IdP integration involves three main components working together:
- IdP Service: Provides the identity provider functionality and user authentication
- Auth Service: Handles authentication flows and user session management
- Application: Orchestrates the services and exposes the unified GraphQL API
Integration Flow
Step 1: IdP Service Setup
The tailor_idp resource creates the identity provider service that will handle user authentication. This service:
- Manages user credentials and authentication
- Provides OIDC endpoints for authentication flows
- Generates client credentials for secure communication
Step 2: Auth Service Configuration
The tailor_auth_idp_config resource connects your Auth service to the Built-in IdP:
- Configures OIDC settings to communicate with the IdP service
- Maps user claims to application user profiles
- Handles token validation and user session management
Step 3: Application Integration When you register both IdP and Auth services as subgraphs in your application, they become part of your unified GraphQL schema:
- IdP subgraph provides user management operations (
_users,_createUser, etc.) - Auth subgraph provides authentication and authorization functionality
- Application orchestrates both services through a single GraphQL endpoint
Service Communication
The services communicate through secure internal channels:
User Request → Application → Auth Service → IdP Service
↓ ↓ ↓
GraphQL API → Token Validation → User Authentication
Authentication Flow:
- User attempts to authenticate through your application
- Auth service redirects to Built-in IdP OIDC endpoints
- IdP service validates credentials and issues tokens
- Auth service validates tokens and creates user sessions
- Application provides authenticated access to protected resources
Authentication Policy Configuration
The user_auth_policy block allows you to configure how users authenticate with the Built-in IdP:
- Email-only authentication (default): When
use_non_email_identifierisfalseor omitted, users can only authenticate using email addresses - Username-based authentication: When
use_non_email_identifieristrue, users can authenticate using identifiers other than email addresses (such as usernames) - Self-service password reset: When
allow_self_password_resetistrue, a "Forgot Password?" link is displayed on the sign-in screen, allowing users to reset their own password. This option is disabled by default. - Google OAuth: When
allow_google_oauthistrue, a "Sign in with Google" button is displayed on the sign-in screen, allowing users to authenticate using their Google account. See Google OAuth for details. - Allowed email domains: When
allowed_email_domainsis set, only users with email addresses from the specified domains can sign in or be created. See Allowed Email Domains for details.
This flexibility allows you to choose the authentication method that best fits your application's requirements.
Password Policy Configuration
The Built-in IdP allows you to enforce password requirements to enhance security. You can configure password policies within the user_auth_policy block to require specific character types and set length constraints.
Available Password Policy Options:
- Name
password_require_uppercase- Type
- boolean
- Description
Requires at least one uppercase letter (A-Z) in the password. Defaults to
false.
- Name
password_require_lowercase- Type
- boolean
- Description
Requires at least one lowercase letter (a-z) in the password. Defaults to
false.
- Name
password_require_numeric- Type
- boolean
- Description
Requires at least one numeric digit (0-9) in the password. Defaults to
false.
- Name
password_require_non_alphanumeric- Type
- boolean
- Description
Requires at least one special character (e.g., !@#$%^&*) in the password. Defaults to
false.
- Name
password_min_length- Type
- integer
- Description
Minimum password length. Valid range is 6-30. Defaults to
6.
- Name
password_max_length- Type
- integer
- Description
Maximum password length. Valid range is 6-4096. Defaults to
4096.
Example Configuration:
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_idp" "builtin_idp" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span><span style="color: var(--shiki-color-text)"> namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"builtin-idp"</span></span>
<span><span style="color: var(--shiki-color-text)"> </span></span>
<span><span style="color: var(--shiki-color-text)"> authorization </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)"># CEL expression to restrict access to admin users</span></span>
<span><span style="color: var(--shiki-color-text)"> expr </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"user.role == 'admin'"</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> </span></span>
<span><span style="color: var(--shiki-color-text)"> user_auth_policy </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> use_non_email_identifier </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">false</span></span>
<span><span style="color: var(--shiki-color-text)"> allow_self_password_reset </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span></span>
<span><span style="color: var(--shiki-color-text)"> </span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)"># Password policy settings</span></span>
<span><span style="color: var(--shiki-color-text)"> password_require_uppercase </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span></span>
<span><span style="color: var(--shiki-color-text)"> password_require_lowercase </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span></span>
<span><span style="color: var(--shiki-color-text)"> password_require_numeric </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span></span>
<span><span style="color: var(--shiki-color-text)"> password_require_non_alphanumeric </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span></span>
<span><span style="color: var(--shiki-color-text)"> password_min_length </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">8</span></span>
<span><span style="color: var(--shiki-color-text)"> password_max_length </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">128</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>Important: When a password policy is updated, existing users whose passwords do not meet the new requirements will be unable to log in until they update their passwords. They will be prompted to reset their password upon their next sign-in attempt.
Google OAuth
The Built-in IdP supports "Sign in with Google", allowing users to authenticate using their Google accounts. When enabled, a Google Sign-In button is displayed on the sign-in screen alongside the standard email/password form.
How it works:
- User clicks the "Sign in with Google" button on the sign-in screen
- Google authenticates the user and returns a verified ID token
- The Built-in IdP verifies the token and checks the user's email
- If the user does not yet exist, a new IdP user is automatically created using the Google account's email address (without a password)
- The user is signed in and redirected to the application
Users created via Google OAuth do not have a password set. They can only sign in using Google. To enable password-based login for these users, use _sendPasswordResetEmail to set an initial password.
To enable Google OAuth, set allow_google_oauth to true in the user_auth_policy block:
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_idp" "builtin_idp" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span><span style="color: var(--shiki-color-text)"> namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"builtin-idp"</span></span>
<span><span style="color: var(--shiki-color-text)"> </span></span>
<span><span style="color: var(--shiki-color-text)"> authorization </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> expr </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"user.role == 'admin'"</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> </span></span>
<span><span style="color: var(--shiki-color-text)"> user_auth_policy </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> allow_google_oauth </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
allow_google_oauth cannot be enabled when use_non_email_identifier is true. Google OAuth requires email-based identifiers because Google accounts are identified by email addresses.
Allowed Email Domains
You can restrict which email domains are allowed to sign in or be created in the Built-in IdP by setting allowed_email_domains. When configured, only users whose email addresses belong to one of the specified domains can authenticate or be registered. This applies to both standard email/password sign-in and Google OAuth.
- Name
allowed_email_domains- Type
- list of strings
- Description
A list of allowed email domains (e.g.,
["example.com", "corp.example.com"]). An empty list (default) means all domains are allowed. Maximum 100 domains.
Example Configuration:
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_idp" "builtin_idp" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span><span style="color: var(--shiki-color-text)"> namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"builtin-idp"</span></span>
<span><span style="color: var(--shiki-color-text)"> </span></span>
<span><span style="color: var(--shiki-color-text)"> authorization </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> expr </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"user.role == 'admin'"</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> </span></span>
<span><span style="color: var(--shiki-color-text)"> user_auth_policy </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> allow_google_oauth </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span></span>
<span><span style="color: var(--shiki-color-text)"> allowed_email_domains </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span><span style="color: var(--shiki-token-string-expression)">"example.com"</span><span style="color: var(--shiki-color-text)">, </span><span style="color: var(--shiki-token-string-expression)">"corp.example.com"</span><span style="color: var(--shiki-color-text)">]</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
allowed_email_domains cannot be set when use_non_email_identifier is true, as email domain validation requires email-based identifiers.
Why Use the Built-In IdP
-
Unified API with Automatic Schema Generation: When registered as subgraphs, both services automatically contribute their schemas to your application's GraphQL API, making all authentication and user management operations available through a single GraphQL endpoint and simplifying client integration.
-
Centralized Configuration: All authentication settings are managed through your application configuration, providing a single source of truth.
-
Flexible Authentication: Support for both email and username-based authentication through the
user_auth_policyconfiguration, with optional Google OAuth integration for streamlined sign-in.
For detailed configuration parameters for each resource, refer to the Terraform provider documentation.
User Management
When you register a Built-in IdP service in your application's subgraph, it automatically adds a GraphQL schema for user management. This enables you to manage IdP users directly through GraphQL operations, providing a programmatic interface for user administration.
Registering IdP as a Subgraph
To enable GraphQL user management, include the IdP service in your application's subgraphs configuration:
<span><span style="color: var(--shiki-token-function)">resource</span><span style="color: var(--shiki-color-text)"> "tailor_application" "main_app" {</span></span>
<span><span style="color: var(--shiki-color-text)"> workspace_id </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> var.workspace_id</span></span>
<span><span style="color: var(--shiki-color-text)"> name </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"main-app"</span></span>
<span><span style="color: var(--shiki-color-text)"> auth_namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_auth.main_auth.namespace</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> subgraphs </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> [</span></span>
<span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> service_type </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"IDP"</span></span>
<span><span style="color: var(--shiki-color-text)"> service_namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_idp.builtin_idp.namespace</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> service_type </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"AUTH"</span></span>
<span><span style="color: var(--shiki-color-text)"> service_namespace </span><span style="color: var(--shiki-token-keyword)">=</span><span style="color: var(--shiki-color-text)"> tailor_auth.main_auth.namespace</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-comment)"># Add other subgraphs as needed</span></span>
<span><span style="color: var(--shiki-color-text)"> ]</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>Available GraphQL Operations
Once registered, the IdP subgraph provides the following GraphQL operations for user management:
Query Operations:
_users- List IdP users with pagination and filtering_user- Get a specific IdP user by ID
Mutation Operations:
_createUser- Create a new IdP user_updateUser- Update an existing IdP user_deleteUser- Delete an IdP user_sendPasswordResetEmail- Send a password reset email to an IdP user
GraphQL Examples
Here are practical examples of user management operations:
Query all IdP users:
<span><span style="color: var(--shiki-token-keyword)">query</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">GetUsers</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> _users(first: </span><span style="color: var(--shiki-token-constant)">10</span><span style="color: var(--shiki-color-text)">) {</span></span>
<span><span style="color: var(--shiki-color-text)"> edges {</span></span>
<span><span style="color: var(--shiki-color-text)"> node {</span></span>
<span><span style="color: var(--shiki-color-text)"> id</span></span>
<span><span style="color: var(--shiki-color-text)"> name</span></span>
<span><span style="color: var(--shiki-color-text)"> createdAt</span></span>
<span><span style="color: var(--shiki-color-text)"> disabled</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> pageInfo {</span></span>
<span><span style="color: var(--shiki-color-text)"> hasNextPage</span></span>
<span><span style="color: var(--shiki-color-text)"> endCursor</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> totalCount</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Query IdP users with filtering:
<span><span style="color: var(--shiki-token-keyword)">query</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">GetUsersByName</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> _users(</span></span>
<span><span style="color: var(--shiki-color-text)"> first: </span><span style="color: var(--shiki-token-constant)">5</span></span>
<span><span style="color: var(--shiki-color-text)"> query: { </span><span style="color: var(--shiki-token-string)">names</span><span style="color: var(--shiki-color-text)">: [</span><span style="color: var(--shiki-token-comment)">"john.doe"</span><span style="color: var(--shiki-color-text)">, </span><span style="color: var(--shiki-token-string-expression)">"jane.smith"</span><span style="color: var(--shiki-color-text)">] }</span></span>
<span><span style="color: var(--shiki-color-text)"> ) {</span></span>
<span><span style="color: var(--shiki-color-text)"> edges {</span></span>
<span><span style="color: var(--shiki-color-text)"> node {</span></span>
<span><span style="color: var(--shiki-color-text)"> id</span></span>
<span><span style="color: var(--shiki-color-text)"> name</span></span>
<span><span style="color: var(--shiki-color-text)"> disabled</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Get a specific IdP user:
<span><span style="color: var(--shiki-token-keyword)">query</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">GetUser</span><span style="color: var(--shiki-color-text)">($userId: </span><span style="color: var(--shiki-token-constant)">ID</span><span style="color: var(--shiki-token-keyword)">!</span><span style="color: var(--shiki-color-text)">) {</span></span>
<span><span style="color: var(--shiki-color-text)"> _user(id: $userId) {</span></span>
<span><span style="color: var(--shiki-color-text)"> id</span></span>
<span><span style="color: var(--shiki-color-text)"> name</span></span>
<span><span style="color: var(--shiki-color-text)"> createdAt</span></span>
<span><span style="color: var(--shiki-color-text)"> disabled</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Create a new IdP user:
<span><span style="color: var(--shiki-token-keyword)">mutation</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">CreateUser</span><span style="color: var(--shiki-color-text)">($input: </span><span style="color: var(--shiki-token-constant)">_CreateUserInput</span><span style="color: var(--shiki-token-keyword)">!</span><span style="color: var(--shiki-color-text)">) {</span></span>
<span><span style="color: var(--shiki-color-text)"> _createUser(input: $input) {</span></span>
<span><span style="color: var(--shiki-color-text)"> id</span></span>
<span><span style="color: var(--shiki-color-text)"> name</span></span>
<span><span style="color: var(--shiki-color-text)"> createdAt</span></span>
<span><span style="color: var(--shiki-color-text)"> disabled</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Variables:
<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"input"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"name"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"john.doe"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"password"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"secure-password-123"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"disabled"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">false</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
The password field is optional. If omitted, the user is created without a password and will not be able to log in until a password is set (e.g., via _sendPasswordResetEmail).
<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"input"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"name"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"john.doe"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"disabled"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">false</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Update an IdP user:
<span><span style="color: var(--shiki-token-keyword)">mutation</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">UpdateUser</span><span style="color: var(--shiki-color-text)">($input: </span><span style="color: var(--shiki-token-constant)">_UpdateUserInput</span><span style="color: var(--shiki-token-keyword)">!</span><span style="color: var(--shiki-color-text)">) {</span></span>
<span><span style="color: var(--shiki-color-text)"> _updateUser(input: $input) {</span></span>
<span><span style="color: var(--shiki-color-text)"> id</span></span>
<span><span style="color: var(--shiki-color-text)"> name</span></span>
<span><span style="color: var(--shiki-color-text)"> disabled</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Variables:
<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"input"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"id"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"user-id-here"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"name"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"john.doe.updated"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"disabled"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
To clear a user's password, set clearPassword to true. The user will not be able to log in until a new password is set.
<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"input"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"id"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"user-id-here"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"clearPassword"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-constant)">true</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
The password and clearPassword fields are mutually exclusive. Setting both at the same time will result in an error.
Delete an IdP user:
<span><span style="color: var(--shiki-token-keyword)">mutation</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">DeleteUser</span><span style="color: var(--shiki-color-text)">($userId: </span><span style="color: var(--shiki-token-constant)">ID</span><span style="color: var(--shiki-token-keyword)">!</span><span style="color: var(--shiki-color-text)">) {</span></span>
<span><span style="color: var(--shiki-color-text)"> _deleteUser(id: $userId)</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Send a password reset email:
This mutation sends a password reset email to an IdP user. It can be used for resetting existing IdP users' passwords, setting initial passwords for users created without a password, or setting a new password after clearing a user's password with clearPassword.
<span><span style="color: var(--shiki-token-keyword)">mutation</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-function)">SendPasswordResetEmail</span><span style="color: var(--shiki-color-text)">($input: </span><span style="color: var(--shiki-token-constant)">_SendPasswordResetEmailInput</span><span style="color: var(--shiki-token-keyword)">!</span><span style="color: var(--shiki-color-text)">) {</span></span>
<span><span style="color: var(--shiki-color-text)"> _sendPasswordResetEmail(input: $input)</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Variables:
<span><span style="color: var(--shiki-color-text)">{</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"input"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"userId"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"user-id-here"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-keyword)">"redirectUri"</span><span style="color: var(--shiki-token-punctuation)">:</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string-expression)">"https://your-app.com/reset-password-complete"</span></span>
<span><span style="color: var(--shiki-color-text)"> }</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Password reset emails are sent from no-reply@idp.erp.dev. The redirectUri must be a valid absolute URL with http or https scheme. This operation is only available when use_non_email_identifier is set to false (the default), as it requires users to have email addresses.
User management operations are available only when the IdP service is registered as a subgraph in your application configuration. The GraphQL schema is automatically generated based on the IdP service specification.