diff --git a/CODEOWNERS.md b/CODEOWNERS.md index 9040995fe..410d59f32 100644 --- a/CODEOWNERS.md +++ b/CODEOWNERS.md @@ -1,3 +1 @@ -clairekinde11 -danielrivers -DaveOrDead +* @kinde-oss/giants-kinde diff --git a/POST_BUILD_SCRIPTS.md b/POST_BUILD_SCRIPTS.md new file mode 100644 index 000000000..2f2b4a14c --- /dev/null +++ b/POST_BUILD_SCRIPTS.md @@ -0,0 +1,240 @@ +# Post-Build Scripts + +This document explains the automated post-build scripts that run after every documentation build to generate LLM training files and update security configurations. + +## Overview + +The documentation site runs several post-build scripts automatically after each build to: + +1. **Update Content Security Policy (CSP)** - Ensures security compliance for inline scripts +2. **Generate LLM Training Files** - Creates documentation files optimized for AI/LLM training + +These scripts are integrated into the build process via the `postbuild` npm script and run automatically in CI/CD and local builds. + +## Post-Build Scripts + +### 1. CSP Update Script (`scripts/update-csp.js`) + +**Purpose**: Updates Content Security Policy headers to allow inline scripts generated during the build process. + +**What it does**: +- Scans all HTML files in the `dist/` directory for inline scripts +- Generates SHA256 hashes for each inline script +- Updates the CSP `script-src` directive in `customHttp.yml` with these hashes +- Ensures security compliance while allowing necessary inline scripts + +**Output**: Updates `customHttp.yml` with new script hashes + +### 2. LLM Generation Scripts + +**Purpose**: Generate documentation files optimized for Large Language Model (LLM) training. + +**Generated Files**: +- **`llms.txt`** - Main index file with links to all LLM documentation +- **`llms-abridged.txt`** - Compact version with frontmatter only (title, description, keywords, topics) +- **`llms-full.txt`** - Complete documentation with full content +- **Section-specific files** - Individual files for each documentation section + +## LLM Generated Files + +### Main Files (in `public/`) +- `llms.txt` - Index file with links to all LLM documentation +- `llms-abridged.txt` - Abridged documentation (frontmatter only) +- `llms-full.txt` - Complete documentation with full content + +### Section Files (in `public/_llms-txt/`) +- `authenticate.txt` - Authentication documentation +- `billing.txt` - Billing and subscription management +- `build.txt` - Building applications on Kinde +- `developer-tools.txt` - Developer tools and APIs +- `get-started.txt` - Getting started guides +- `integrate.txt` - Third-party integrations +- `machine-to-machine-applications.txt` - M2M applications +- `manage-users.txt` - User management +- `manage-your-account.txt` - Account management +- `manage-your-apis.txt` - API management +- `properties.txt` - Custom properties +- `workflows.txt` - Workflow automation + +## Build Integration + +### Automatic Execution +All post-build scripts run automatically when you run: +```bash +npm run build +``` + +The build process follows this sequence: +1. **Astro build** - Generates the static site +2. **Post-build scripts** (automatic): + - `scripts/update-csp.js` - Updates CSP headers + - `scripts/generate-llms-txt-abridged.js` - Generates abridged LLM files + - `scripts/generate-llms-txt-full.js` - Generates complete LLM files + - `scripts/generate-llms-txt-sections.js` - Generates section-specific LLM files + +### Package.json Configuration +```json +{ + "scripts": { + "build": "astro build", + "postbuild": "node ./scripts/update-csp.js && node ./scripts/generate-llms-txt-abridged.js && node ./scripts/generate-llms-txt-full.js && node ./scripts/generate-llms-txt-sections.js" + } +} +``` + +## LLM Generation Scripts + +### `scripts/generate-llms-txt-abridged.js` +Generates the abridged documentation file containing only frontmatter data: +- Extracts `title`, `description`, `keywords`, and `topics` from all MDX files +- Creates a compact format suitable for quick reference +- Output: `public/llms-abridged.txt` + +### `scripts/generate-llms-txt-full.js` +Generates the complete documentation file with full content: +- Extracts frontmatter and complete content from all MDX files +- Formats page titles with folder paths (e.g., "Authenticate - About auth") +- Minifies content by removing line breaks +- Output: `public/llms-full.txt` + +### `scripts/generate-llms-txt-sections.js` +Generates individual files for each top-level documentation section: +- Creates separate files for each section (authenticate, billing, etc.) +- Uses the same format as the full documentation +- Output: `public/_llms-txt/[section].txt` + +## Manual Script Execution + +### Prerequisites +- Node.js installed +- Dependencies installed (`npm install`) + +### Run Individual Scripts +```bash +# Update CSP headers only +node scripts/update-csp.js + +# Generate abridged documentation only +node scripts/generate-llms-txt-abridged.js + +# Generate complete documentation only +node scripts/generate-llms-txt-full.js + +# Generate section-specific files only +node scripts/generate-llms-txt-sections.js +``` + +### Run All Post-Build Scripts +```bash +# Run all post-build scripts manually +npm run postbuild +``` + +## File Formats + +### Abridged Format +``` +# Page Title +Page description +keyword1, keyword2, keyword3 +topic1, topic2, topic3 + +# Next Page Title +Next page description +... +``` + +### Full Format +``` +# Section - Page Title - Page Description +> Page description +keyword1, keyword2, keyword3 +topic1, topic2, topic3 +Full page content without line breaks... + +# Next Section - Next Page Title - Next Page Description +... +``` + +## Source Data + +All LLM files are generated from MDX files in `src/content/docs/`. The scripts: +1. Scan all `.mdx` files recursively +2. Extract frontmatter using the `gray-matter` library +3. Parse content and apply formatting rules +4. Write output files to the `public/` directory + +## Dependencies + +### CSP Update Script +- `cheerio` - HTML parsing and manipulation +- `crypto` - SHA256 hash generation +- `js-yaml` - YAML file parsing and writing +- Node.js `fs` and `path` modules + +### LLM Generation Scripts +- `gray-matter` - Frontmatter parsing +- `glob` - File pattern matching +- Node.js `fs` and `path` modules + +## Publishing + +Files in the `public/` directory are automatically served by Astro at the root URL: +- `https://docs.kinde.com/llms.txt` +- `https://docs.kinde.com/llms-abridged.txt` +- `https://docs.kinde.com/llms-full.txt` +- `https://docs.kinde.com/_llms-txt/[section].txt` + +## Maintenance + +### Automatic Updates +All post-build scripts run automatically during: +- Local development builds (`npm run build`) +- CI/CD pipeline builds +- Production deployments + +### Manual Updates +The `llms.txt` file is manually maintained and should be updated when: +- Adding new section files +- Changing file locations +- Updating descriptions or links + +### When Scripts Run +- **CSP Update**: Every build (ensures security compliance) +- **LLM Generation**: Every build (keeps training data current) +- **Content Changes**: Automatically detected and processed + +## Troubleshooting + +### Common Issues +1. **Missing dependencies**: Run `npm install` to ensure all packages are available +2. **File not found errors**: Ensure MDX files exist in `src/content/docs/` +3. **Permission errors**: Check write permissions for the `public/` directory +4. **Empty output**: Verify MDX files have proper frontmatter structure +5. **CSP errors**: Check that `customHttp.yml` exists and is writable +6. **Build failures**: Scripts run in sequence - if one fails, subsequent scripts won't run + +### Validation +After build completion, verify: +- **CSP Update**: Check `customHttp.yml` for updated script hashes +- **LLM Files**: All expected files are created in `public/` and `public/_llms-txt/` +- **File sizes**: Reasonable sizes (not empty or unusually large) +- **Content format**: Properly formatted with frontmatter +- **Links**: All links in `llms.txt` point to existing files + +### Build Output +Successful build should show: +``` +> documentation@0.0.1 postbuild +> node ./scripts/update-csp.js && node ./scripts/generate-llms-txt-abridged.js && node ./scripts/generate-llms-txt-full.js && node ./scripts/generate-llms-txt-sections.js + +YAML configuration has been updated. +Abridged documentation created: public/llms-abridged.txt +Processed 392 files +Complete documentation created: public/llms-full.txt +Processed 392 files +Generating section documentation files... +Found 16 sections: authenticate, billing, build, contribute, design, developer-tools, get-started, integrate, machine-to-machine-applications, manage-users, manage-your-account, manage-your-apis, properties, releases, trust-center, workflows +... +All section documentation files have been generated in public/_llms-txt/ +``` diff --git a/astro.config.mjs b/astro.config.mjs index 576cf63a4..9820a4fb8 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -35,9 +35,11 @@ export default defineConfig({ enabled: false }, redirects: { + "/sitemap.xml": "/sitemap-0.xml", "/developer-tools/kinde-api/register-manage-apis/": "/developer-tools/your-apis/register-manage-apis/", - "/developer-tools/kinde-api/protect-your-api/": "/developer-tools/your-apis/protect-your-api/", + "/developer-tools/kinde-api/protect-your-api/": + "/developer-tools/your-apis/protect-your-api/", "/developer-tools/kinde-api/access-to-your-api/": "/developer-tools/your-apis/access-to-your-api/", "/developer-tools/kinde-api/custom-api-scopes/": @@ -51,7 +53,221 @@ export default defineConfig({ "/developer-tools/kinde-api/test-the-connection-to-kindes-api/": "/developer-tools/kinde-api/troubleshoot-kinde-api/", "/developer-tools/sdks/native/expo-react-native/": - "/developer-tools/sdks/native/expo/" + "/developer-tools/sdks/native/expo/", + "/design/pages/design-your-welcome-pages/": + "/design/brand/apply-branding-for-an-organization/", + "/developer-tools/guides/deploy-on-vercel/kinde.com/": + "/developer-tools/guides/deploy-on-vercel/", + "/design/pages/set-language-for-pages/": + "/design/content-customization/set-language-for-pages/", + "/design/pages/internationalization/": + "/design/content-customization/set-language-for-pages/", + + // Section-level redirects to prevent 404s when users truncate URLs + "/authenticate/": + "/authenticate/about-auth/about-authentication/", + "/billing/": + "/billing/about-billing/about-billing/", + "/build/": + "/build/applications/about-applications/", + "/design/": + "/design/brand/global-brand-defaults/", + "/developer-tools/": + "/developer-tools/about/our-sdks/", + "/get-started/": + "/get-started/apis-and-sdks/about-kinde-apis/", + "/integrate/": + "/integrate/connected-apps/add-connected-apps/", + "/machine-to-machine-applications/": + "/machine-to-machine-applications/about-m2m/authenticate-with-m2m/", + "/manage-your-account/": + "/manage-your-account/business-information/update-your-details/", + "/manage-users/": + "/manage-users/about/manage-users-across-organizations/", + "/properties/": + "/properties/about-properties/application-properties/", + "/releases/": + "/releases/about/about-feature-flags/", + "/trust-center/": + "/trust-center/agreements/terms-of-service/", + "/workflows/": + "/workflows/about-workflows/", + "manage-your-apis/": + "manage-your-apis/about-api-keys/api-keys-overview/", + + // Authenticate section subfolder redirects + "/authenticate/about-auth/": + "/authenticate/about-auth/about-authentication/", + "/authenticate/auth-guides/": + "/authenticate/auth-guides/enterprise-connections-identity/", + "/authenticate/authentication-methods/": + "/authenticate/authentication-methods/email-authentication/", + "/authenticate/custom-configurations/": + "/authenticate/custom-configurations/authentication-experience/", + "/authenticate/enterprise-connections/": + "/authenticate/enterprise-connections/about-enterprise-connections/", + "/authenticate/manage-authentication/": + "/authenticate/manage-authentication/authenticated-sessions-across-multiple-applications/", + "/authenticate/multi-factor-auth/": + "/authenticate/multi-factor-auth/about-multi-factor-authentication/", + "/authenticate/social-sign-in/": + "/authenticate/social-sign-in/add-social-sign-in/", + + // Billing section subfolder redirects + "/billing/about-billing/": + "/billing/about-billing/about-billing/", + "/billing/billing-user-experience/": + "/billing/billing-user-experience/add-pricing-table/", + "/billing/get-started/": + "/billing/get-started/add-billing-role/", + "/billing/manage-plans/": + "/billing/manage-plans/about-plans/", + "/billing/manage-subscribers/": + "/billing/manage-subscribers/add-metered-usage/", + "/billing/payment-management/": + "/billing/payment-management/manage-stripe-connection/", + "/billing/pricing/": + "/billing/pricing/pricing-models/", + + // Build section subfolder redirects + "/build/applications/": + "/build/applications/about-applications/", + "/build/domains/": + "/build/domains/pointing-your-domain/", + "/build/env-variables/": + "/build/env-variables/add-manage-env-variables/", + "/build/environments/": + "/build/environments/environments/", + "/build/organizations/": + "/build/organizations/add-and-manage-organizations/", + "/build/set-up-options/": + "/build/set-up-options/access-policies/", + "/build/tokens/": + "/build/tokens/about-access-tokens/", + + // Design section subfolder redirects + "/design/brand/": + "/design/brand/global-brand-defaults/", + "/design/content-customization/": + "/design/content-customization/how-content-is-managed/", + "/design/customize-with-code/": + "/design/customize-with-code/connect-repo/", + "/design/pages/": + "/design/pages/page-layout/", + + // Your APIs section subfolder redirects + "/manage-your-apis/about-api-keys/": + "/manage-your-apis/about-api-keys/api-keys-overview/", + "/manage-your-apis/add-manage-api-keys/": + "/manage-your-apis/add-manage-api-keys/create-an-api-key/", + "/manage-your-apis/troubleshoot-api-keys/": + "/manage-your-apis/troubleshoot-api-keys/common-api-key-errors/", + + // Developer tools section subfolder redirects + "/developer-tools/about/": + "/developer-tools/about/our-sdks/", + "/developer-tools/account-api/": + "/developer-tools/account-api/about-account-api/", + "/developer-tools/guides/": + "/developer-tools/guides/code-sync-errors/", + "/developer-tools/kinde-api/": + "/developer-tools/kinde-api/about-m2m-scopes/", + "/developer-tools/sdks/backend/": + "/developer-tools/sdks/backend/apollo-graphql/", + "/developer-tools/sdks/frontend/": + "/developer-tools/sdks/frontend/javascript-sdk/", + "/developer-tools/sdks/native/": + "/developer-tools/sdks/native/android-sdk/", + "/developer-tools/your-apis/": + "/developer-tools/your-apis/access-to-your-api/", + + // Get started section subfolder redirects + "/get-started/apis-and-sdks/": + "/get-started/apis-and-sdks/about-kinde-apis/", + "/get-started/connect/": + "/get-started/connect/callback-urls/", + "/get-started/guides/": + "/get-started/guides/byo-code/", + "/get-started/learn-about-kinde/": + "/get-started/learn-about-kinde/kinde-product-security/", + "/get-started/switch-to-kinde/": + "/get-started/switch-to-kinde/auth0-to-kinde/", + "/get-started/team-and-account/": + "/get-started/team-and-account/add-team-members/", + + // Integrate section subfolder redirects + "/integrate/connected-apps/": + "/integrate/connected-apps/add-connected-apps/", + "/integrate/third-party-tools/": + "/integrate/third-party-tools/cloudflare-zero-trust/", + "/integrate/webhooks/": + "/integrate/webhooks/about-webhooks/", + + // Machine-to-machine applications section subfolder redirects + "/machine-to-machine-applications/m2m-application-setup/": + "/machine-to-machine-applications/m2m-application-setup/add-feature-flags-to-m2m-applications/", + "/machine-to-machine-applications/m2m-token-customization/": + "/machine-to-machine-applications/m2m-token-customization/customize-m2m-tokens/", + "/machine-to-machine-applications/m2m-workflow-automation/": + "/machine-to-machine-applications/m2m-workflow-automation/m2m-workflow/", + "/machine-to-machine-applications/organization-scoped-m2m-apps/": + "/machine-to-machine-applications/organization-scoped-m2m-apps/enforce-org-m2m-access-in-your-api/", + "/machine-to-machine-applications/troubleshooting-m2m/": + "/machine-to-machine-applications/troubleshooting-m2m/troubleshoot-m2m-token-errors/", + + // Manage your account section subfolder redirects + "/manage-your-account/business-information/": + "/manage-your-account/business-information/change-your-business-time-zone/", + "/manage-your-account/profile-and-plan/": + "/manage-your-account/profile-and-plan/change-kinde-plan/", + "/manage-your-account/your-data/": + "/manage-your-account/your-data/check-your-mau/", + + // Manage users section subfolder redirects + "/manage-users/access-control/": + "/manage-users/access-control/accept-policies-signup/", + "/manage-users/add-and-edit/": + "/manage-users/add-and-edit/add-and-edit-users/", + "/manage-users/roles-and-permissions/": + "/manage-users/roles-and-permissions/apply-roles-and-permissions-to-users/", + "/manage-users/view-activity/": + "/manage-users/view-activity/hotjar/", + + // Properties section subfolder redirects + "/properties/work-with-properties/": + "/properties/work-with-properties/manage-properties/", + + // Releases section subfolder redirects + "/releases/about/": + "/releases/about/about-feature-flags/", + "/releases/feature-flags/": + "/releases/feature-flags/add-feature-flag/", + "/releases/guides/": + "/releases/guides/guide-to-app-store-approvals/", + + // Trust center section subfolder redirects + "/trust-center/agreements/": + "/trust-center/agreements/end-user-licence-agreement/", + "/trust-center/kinde-performance/": + "/trust-center/kinde-performance/service-status/", + "/trust-center/privacy-and-compliance/": + "/trust-center/privacy-and-compliance/compliance/", + "/trust-center/security/": + "/trust-center/security/security-at-kinde/", + + // Workflows section subfolder redirects + "/workflows/bindings/": + "/workflows/bindings/access-token-binding/", + "/workflows/configuration/": + "/workflows/configuration/bindings/", + "/workflows/example-workflows/": + "/workflows/example-workflows/existing-password-provided-workflow/", + "/workflows/getting-started/": + "/workflows/getting-started/connect-repo-for-workflows/", + "/workflows/manage-workflows/": + "/workflows/manage-workflows/create-workflow/", + "/workflows/observability/": + "/workflows/observability/workflow-build-logs/", }, markdown: { rehypePlugins: [ @@ -111,7 +327,12 @@ export default defineConfig({ applyBaseStyles: false }), icon(), - sitemap(), + sitemap({ + filter: (page) => !page.includes('404'), + customPages: [ + 'https://docs.kinde.com/' + ] + }), AutoImport({ imports: [ "./src/components/SDKSelector.astro", diff --git a/customHttp.yml b/customHttp.yml index 97341b4df..352aa678b 100644 --- a/customHttp.yml +++ b/customHttp.yml @@ -5,12 +5,13 @@ customHeaders: value: >- default-src 'self' *.kinde.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; frame-src - https://www.youtube-nocookie.com; child-src 'self'; connect-src 'self' - ws https://api.management.inkeep.com https://api.inkeep.com - wss://api.inkeep.com https://api.hsforms.com https://app.kinde.com - https://kinde.com https://kinde-api-docs-proxy.pages.dev; base-uri - 'none'; font-src 'self' https://fonts.gstatic.com; img-src 'self' - data: https://storage.googleapis.com https://imagedelivery.net + https://www.youtube-nocookie.com; child-src 'self'; + connect-src 'self' wss: https://api.management.inkeep.com + https://api.inkeep.com wss://api.inkeep.com https://api.hsforms.com + https://app.kinde.com https://kinde.com + https://kinde-api-docs-proxy.pages.dev https://analytics.usehall.com; + base-uri 'none'; font-src 'self' https://fonts.gstatic.com; img-src + 'self' data: https://storage.googleapis.com https://imagedelivery.net https://customer-xcbruusbiervz265.cloudflarestream.com https://i.ytimg.com; media-src 'self' https://customer-xcbruusbiervz265.cloudflarestream.com @@ -44,7 +45,9 @@ customHeaders: 'sha256-8JLcQFZQruxl3jMUwogr3y5/GMmZPAc+j2mNi7gywmw=' 'sha256-w78n7W12c94ck4KhBCBA4NrjqkbDvSutqee+u+no0Tg=' 'sha256-/4BQzbQ0kgR1l13wtSM3rZ7nSvyV3PX/ShEfhZA1WoQ=' - 'sha256-zB5rUhTjHzt+r/RjhhI8CyMb5Y63k+J7ICVfQ7iHJqA=' 'self' + 'sha256-zB5rUhTjHzt+r/RjhhI8CyMb5Y63k+J7ICVfQ7iHJqA=' + 'sha256-fFmtUWM/kGeUru+1rcCArLmnXKoEjis5I/dYQkZA+HM=' + 'sha256-13ENHEoc4foVPMgYwApSstLrIGX/6Y5xvroD2DkDFcE=' 'self' widgets.kinde.com kinde.com https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.23.5/dist/browser/standalone.min.js - key: Strict-Transport-Security @@ -74,11 +77,11 @@ customHeaders: https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.23.5/dist/browser/standalone.min.js 'unsafe-inline' 'self' widgets.kinde.com kinde.com; font-src https://fonts.scalar.com 'self' https://fonts.gstatic.com; connect-src - 'self' ws https://api.management.inkeep.com https://api.inkeep.com + 'self' wss: https://api.management.inkeep.com https://api.inkeep.com wss://api.inkeep.com https://api.hsforms.com https://app.kinde.com https://kinde.com https://api-spec.kinde.com - https://kinde-api-docs-proxy.pages.dev; img-src - https://storage.googleapis.com + https://kinde-api-docs-proxy.pages.dev https://analytics.usehall.com; + img-src https://storage.googleapis.com - pattern: /kinde-apis/frontend/* headers: - key: Content-Security-Policy @@ -88,8 +91,8 @@ customHeaders: https://cdn.jsdelivr.net/npm/@scalar/api-reference@1.23.5/dist/browser/standalone.min.js 'unsafe-inline' 'self' widgets.kinde.com kinde.com; font-src https://fonts.scalar.com 'self' https://fonts.gstatic.com; connect-src - 'self' ws https://api.management.inkeep.com https://api.inkeep.com + 'self' wss: https://api.management.inkeep.com https://api.inkeep.com wss://api.inkeep.com https://api.hsforms.com https://app.kinde.com https://kinde.com https://api-spec.kinde.com - https://kinde-api-docs-proxy.pages.dev; img-src - https://storage.googleapis.com + https://kinde-api-docs-proxy.pages.dev https://analytics.usehall.com; + img-src https://storage.googleapis.com diff --git a/package.json b/package.json index 5d5feea59..9b2daae7d 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "preview": "astro preview", "astro": "astro", "lint": "npx prettier \"src/content/docs/**/*\" --write --ignore-unknown", - "postbuild": "node ./scripts/update-csp.js" + "postbuild": "node ./scripts/update-csp.js && node ./scripts/generate-llms-txt-abridged.js && node ./scripts/generate-llms-txt-full.js && node ./scripts/generate-llms-txt-sections.js" }, "dependencies": { "@astrojs/mdx": "^4.0.3", diff --git a/public/_llms-txt/authenticate.txt b/public/_llms-txt/authenticate.txt new file mode 100644 index 000000000..5376d4654 --- /dev/null +++ b/public/_llms-txt/authenticate.txt @@ -0,0 +1,627 @@ +--- +page_id: 9b0c1d2e-3f4a-5b6c-7d8e-9f0a1b2c3d4e +title: Kinde Documentation - Authenticate +description: "Complete documentation for Kinde's authenticate section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section for LLM training" +sidebar: + order: 1 +topics: + - llm + - documentation + - training + - authenticate +sdk: [] +languages: + - markdown + - text +audience: developers +complexity: beginner +keywords: + - llm training + - documentation + - authenticate + - section + - frontmatter + - metadata + - kinde +updated: 2025-09-18 +featured: false +deprecated: false +ai_summary: "Complete documentation for Kinde's authenticate section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section for LLM training" +--- + +# Kinde Documentation - Authenticate + +This is the complete documentation for Kinde's authenticate section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section. + +# Authenticate - About auth - About Kinde authentication + +> Learn about Kinde's authentication methods including password, passwordless, social sign-in, and enterprise connections. + +authentication, sign up, sign in, password, passwordless, social login, enterprise, SSO +authenticate + +Kinde makes authentication easy by providing a range of methods to choose from. Allow your users to sign up or sign in: - [by invitation only](/authenticate/custom-configurations/disable-sign-up/) - using self-sign-up (default) - [with a password](/authenticate/authentication-methods/password-authentication/) - [passwordless](/authenticate/authentication-methods/passwordless-authentication/) (Applied by default in all new Kinde businesses) - with a [phone number](/authenticate/authentication-methods/phone-authentication/) - with a range of [social sign in options](/authenticate/social-sign-in/add-social-sign-in/), like Google, Apple, Slack, and more - via [enterprise connections](/authenticate/enterprise-connections/about-enterprise-connections/) such as Cloudflare or SAML Authentication can be set per environment, and can be changed for different applications, e.g. your production web app and mobile app can have different authentication requirements. You can start simple with email self-sign-up, and then add more options as needed, such as social sign in and multi-factor authentication. ## Multi-domain authentication Kinde supports: - authenticated sessions across domains and subdomains - users switching between domains and subdomains Kinde supports multi-domain authentication where the primary domain is the same, but there are different subdomains. For example, `website.yourdomain.com`, `app.yourdomain.com`, `docs.yourdomain.com`. This is similar to how Google manages authentication for `calendar.google.com`, `mail.google.com`, etc. Once a user is signed in to one domain or subdomain, they can switch to another and remain authenticated. To do this, you need to initiate the flow with `prompt=none` as part of the auth URL. This checks for a session on Kinde invisibly. If it exists the user experiences a seamless session between sites, and if a session doesn’t exist, they are prompted to reauthenticate. See also, [Manage authentication across applications](/authenticate/manage-authentication/user-auth-applications/). ## Rate limiting and identity management issues if third party keys not entered When setting up third party authentication, such as [social sign in](/authenticate/social-sign-in/add-social-sign-in/), ensure you have added the third party app, and included the Client ID and Client Secret (Keys) to the configuration screens in your live environment. If you don’t use your own app's keys: - Kinde will fall back to using our own credentials as a proxy, which will cause rate limiting - For Apple SSO specifically, if you don't use your own app from the start, users will be permanently associated with the wrong app and cannot be transferred later Using the Kinde app is okay for local development environments, but not for live production environments. ## Get started with authentication Before setting up authentication, think about what your audience preferences are and how you want to manage access in the short and longer term. Enabling social sign in GitHub, for example, might be expected if your audience are software developers. Here’s a common set of tasks for getting started. 1. [Set up user authentication](/authenticate/authentication-methods/set-up-user-authentication/) 2. [Add social sign in](/authenticate/social-sign-in/add-social-sign-in/) 3. [Enable multi-factor authentication](/authenticate/multi-factor-auth/enable-multi-factor-authentication/) + +# Authenticate - About auth - Ways to authenticate + +> Detailed guide to all authentication methods supported by Kinde including email, phone, social, and enterprise authentication. + +email authentication, password, passwordless, phone auth, SMS, social login, enterprise SSO, OTP +authenticate + +Kinde supports the following authentication methods. For instructions on how to switch on each method for your apps, see [Set up user authentication](/authenticate/authentication-methods/set-up-user-authentication/). ## Email authentication ### Password You can set up authentication so users can authenticate via email using a [password](/authenticate/authentication-methods/password-authentication/). The password needs to be at least 8 characters and popular passwords are blocked. If allowing this method, you should encourage users to use a password manager to increase security. Users will be prompted to verify their email address when they first sign up, using a one time code. ### Passwordless For [passwordless](/authenticate/authentication-methods/passwordless-authentication/) authentication, set up authentication so users can authenticate via email or username using a one time code. When you activate this option, users will be sent a one-time password (OTP) to confirm their identity when they sign in. This option is more secure than using passwords, which need to be stored and protected by the user. Users will be prompted to verify their email address when they first sign up, also using an OTP. Kinde does not currently support magic links as a passwordless authentication method, as they are less secure than an OTP. ## Phone authentication You can allow users to authenticate using their phone number as their sign in identity. This is a passwordless method. Once set up, users enter their phone number on the sign in screen and then enter a one-time passcode (sent via SMS) on the next screen. ### Passwordless via SMS For users to receive a sign in code via SMS, you need to set up a connection to [Twilio](https://www.twilio.com/en-us), who offer a messaging service for authenticating via SMS. You will need a Twilio account to set up this auth option in Kinde. See [Set up phone authentication](/authenticate/authentication-methods/phone-authentication/). Once set up, users will receive a one time code via SMS that enables them to complete the sign up process to your application or site. If you’re switching to Kinde from another auth provider, you can [import phone numbers with other user details](/manage-users/add-and-edit/import-users-in-bulk/) (such as email, first name, last name, etc.) to support authentication. ### OTP message format The SMS message that users receive through Kinde auth complies with OTP best practice. Here’s an example: The content and format of the OTP SMS message is not editable. You’ll notice that the last part of the message includes a duplication of the OTP - `@bound_domain.xxx.dk #OTP_CODE` in the last line of the message. This keeps the OTP secured to the specified domain and allows browsers to reliably extract the OTP. The reason the OTP is included at the start of the message as well, is so that it can be read easily from a short notification popup. ## Social authentication You can let users sign up and sign in using social profiles. This requires some admin setup work and developer skills. **Returning users matched by email** Unlike some other authentication providers, Kinde automatically matches some accounts on sign up by matching verified email addresses. This means that if a user signs up with Google the first time, and they come back and sign up again with Slack, and the same email is detected (and the emails are verified), then the accounts get linked. See the [individual social sign in](/authenticate/social-sign-in/add-social-sign-in/) instructions. ## Enterprise authentication Kinde supports the use of [Microsoft Entra ID](/authenticate/enterprise-connections/azure/) and [SAML](/authenticate/enterprise-connections/custom-saml/) as an enterprise-level single sign on (SSO) authentication methods. These methods are more suited to big corporate and government organizations. + +# Authenticate - About auth - User identity and verification + +> Understanding how user identity and verification works in Kinde, including identity types, trusted providers, and verification processes. + +user identity, verification, trusted providers, email verification, social identity, enterprise identity, profile sync +authenticate + +A key part of making authentication secure, is through verification of user identities. Verification usually happens at sign up, to ensure the person signing up exists and is the intended person gaining access to your app or project. This topic is a conceptual overview of how identity works in Kinde. There are two parts to a user’s identity in Kinde: - Kinde profile - first name, last name, and picture - Identity details - information a user can sign in with: Email, phone, social, enterprise. This is explained in more detail below. ## Identity When we use the term ‘identity’, we’re referring to a unique identifier that allows a user to sign in and be verified. An email, phone number, SSO provider, etc. When a user tries to access a system or service, they provide their identity along with additional credentials (e.g. password, one-time password OTP) to verify their identity and gain access. ## Types of identities ### Identity credentials This refers to an email, phone number, or username. Identity credentials are created for a user when they first sign up with an email address, phone number, or username. If it’s the first identity to be added, it will be marked as primary. You can [manually add these user identities](/manage-users/add-and-edit/add-manage-user-identities/). ### Social A social identity is created when a user signs up with a social account or when they sign in with a trusted provider, who supplies a verified email that matches an existing email identity in Kinde. If a user signs up with a trusted social provider that provides us a verified email, and an email identity does not exist for the user, Kinde creates an email identity with this email. They can use this email to sign in with (if an email authentication method is enabled for your application). ### Enterprise An enterprise identity is created when a user signs up via an enterprise connection, or when they sign in via a trusted provider who supplies a verified email that matches an existing email identity. Users with enterprise identities in Kinde can't also have other identity types in Kinde. E.g. a user can have an email identity and a social identity. But if a user has an enterprise identity, they cannot have other identities. In this case, identity information is sourced with the identity provider and is managed via the identity provider, not in Kinde. ## Trusting emails from providers ### Trusted emails A trusted email provider is one that guarantees the email they issue is verified and also does not allow the user to change their primary email address. Currently Google is the only provider we treat as trusted by default. But you can choose to trust emails from any provider when you configure them in Kinde (See below). You can also choose not to trust Google emails if you want. **Google example** 1. When a user signs up, the Kinde profile first name, last name and picture are populated from Google. 2. If Google is a trusted provider, we create a social identity and an email identity. 3. The user can sign in with either Google or their email (if this auth method is allowed). ### Untrusted emails This isn’t to say that other email providers are not trustworthy, this purely relates to email addresses and the guarantee that it will not change. **LinkedIn example** 1. When a user signs up, the Kinde profile first name, last name and picture are populated from LinkedIn. 2. If LinkedIn is an untrusted email provider, we only create a social identity. 3. At this stage the user can only sign in with their LinkedIn account. ### Trust an untrusted provider When you set up an enterprise connection or a social connection, you can select the option to trust them. For example, go to **Settings > Authentication > Social connections** and select **Configure** on a tile. You’ll see the **Trust this connection** switch. Switch on or off as you like. ## Email sign up flow example 1. When a user signs up with email, the Kinde profile first name, last name are populated by the user (if you ask for it as part of the sign up flow). Their picture will be populated from Gravatar if it exists. 2. Kinde creates a primary contact email using the address they signed up with. They can only sign in with this email address. 3. If the same user returns and signs in with a trusted connection, e.g. Google, Kinde recognises that a user exists and the email address is from a trusted provider, so we add a Google identity to their profile. 4. The Kinde profile first name, last name and picture are updated by Google (if profile syncing is also turned on). 5. The user can sign in using either email or Google. ## Keeping identities in sync ### Social provider syncing If a social provider gives us a new first name, last name or picture for a user, Kinde updates these fields in the user profile to match those supplied to us. This is on by default, but you can turn it off if you wish to keep a static profile. [About profile sync](/manage-users/about/). If you have syncing off at an environment level but turned on at a social connection level we will honor the request for the social connection to sync. ### Enterprise connection syncing If an enterprise provider gives us a new first name, last name, or picture for a user, Kinde updates these fields in the user profile to match those supplied to us. This is on by default, but you can turn it off if you wish to keep a static profile. [About profile sync](/manage-users/about/). If you have syncing off at an environment level but turned on at an enterprise connection level we will honor the request for the enterprise connection to sync. ## Identity verification Verification is an authentication security measure that checks the person seeking system access is who they say they are. In addition, an up to date identity provides a secure method to contact a user. Email identity details are required, for example, to reset a user’s password (requested or forced), and are needed to reliably send OTPs and trigger other auth mechanisms, like auth apps. ## Username identities must have an email At Kinde, we don’t treat username identities the same as phone and email identities. If you want users to sign in and authenticate with usernames, they still need to verify themselves (if only once) via email. ## Cases in usernames Kinde treats usernames as case-insensitive. In other words, we ignore case. We do this because it eliminates the possibility of auth issues and fraud when two usernames are identical in every aspect except the case of one of their letters. We are happy to support users choosing an aesthetically pleasing username combination, like `RosyRose` or `BuilderBob`. We just don't also support separate identities for `rosYrosE` and `BUilderbob`. ## When an identity changes For security reasons, you can’t edit a user’s verified identity. But we know it still needs to be possible. People change emails, change names, get new phone numbers, etc. You can update identities by adding a new identity and deleting the old one. See [Add and manage user identities](/manage-users/add-and-edit/add-manage-user-identities/), or [via the Kinde API](/kinde-apis/management/). + +# Authenticate - About auth - Top questions about Kinde authentication + +> A collection of the top questions and answers about how to set up and configure Kinde authentication for your user's needs. + +login, sign in, popup, error, sessions, tokens, auth +authentication, enterprise auth, SSO, social sign-in, authentication issues, user access control, user access, user authentication + +Here’s some short answers to the most common authentication questions. Click on any question to expand the answer. ## Authentication methods & core functionality
How do I choose the right Kinde authentication method for my SaaS product's user base? Think about who you're building for and what they're used to. If you're targeting developers, they'll probably expect GitHub or GitLab sign-in options. Building something for everyday consumers? Google and Apple sign-in will feel familiar and remove friction. Got enterprise customers? They'll likely need SAML or Microsoft Entra ID to keep their IT teams happy. You don't need to figure it all out upfront. Start simple with email authentication and add more options as you grow. Your web app and mobile app can even have different auth requirements if that makes sense for your users. [Learn more about authentication methods](/authenticate/about-auth/about-authentication/)
What's the difference between Kinde's password and passwordless authentication, and which should I implement? With passwords, your users create and remember their own passwords (we enforce 8+ characters and block common ones). With passwordless, we send them a one-time code via email or SMS instead. Passwordless is genuinely more secure - no passwords to store, steal, or forget, and codes expire after 2 hours. Just know you can't mix both methods for the same app - it's one or the other. If you're building something mobile-first or want to reduce support tickets about forgotten passwords, passwordless is your friend. [Password authentication guide](/authenticate/authentication-methods/password-authentication/) | [Passwordless authentication guide](/authenticate/authentication-methods/passwordless-authentication/)
How does Kinde's automatic account linking work? Kinde automatically connect accounts when someone uses the same verified email across different sign-in methods. So if someone first signs up with Google, then later tries to create an account with Slack using the same email, we'll link them together automatically. No duplicate accounts, no confusion. They can sign in with either method to access the same account. Once your users verify their email with any method, all their sign-in options with that email will work seamlessly together. [Learn about identity and verification](/authenticate/about-auth/identity-and-verification/)
Can I set different Kinde authentication requirements for different parts of my application? Absolutely! This is one of those features that sounds complicated but actually makes total sense. Set up your baseline authentication methods at the environment level, then customize per application or organization as needed. Maybe your main web app uses social sign-in to keep things simple, while your mobile app needs phone authentication, or you want business customers to use MFA while keeping consumer sign-up super easy. It's all about matching the auth experience to what makes sense for each user group. [Configure authentication options](/authenticate/authentication-methods/set-up-user-authentication/)
How do I handle Kinde authentication across multiple domains and subdomains? We've got this covered with multi-domain authentication. Think about how Google lets you stay signed in whether you're on Gmail, Calendar, or Drive - same idea. Users can hop between `website.yourapp.com`, `app.yourapp.com`, `docs.yourapp.com` and stay authenticated. The trick is using `prompt=none` in your auth URL, which invisibly checks for an existing session. If they're already signed in elsewhere, it's seamless. If not, they'll get prompted to sign in again. [About Kinde authentication](/authenticate/about-auth/about-authentication/)
What happens when my users can't receive their Kinde auth verification codes? Tell them to check their spam folder first. This fixes it most of the time because email providers can be overly protective. For SMS codes, make sure they've got decent cell reception. If they're taking too long (codes expire after 2 hours), they'll need to request a fresh one. And if you're using SMS auth, double-check that your Twilio setup is working properly - that's usually where things go sideways. [Passwordless authentication troubleshooting](/authenticate/authentication-methods/passwordless-authentication/)
## Social sign-in
How do I set up Kinde social authentication without compromising security for my production app? Before you go live, you absolutely must swap out Kinde's default social credentials with your own. We let you use ours for testing, but keeping them in production is asking for trouble - security risks, performance issues, and you'll be stuck if you ever want to switch providers. Create your own apps with Google, GitHub, Apple, whatever you're using, grab your Client ID and Client Secret, and put them into Kinde's social connection settings. Don't forget to add your custom domain callbacks if you're using those. [Add and manage social connections](/authenticate/social-sign-in/add-social-sign-in/)
Some social providers don't provide email addresses. How does Kinde maintain these user identities? Some social providers (looking at you, X/Twitter and Apple) don't always hand over email addresses, but we need them for security things like password resets. When this happens, we'll ask your users for an email address just once during their first sign-up. After that one-time thing, they can sign in with their social account without any hassle. It's a small bump in the road that keeps everyone secure. [X social sign-in](/authenticate/social-sign-in/twitter/) | [Apple social sign-in](/authenticate/social-sign-in/apple/)
How can I use Kinde to create a seamless social authentication experience for my users? If you're going all-in on social auth (no email/password fallbacks), you can create a pretty slick experience. Users click your sign-in button and boom - straight to Google's or Apple's account picker. Set up custom authentication pages and use the `connectionId` parameter to skip our initial screens entirely. The only catch? We'll still handle verification and MFA screens because, well, security matters and we're good at it. [Custom authentication pages](/authenticate/custom-configurations/custom-authentication-pages/)
Should I mark social connections as "trusted providers" in Kinde? Generally, no - leave this off for better security. "Trusted provider" means we'll take their word that emails are verified, but here's the thing: people change email addresses, and social providers don't always keep up. Only flip this switch if you're 100% certain the provider maintains verified, current email addresses. When in doubt, err on the side of caution. [Social connections configuration](/authenticate/social-sign-in/add-social-sign-in/)
## Enterprise authentication & SAML
How do I set up Kinde SAML authentication for enterprise customers? SAML setup is where things get a bit technical, but stick with us. Kinde acts as the service provider while your enterprise customer brings their own identity provider (Google Workspace, Microsoft Entra ID, Cloudflare, whatever they're using). You'll create an enterprise connection in Kinde, make up a unique Entity ID (just a random string like "870sa9fbasfasdas23aghkhc12zasfnasd"), and get their IdP metadata URL. They'll need to add your ACS URL to their setup. Pro tip: generate certificate and private key pairs for extra security, and always test in a sandbox environment first. [Custom SAML setup](/authenticate/enterprise-connections/custom-saml/)
What do I use home realm domains for in Kinde enterprise connections? Home realm domains are basically a shortcut that makes enterprise sign-in smoother. When you set `bigcorp.com` as a home realm domain, anyone with a "@bigcorp.com" email gets automatically routed to their company's sign-in flow - no extra clicks needed. Just remember that each domain can only be used once across all your connections, so no sharing. And the SSO button disappears by default when you use this (though you can bring it back if needed). [Microsoft Entra ID setup](/authenticate/enterprise-connections/azure/)
What's the best way to migrate enterprise users to Kinde? Get your enterprise connections set up in Kinde first - SAML, Entra ID, whatever they're using. Then when you import their user data (via CSV or JSON), we'll automatically match everyone to the right connection based on their email addresses. This means their sign-in experience stays exactly the same - they won't even notice you've switched to Kinde behind the scenes. Import their roles and permissions too if you've got them. [Migrate to Kinde](/get-started/switch-to-kinde/switch-to-kinde-for-user-authentication/)
How do I handle enterprise users who are already signed into their identity provider with Kinde? When enterprise users sign out of your app, they're only signing out of Kinde, not their company's identity provider (like Entra ID). This is totally normal for federated auth - it's how most enterprise setups work. If your customer really needs full sign-out from both systems, you'll need to build additional logout flows, but honestly, most companies prefer it this way. [Entra ID SAML connection](/authenticate/enterprise-connections/entra-id-saml/)
## Multi-factor authentication
How do I use Kinde to implement MFA for different types of customers? MFA is one of those things where one size definitely doesn't fit all. You can set it up for everyone (environment level) or get granular with specific customer segments (organization level). Finance and government customers? They'll probably want mandatory MFA. Consumer-facing app? Maybe make it optional so you don't scare people away. Kinde supports email codes, SMS codes, and authenticator apps as second factors. Just don't use the same method twice - as in don't make email the primary and secondary auth method. That could be confusing. [Enable multi-factor authentication](/authenticate/multi-factor-auth/enable-multi-factor-authentication/)
Can I exempt certain users or connections from MFA requirements in Kinde? Yep, you've got options here. You can exempt specific roles (maybe only admins need MFA) or exempt enterprise connections where MFA is already handled by their company's identity provider. Nobody wants double MFA - that's just annoying. Set these exemptions at the organization level, and if someone has a mix of exempt and non-exempt roles, MFA kicks in by default (better safe than sorry). [Set MFA per organization](/authenticate/multi-factor-auth/mfa-per-org/)
How do I help users who are having trouble with MFA? Make the instructions super clear for each method you support. For authenticator apps, walk them through the QR code scanning and emphasize saving those backup codes (they will lose them otherwise). For SMS, double-check they're entering phone numbers correctly with country codes. For email codes, check spam folder. Always give users a way to contact you when they get locked out - it happens to the best of us. You can also [reset MFA for a user](/manage-users/access-control/reset-multi-factor-authentication-for-a-user/). [Multi-factor authentication guide](/authenticate/multi-factor-auth/enable-multi-factor-authentication/)
## Username authentication
Do people still use username authentication? Does Kinde allow this? Absolutely Kinde supports this. Username auth is perfect when you want to give users more personality in their sign-in experience or when your app has that community vibe (think gaming platforms or developer tools). They'll still need to verify their email once for security (we're not animals), but after that they can sign in with their chosen username. Works with both password and passwordless methods, so you've got flexibility there. [Username authentication guide](/authenticate/authentication-methods/username-authentication/)
How does Kinde handle username uniqueness and case sensitivity? We treat usernames as case-insensitive because life's too short for "BuilderBob" vs "builderbob" authentication headaches. Users can still make their aesthetic choices like "RosyRose" or "DevDan" for display, but behind the scenes we're not picky about capitalization. This prevents fraud attempts and those frustrating "username not found" moments when someone forgets their exact capitalization. [Username authentication details](/authenticate/authentication-methods/username-authentication/)
What happens if a user changes their password when using both email and username authentication in Kinde? Both methods share the same password! If someone can sign in with both their email and username, changing the password for one affects both. It keeps things simple for users (one password to remember) and prevents the confusion of having different passwords for the same account. We think this makes way more sense than forcing people to juggle multiple credentials. [Username authentication configuration](/authenticate/authentication-methods/username-authentication/)
## Device Authorization Flow
When should I use Kinde's device authorization flow instead of regular authentication? Device authorization flow is perfect for situations where typing is a nightmare - think smart TVs, gaming consoles, IoT devices, or anything without a proper keyboard. Instead of watching users struggle with TV remote controls to spell out "MyComplexPassword123!", the device shows them a simple code to enter on their phone or laptop where typing doesn't suck. It's basically Netflix's approach: the TV shows a code, you enter it on your phone, boom - you're authenticated. Much better user experience, and way more secure. [Device Authorization Flow](/authenticate/device-authorization-flow/overview/).
How does Kinde's device authorization flow work, and what should I tell my users? Here's the flow: your device (let's say a smart TV app) requests a device code from Kinde, then shows users a simple code and a URL like "Go to `yourapp.com/device` and enter code: ABC123". Users grab their phone, visit that URL, sign in normally (with all their usual auth methods available), enter the code, and authorize the device. Meanwhile, your TV app is polling our servers asking "Are they done yet? Are they done yet?" until we give it the green light with tokens. The whole thing happens in parallel - no hanging around waiting. [Device Authorization Flow](/authenticate/device-authorization-flow/overview/)
What are the security benefits of Kinde's device authorization flow? It keeps credentials off devices you don't control, which is huge for security. Users never enter their actual passwords on the TV, CLI, or IoT device - they authenticate on their trusted phone or laptop instead. Plus, they get access to all their usual security features like MFA, social sign-in, and password managers. The codes expire quickly, we rate-limit the polling to prevent abuse, and users always see a proper consent screen before authorizing access. It's basically taking the most secure part of OAuth (browser-based auth) and making it work for devices that can't do browsers. [About authentication methods](/authenticate/about-auth/authentication-methods/)
How do I handle Kinde device authorization flow errors and edge cases? The main errors you'll see are `authorization_pending` (user hasn't finished yet - keep polling), `slow_down` (you're polling too aggressively - back off), and `expired_token` (codes expired - start over). Handle these gracefully in your app rather than crashing. Users might also get confused about which device they're supposed to use for what, so make your instructions crystal clear. And remember, some users will start the process but never finish it - that's normal, just clean up expired sessions. [OAuth token validation and errors](/build/tokens/token-validation-errors/)
What's the best UX for presenting Kinde device codes to users? Keep it simple and obvious. Show the code clearly (big, readable font), include the full URL they need to visit, and consider showing both a QR code and the manual entry option. Don't overwhelm them with too much text - just "Go to `yourapp.com/device` on your phone and enter: ABC123" works perfectly. If you can, show some kind of progress indicator so they know the app is waiting for them to complete the process. And please, test this with actual humans - what seems obvious to developers often isn't to regular users.
## Custom configurations & user experience
What do I need to set up Kinde phone authentication for my users? You'll need a paid Twilio business account - this isn't something we can handle for free because SMS costs money. Before you dive in, check if you need 10DLC registration (10 Digit Long Code) for your region - it's required in some places for business messaging. Read up on Twilio's A2P (Application to Person) messaging guidelines too. Once you've got that sorted, plug your Twilio details into Kinde, pick between using their messaging service (better for global apps) or a specific phone number, and set your default country. [Set up phone authentication](/authenticate/authentication-methods/phone-authentication/)
Can I customize the SMS message that Kinde users receive? Nope, and here's why - we use a standard format that meets security best practices and works across different languages. The message looks like: "123456 is your one-time code to sign in to [xxxx@login.xxx.au](mailto:xxxx@login.xxx.au) #123456". That weird duplication at the end? It's for security. We know it might not match your brand perfectly, but it keeps everyone safe and compliant. [Phone authentication details](/authenticate/authentication-methods/phone-authentication/)
How can I create a more seamless Kinde sign-up experience for invited users? Use the `login_hint` parameter to pre-fill email fields when you know who's trying to sign in - it's like having their name already on the guest list. You can also create a unified experience where users don't have to choose between "sign up" or "sign in" (because honestly, who remembers if they've been here before?). Skip asking for first and last names if you want to keep things really minimal. Every little bit of friction you remove makes a difference. [Pre-populate user identity](/authenticate/custom-configurations/prepopulate-identity-sign-in/) | [Manage authentication experience](/authenticate/custom-configurations/authentication-experience/)
What's the best way to handle profile pictures and user data with Kinde? We automatically grab profile pictures from email providers like Google and use Gravatar as backup when pictures are missing. If you'd rather handle profile pics your own way or just hate blank avatars, you can switch off the Gravatar fallback. Fair warning: Apple is pretty stingy with user data - they don't pass through avatars or much profile info, so don't expect much there. [Authentication experience customization](/authenticate/custom-configurations/authentication-experience/)
How can I pass additional parameters to identity providers through Kinde? Upstream parameters let you send extra data during authentication - either the same value every time (static) or something unique per user (dynamic). Common use case: passing `login_hint` to pre-fill sign-in forms or enabling those handy account switchers you see on Google. Each provider supports different parameters (check their docs), and you can even rename parameters using aliases if your IdP is picky about naming. [Pass parameters to identity providers](/authenticate/auth-guides/pass-params-idp/)
## Developer questions
Why does Kinde authentication state get lost when users refresh the page in single-page apps? We store tokens in memory for security - it protects against both CSRF and XSS attacks, which is definitely worth the trade-off. But yeah, it means page refreshes wipe the tokens. The best fix? Use our Custom Domains feature, which lets us set secure httpOnly cookies on your domain. For local development, there's an escape hatch called `is_dangerously_use_local_storage`, but seriously, don't use that in production - the name isn't kidding about the danger part. [JavaScript SDK guide](m/developer-tools/sdks/frontend/javascript-sdk/) | [React SDK guide](/developer-tools/sdks/frontend/react-sdk/)
How do I implement Kinde authentication in a React application without losing user state? Wrap your app in the KindeProvider - it's your new best friend for managing auth state. Use hooks like `useKindeAuth()` to check if someone's signed in, and always check the `isLoading` state before making decisions (nobody likes flickering UI). For production, definitely set up custom domains so you can use secure cookies. Handle your post-auth redirects properly, and your users will never know how complex this stuff really is under the hood. [React SDK implementation](/developer-tools/sdks/frontend/react-sdk/)
What's the best approach for handling Kinde authentication callbacks in different frameworks? Each framework has its own quirks. Next.js App Router wants `app/api/auth/[kindeAuth]/route.js`, Pages Router prefers `pages/api/auth/[...kindeAuth].js`, and vanilla JavaScript means you're handling the OAuth dance yourself. Always make sure your callback URLs match what you've configured in Kinde (case-sensitive, protocol-specific). Use our SDK callback handlers instead of rolling your own - we've already dealt with all the edge cases. [Next.js App Router SDK](/developer-tools/sdks/backend/nextjs-sdk/) | [Using Kinde without SDK](/developer-tools/about/using-kinde-without-an-sdk/)
How can I protect API endpoints and validate Kinde tokens properly? Use our backend SDKs or validate JWT tokens manually - either works, but the SDKs handle the fiddly bits for you. The `getToken()` method gives you bearer tokens for API calls. On your backend, always check the token's audience claim matches your API and verify it hasn't expired. And please, never put client secrets in frontend code - that's like leaving your house key under the doormat. [TypeScript SDK guide](/developer-tools/sdks/backend/typescript-sdk/)
## Troubleshooting & common issues
How do I use Kinde to help my users who forgot their passwords? Users can hit "forgot password" on the sign-in screen and we'll send them a one-time code via email to reset it. As an admin, you can also trigger password resets through the Kinde dashboard or API (as long as they have a verified email). There's also the option to set a temporary password for them, but you'll need to send it through your own channels - we won't email passwords directly because that's not secure. [Password reset procedures](/authenticate/authentication-methods/password-authentication/)
How should I help users who aren't receiving Kinde SMS auth codes? Start with the basics - did they enter their phone number correctly with the right country code? Do they have cell reception? Are they in a country where SMS might be restricted? Then check your end - is your Twilio account funded and configured properly? SMS delivery can be finicky, especially internationally, so having backup contact methods is always smart. [Phone authentication setup](/authenticate/authentication-methods/phone-authentication/)
How should I help users who aren't receiving Kinde auth codes via email? Start with the basics - could the email have been caught in their spam or been caught by their organization's firewall and have been added to a supression list? Have them check this first. If you have [custom SMTP email delivery](/integrate/third-party-tools/kinde-resend-custom-smtp/) set up, you should be able to check logs from the delivery provider. If you rely on Kinde to deliver emails, check the same basic things with the recipient and ask them to try again. If you need to, contact the Kinde support team to check our logs to see if there was an email disruption. [Phone authentication setup](/authenticate/authentication-methods/phone-authentication/)
If I want to change which providers can be used for auth in Kinde, how do I support my customers? If users were relying on a social or enterprise connection that got removed or changed, they're stuck until you fix it. Before deleting any connection, make sure nobody's using it for auth. If you need to switch providers, set up the new one first, then help users transition by linking their accounts or setting up alternative auth methods. Always have a backup plan. [Manage social connections](/authenticate/social-sign-in/add-social-sign-in/)
Why are my Kinde authentication redirects failing? Nine times out of ten, it's a URL mismatch. Your callback URLs in Kinde need to match exactly what's in your app code and any social provider configs - we're talking case-sensitive, protocol-specific matching here. If you're using custom domains, double-check that your DNS records are set up correctly and SSL certificates are active. Also remember that custom domain tokens and Kinde subdomain tokens don't play nice together - pick one and stick with it. [Custom domain setup](/build/domains/pointing-your-domain/)
How do I debug Kinde OAuth 2.0 authentication errors? The error names are pretty self-explanatory once you know what to look for. `invalid_client` usually means wrong client ID or secret, `invalid_grant` means your authorization code expired (they only last a short time), and `invalid_scope` means you're asking for something we don't support. Check your credentials first, make sure you're exchanging codes quickly, and verify your requested scopes are valid. Give users helpful error messages instead of raw OAuth codes - nobody wants to see "invalid_grant" when they're just trying to sign in. [OAuth 2.0 validation and errors](/build/tokens/token-validation-errors/)
What should I check in Kinde when users report authentication isn't working on mobile? Mobile auth has its own special challenges. For React Native, make sure your deep linking is configured properly with the right URL schemes for both iOS and Android. Check that your redirect URLs use the correct custom scheme format like `myapp://your_kinde_domain.kinde.com/kinde_callback`. And here's a fun fact: Google doesn't support auth in webview, so make sure you're using proper browser-based flows. If your users are not receiving verification codes and you have Twilio set up, you can check the Twilio logs to help you troubleshoot. [React Native SDK](/developer-tools/sdks/native/react-native-sdk/) and [Set up phone auth with Twilio](/authenticate/authentication-methods/phone-authentication/)
How do I handle Kinde authentication state persistence across different environments? For production, custom domains are your friend - they enable secure cookie storage that survives page refreshes. For local development, you can use the local storage escape hatch (just remember to remove it before going live). On your backend, implement proper session management using encrypted cookies or shared cache systems if you're running multiple servers. The right approach depends on your architecture, but security should always come first. [TypeScript SDK session management](/developer-tools/sdks/backend/typescript-sdk/)
## Best practices & security
What security considerations should I communicate to my customers about Kinde authentication choices? Be honest about the security trade-offs without scaring people away. Passwordless is genuinely more secure than passwords, MFA adds real protection (not just security theater), and social sign-in can be both convenient and secure when done right. If you're offering password auth, nudge users toward password managers - most people's password habits are... not great. And here's something most auth providers won't tell you: we store passwords as encrypted hashes that literally cannot be deciphered, so even we can't see what users set. [Password authentication security](/authenticate/authentication-methods/password-authentication/)
How do I ensure my Kinde authentication setup scales with business growth? Start simple and add complexity as you need it - don't over-engineer from day one. Begin with email auth, then layer in social sign-in, MFA, and enterprise connections as your customer base grows. Use organizations to handle multi-tenant setups where each customer needs their own user management. Set up your foundation at the environment level, then customize per organization when customers have specific needs. And seriously, implement custom domains early if you can - it makes everything smoother later. [Kinde for different business models](/build/set-up-options/kinde-business-model/)
What's the recommended approach for handling user migration from other auth providers to Kinde? Set up your auth methods in Kinde first, then export and import user data via CSV or JSON. If you import passwords too, your users won't notice anything changed - which is exactly what you want. If you're switching auth methods (like going passwordless), give users a heads up about what's changing. Test everything in a sandbox environment first, and keep an eye out for edge cases like users who change their passwords during the migration window. [Switch to Kinde migration guide](/get-started/switch-to-kinde/switch-to-kinde-for-user-authentication/)
## Advanced integration
How do I implement Kinde custom authentication pages while maintaining security? You can build your own sign-up and sign-in pages to match your brand perfectly, but we'll still handle the security-critical stuff like verification and MFA. Use connection IDs and login hints in your auth URLs to route users directly to specific authentication methods. Think of it as having your cake and eating it too - custom experience with bulletproof security. Just remember that some screens (password entry, code verification) stay with us because that's where the security magic happens. [Custom authentication pages](/authenticate/custom-configurations/custom-authentication-pages/)
What's the best way to handle cross-subdomain authentication in Kinde, for complex applications? Custom domains and proper cookie configuration are your best friends here. Set cookies to the root domain instead of subdomains so they're accessible across your entire ecosystem. For PHP apps, we've got helper functions to make this easy. Test everything thoroughly across all your subdomains - nothing's more embarrassing than users getting stuck switching between `app.yoursite.com` and `dashboard.yoursite.com`. [PHP SDK domain configuration](/developer-tools/sdks/backend/php-sdk/)
How should I configure Kinde authentication for different business models (B2C vs B2B)? B2C is straightforward - configure everything at the business level with easy social sign-in and email auth. B2B gets more interesting because you're serving multiple companies, each with their own needs. Use organizations to create separate tenant management, set up enterprise connections for business customers who need SAML or Entra ID, and keep simpler social auth for any consumer-facing parts of your platform. It's all about matching Kinde auth options to what your customer actually needs. [Business model configuration](/build/set-up-options/kinde-business-model/)
+ +# Authenticate - About auth - User communication in Kinde + +> Learn about how Kinde communicates with users through emails and SMS for authentication purposes. + +user communication, email, SMS, OTP, verification, Twilio, webhooks +authenticate + +Kinde only sends emails or texts to users as part of the authentication experience, for example to send one-time passwords or to verify user identity for self-sign-up. We’ve kept communication features to a bare minimum for authentication, so that we do not send unwanted or unsolicited communication to users, on behalf of your business. ## Emails sent from Kinde The following emails are sent from no-reply@kinde.com. - Invitations to join your business on Kinde when you manually add a new team member - Export data warning emails to ensure only authorized people can get user data out of your business. - (Unless you enter custom email sender details) verification and authentication emails for sign-up, sign-in, multi-factor authentication, and password reset. To configure authentication emails to come from your own email provider, see [Customize email sender](/get-started/connect/customize-email-sender/). ## Kinde does not send emails in these situations - Invitations to users if you add them via API - Invitations to users if you add them in bulk via import - Emails to team members about your Kinde subscription or admin activity If you want certain user events in Kinde to trigger an email, you can set this up with [webhooks](/integrate/webhooks/add-manage-webhooks/). ## Communication when users are added in bulk Our features for adding users in bulk (such as via API or import) are designed with a smooth migration experience in mind. Rather than send confusing emails to existing user bases, we enable a silent transfer of the authentication experience, between your previous supplier and Kinde. That’s why we don’t send emails when users are added to Kinde this way. ## SMS communication for phone authentication Kinde supports [phone authentication](/authenticate/authentication-methods/phone-authentication/) as a primary and secondary authentication factor. To use phone authentication, you need to have a [Twilio](https://www.twilio.com/en-us) account and configure the account details in Kinde. Twilio is a third-party provider who offer bulk messaging services. When a user authenticates via phone number, an SMS containing a one-time passcode is sent. The SMS is in a specific format that cannot be edited. ```text 123456 is your one-time code to sign in to [kinde business URL] #123456 ``` Kinde does not communicate anything else to users via SMS. + +# Authenticate - Auth guides - Guide to enterprise auth and user identities + +> Understanding why Kinde enforces one enterprise identity per user for security, account integrity, and simplified tenant management. + +enterprise identity, SSO, identity provider, IdP, security, account integrity, tenant management +authenticate + +At Kinde, each user can only have one enterprise identity provider (IdP) connection as part of their user profile. This is because we want to keep things simple, secure, and reliable. We get asked about this regularly, so this document explains our reasoning from a security and architectural perspective. ## What is an enterprise connection? An enterprise connection allows users to sign in to your product using their organization’s identity provider — such as Okta, Azure AD, or Google Workspace. This enables Single Sign-On (SSO), centralized user management, and improved security for enterprise customers. ## Why only one identity per user? Many customer identity platforms, including Kinde, enforce a one-to-one relationship between a user and an enterprise connection. Here’s why: ### 1. Prevents identity conflicts If a user could sign in through multiple enterprise providers, it becomes difficult to determine whether those identities belong to the same person. This can result in: - Duplicate accounts for the same user - Conflicting user attributes (email, name, roles, etc.) - Confusion around permissions and organization membership Restricting to a single enterprise connection ensures a consistent and predictable identity model. ### 2. Security and account Integrity Allowing multiple enterprise connections introduces significant security risks: - **Risk of account hijacking:** If a user can link multiple IdPs, and identity claims like email or subject ID (`sub`) overlap or are not verified consistently, it becomes possible for unauthorized users to gain access to another user’s account. - **Inconsistent identity claims:** Different IdPs use different formats and identifiers. One provider may use an email address, another a unique internal ID. Reconciling these automatically increases the risk of incorrect mappings and privilege escalation. - **Reduced auditability:** Security audits and access logs rely on a single, traceable identity. If a user can authenticate through multiple IdPs, it becomes harder to guarantee that all actions are traceable to a single, verified identity. - **Clear accountability:** With one connection per user, the responsibility for identity management, password resets, session revocation, and breach response remains clearly with the source identity provider. ### 3. Simplified tenant and access management In multi-tenant applications, each enterprise typically has its own workspace or organization. Supporting one IdP per user: - Keeps tenant boundaries clean - Prevents role or permission leakage between organizations - Simplifies access control logic ## What if someone needs access to multiple organizations? We support users belonging to multiple organizations within Kinde. In edge cases (such as contractors working across companies) we recommend adding [enterprise connections at the organization level](/authenticate/enterprise-connections/enterprise-connections-b2b/). This means the user signs in directly to the relevant organization, with no confusion about where to be routed. This feature is only available on the Kinde Scale plan. If you are not on the relevant plan, other ways to handle this include: - Use separate emails for each organization - Use different auth methods per organization ## Built for security, designed for clarity This choice to allow only one enterprise identity per user aligns with industry best practices and helps keep your users, data, and systems secure. By enforcing this, Kinde provides a stable and trusted identity layer you can build on with confidence. If you have any questions about more advanced SSO or identity configurations, [contact our team](https://kinde.com/contact). We’re happy to help. + +# Authenticate - Auth guides - Mixed auth set up for B2B and B2C + +> Complete guide to setting up unified authentication for mixed B2B and B2C businesses using Kinde Scale plan features. + +B2B, B2C, mixed authentication, enterprise connections, SAML, organizations, home realm discovery +authenticate + +If you have an app or site that supports a mix of business customers and direct customers, this guide shows you how to set up authentication in Kinde to meet both these needs. For example, say you run a finance business and you have separate sign-ins for accounting business partners and direct customers. Accounting businesses sign in with an enterprise identity, e.g. SAML and direct customers sign in with email and an OTP. This topic explains how to create a simple, unified experience for both groups. ## You’ll need the Kinde Scale plan To set up authentication for a mixed B2B and B2C business that includes multiple enterprise connections, you need to be on the [Kinde Scale plan](https://kinde.com/pricing/). This is the only Kinde plan that gives you access to the features you need: - Multiple enterprise connections (e.g. SAML) - Advanced organizations - for managing users and access for business customers You get 5 enterprise connections and 5 advanced organizations included with Kinde Scale. You can add more, but costs apply. ## How to build a unified sign-in experience A unified experience is where everyone signs in through the same sign in screen, and they are routed to the relevant workflow for authentication. ![unified sign in](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/a14aa42c-3c66-45de-dc80-ee7c9df41b00/public) This simplifies the sign in experience for all your users, including your enterprise connections. ### Example of a unified authentication experience This is what happens behind the scenes with the auth setup. ![image.png](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/ff106642-c42f-44cf-4a89-84406a717000/public) ### Step 1: Set up auth for your B2C users In this scenario, your direct customers will sign in with email and a one-time-passcode (OTP). To set this up: 1. [Enable email + code authentication in your business.](/authenticate/authentication-methods/passwordless-authentication/) 2. [Set email + code as the sign in method in your default organization.](/authenticate/manage-authentication/organization-auth-experience/) 3. (Optional) [Set an organization policy to allow users to sign up to the default org using an email address](/build/organizations/allow-user-signup-org/). ### Step 2: Set up auth for your B2B users Authentication for business customers can be more complex, with additional security considerations and set up time involved. For example, a partner business may require employees to only access your web app using their business email and for authentication to be centralised with their own identity provider via SAML. Let’s go through the process for setting up 5 SAML enterprise connections for 5 different business customers. 1. [Add 5 separate enterprise connections to Kinde](/authenticate/enterprise-connections/about-enterprise-connections/). E.g. EC1, EC2, EC3, and so on. 1. Configure each connection with the domain information, including email domains in the [home realm discovery](/authenticate/enterprise-connections/about-enterprise-connections/#home-realm-discovery) field. You may need to ask the customer’s IT team for this information. 2. (Recommended) Switch on the **Create user on sign up** option to [enable JIT provisioning](/authenticate/enterprise-connections/provision-users-enterprise/). 2. [Create 5 organizations](/build/organizations/add-and-manage-organizations/), one for each business customer (and connection), and select only [the relevant enterprise connection for each organization](/authenticate/manage-authentication/organization-auth-experience/). For example: | For this org… | Switch on this auth connection… | | -------------- | ------------------------------- | | Organization 1 | EC1 (domain x home realm) | | Organization 2 | EC2 (domain y home realm) | | Organization 3 | EC3 (domain a home realm) | | Organization 4 | EC4 (domain b home realm) | | Organization 5 | EC5 (domain c home realm) | 3. In each organization: 1. Go to **Policies** and add the relevant domain to the **Allowed domains** field. 2. Select **Auto-add users from allowed domains**. This activates JIT provisioning for users signing up from this domain. 3. Select **Save**. With home realm discovery and allowed domains set, when a user enters an email that matches the domain name they will be routed through that enterprise connection. There is no need for them to self-select which connection they belong to. ### Step 3: Enable authentication for your application To achieve the above scenario, all the supported sign-in methods need to be switched on in your application. For example, switch on Email + code, EC1, EC2, EC3, EC4, and EC5. ![Auth options to switch on in Kinde](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/cf3a393d-b977-4de3-2bd1-dae72ec93f00/public) ## Optimize your auth flow This unified model of authentication can be extended to 10’s or 100’s of organizations, all while maintaining the same sign in screen. Other situations you can cater for include: - [Adding MFA for an organization's users](/authenticate/multi-factor-auth/mfa-per-org/) - Adding other [enterprise connections](/authenticate/enterprise-connections/about-enterprise-connections/) (e.g. [Google Workspace](/authenticate/enterprise-connections/custom-saml-google-workspace/) or [Microsoft Entra ID](/authenticate/enterprise-connections/azure/)) - [Auto-assigning user roles](/manage-users/roles-and-permissions/default-user-roles/) + +# Authenticate - Auth guides - Pass parameters to identity providers + +> Learn how to pass static and dynamic parameters to identity providers during authentication for improved user experience. + +upstream params, identity provider, OAuth 2.0, SAML, login_hint, prompt, account switcher +authenticate + +You can pass provider-specific parameters to an Identity Provider (IdP) during authentication. These are also known as 'upstream params'. The values your pass can either be static per connection or dynamic per user. There's a number of reason why you might want to use upstream params: - to create a smoother sign in experience - by passing the email through - to offer an account switcher (such as the Google account switcher) during sign in Upstream params are available for OAuth 2.0 connections, e.g. [social connections](/authenticate/social-sign-in/add-social-sign-in/), [Entra ID OAuth 2.0 enterprise connection](/authenticate/enterprise-connections/azure/), and as part of [advanced configurations](/authenticate/enterprise-connections/advanced-saml-configurations/) in SAML connections. ## Limitations Every identity provider has their own set of supported parameters and values, so you'll need to check their documentation to determine which URL parameters are supported. ## Static parameters Static parameters can be useful when you have specific values you always want to pass on to the IDP. These are set in the connecction configuration screen. ![Screen shot of google connection screen and upstream params field](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/3fa86bd8-9005-4022-7118-fc93ce4f4a00/public) The Upstream parameter field accepts JSON and the structure is as follows: ```json { "": { "value": "" } } ``` Replace `` with the name of the parameter you wish to pass upstream to the IDP. Replace `` with the value of the parameter you wish to pass upstream. ### Example: Force the google account selector to display on sign in If you want Google to always show the account selector even if the user is already logged in with a Google account, pass the `prompt=select_account` parameter from Kinde. This is how that would look: ```json { "prompt": { "value": "select_account" } } ``` Now, when your user clicks on the Google button and Kinde creates the URL to redirect to Google, it will append`&prompt=select_account`. ## Dynamic parameters Dynamic parameters cover the case where you don't know the value of the parameter ahead of time, and it needs to be populated on the fly during the auth flow. For example, if you need to pass on a parameter that was provided to Kinde in the auth URL. This is the structure. ```json { "": { "alias": "" } } ``` The `alias` keyword tells Kinde which parameter from your auth url to use, and the value to pass upstream to the IDP. Here is an example where we provide `login_hint` as part of the auth URL, where the email [`&login_hint=hello@example.com`](mailto:&login_hint=hello@example.com) is included on the URL. ```html https://.kinde.com/oauth2/auth ?response_type=code &client_id= &redirect_uri= &scope=openid%20profile%20email &state=abc &login_hint=hello@example.com ``` In this case both Kinde and the IDP use the parameter name `login_hint` so the configuration is the same on both sides: Add this to the connection configuration: } } ```` In this case we are saying pass the `login_hint` parameter upstream to the IDP with the value Kinde received in the `login_hint` auth url param. So `&login_hint=hello@example.com` would be passed on to the provider. Where the `alias` becomes especially powerful is when you want to re-map a parameter name to match the one an IDP expects. For example, let’s say that our IDP expects `username` instead of `login_hint` for the same value, in this case our JSON would look like this: ```json { "username": { "alias": "login_hint" } } ```` In this case we are saying pass the `username` parameter upstream to the IDP with the value Kinde received in the `login_hint` auth url param. We remap the email value from `login_hint` to `username` and the parameter `&username=hello@example.com` would be passed on to the IDP. ## Kinde-provided aliases When an email address is populated during the auth flow, we make this available via the `login_hint` alias. You might use this if you are using Home realm discovery with an Entra ID OAuth2.0 connection, and you want to pass the URL that the user entered on Kinde as the `login_hint`, upstream to Entra, to prevent the user having to enter their email twice. If the user enters `hello@example.com` in the Kinde email field with the following configuration active, we set the `login_hint` parameter to `hello@example.com` via the Kinde provided alias. ```json { "login_hint": { "alias": "login_hint" } } ``` ## Multiple parameters You can send multple parameters this way and mix-and-match between dynamic and static in the same configuration. For example if the user entered `hello@example.com` and the following was configured: ```json { "prompt": { "value": "login" }, "username": { "alias": "login_hint" } } ``` This would result in `&prompt=login&username=hello@example.com` ## Supported aliases The values which can be used as an `alias` are: - `prompt` - `login_hint` If you need other aliases added, let us know via a [feedback form](https://updates.kinde.com/). + +# Authenticate - Authentication methods - About email authentication + +> Comprehensive overview of email authentication methods including verification, account linking, and customization options. + +email authentication, email verification, account linking, Gravatar, login_hint, profile pictures +authenticate + +The most common application signup and sign in method for users is email. Kinde supports a number of approaches to email authentication. You can set up email authentication so that: - users sign up with their preferred email, but don’t need a password - users sign up with their preferred email and set their own password - only [users you invite](/authenticate/custom-configurations/disable-sign-up/) can sign up and sign in using email ## Verification code email from Kinde to your users To verify a user, Kinde sends a verification code to the email they sign up with. If you’ve also enabled passwordless authentication, this is also where the one time code is sent each time they sign in. The verification email has limited customizations. - You can add your own logo - You can change the sender name, but you cannot change the sender email address - You cannot edit the email content - Email content references your [business] name in Kinde. For example: ## All email sign-ups must verify their email address If your authentication method requires users to sign up with an email, they will be prompted to verify their email address using a one time code. Even if they subsequently sign on using their own password, the user must verify their email the first time by entering a one time code. If a user signs up via a social provider that does not require an email (such as Twitter or Apple), or via another OAuth2 protocol that does not pass the email to us, they will be prompted to enter an email address so their account can be verified. ## Kinde automatically links accounts with verified emails Unlike some other authentication providers, Kinde automatically matches accounts on sign up by matching verified email addresses. This means that if a user signs up with Google the first time, and they come back and sign up again with Slack, and the same email is detected (and we know they are both verified), then the accounts get linked. This reduces duplication and creates a better experience for users. ## Pre-populate the email field on sign in If you only allow users that you invite to sign up or sign in to your app, you can pre-populate the email field in the sign in window. This can only be achieved by including the `login_hint` parameter as part of the `login` method. It cannot be set in the Kinde UI. When your project knows which user it is trying to authenticate, it can provide their email in this parameter as a hint to Kinde. Passing this hint pre-fills the email box on the sign-up and sign-in screens. ## How profile pictures are passed to Kinde Typically, Kinde receives user profile pictures via the email provider, e.g. Google. If no picture is attached to a profile, Kinde sets the picture to use a Gravatar URL instead. See also [Switch off Gravatar fallback](/authenticate/custom-configurations/authentication-experience/#switch-off-gravatar-fallback-for-profile-pictures). + +# Authenticate - Authentication methods - Email deliverability in Kinde + +> Guide to email deliverability best practices including custom email senders, authentication records, and troubleshooting delivery issues. + +email deliverability, SMTP, SPF, DMARC, DKIM, email authentication, spam prevention +authenticate + +Kinde encourages users to configure their own email sender, so that verification and other emails are sent form your own business, and not Kinde. When emails are sent via Kinde, we support the email routing, and are proactive about monitoring verification email deliverability and speed. This topic describes email delivery via Kinde, deliverability factors, and some common reasons why delivery can fail. ## Manage your own email sender By default, when you first start using Kinde, all emails are sent from @kinde.com. But you can set up your environments to use your own email, so users receive authentication emails from @yourbusiness.com. You’ll want to configure this before your production environment goes live. All you need is to add SMTP details in Kinde settings. See [Customize email sender](/get-started/connect/customize-email-sender/). ## Emails sent from Kinde Even if you enter custom sender details, these emails will still be sent from Kinde: - Invitation to join business team - triggered by manual or API addition of team member - Warnings and notifications of data export ## Deliverability factors Email delivery is dependent on a number of factors. ### IP address reputation and blocklists Email providers check against a pool of IP addresses and domain blocklists to help protect against bad actors. They constantly monitor to make sure IP addresses are not on any of these lists. If you experience issues, check that your domain doesn't exist on any of these lists. ### Domain name reputation Every domain name (i.e. `example.com`, `kinde.com`, etc.) has its own reputation score. Newer domains do not have a high score, and this may impact deliverability. ### Setup a real email address Email providers will check if there's an actual mailbox behind the "from address" of an email. Make sure when you set your custom email sender, that you use a real email address such as `notifications@yourbusiness.com`. ### Email content Kinde email content is optimized to (as far as we can) ensure our communications don’t get identified by providers as spam. Maintaining deliverability is one of the reasons we have limited the ability to edit email content. ### SPF, DMARC, and DKIM for email authentication SPF (Sender Policy Framework), DMARC (Domain-based Message Authentication, Reporting, and Conformance), and DKIM (DomainKeys Identified Mail) are email authentication methods used to combat email spoofing, phishing, and other forms of email fraud. These records add a digital signature to every outgoing message, which allows your provider to verify that emails were actually sent from you. Almost all email providers look for these to be set as a strong signal of legitimacy. ### Strengthen email authentication with your provider You and your email provider are ultimately responsible for ensuring the right level security and risk management for email authentication. Because Kinde allows you to use any provider you like, check their documentation to find out if their policies and approach meet your needs. ## Provider-related issues Despite all we can do, verification emails still occasionally end up in spam or quarantined. The cases below are specific, but might help you troubleshoot is they arise. ### Gmail Delivery addresses that are part of Google Workspace can sometimes be delayed by about 4 minutes, due to pre-delivery message scanning. It can help to sign up for Gmail's postmaster tools, to help troubleshoot issues. ### Microsoft (Hotmail / Outlook / Office365) Microsoft Defender's aggressive anti-spam filters sometimes stop verification emails reaching certain Outlook inboxes. Then the email is placed in quarantine and the administrator has to restore it, for it to be delivered. With Kinde, this should be rare, as we only send OTPs and not magic links. Access Outlook Sender Support and check you are following recommendations. + +# Authenticate - Authentication methods - Password authentication + +> Complete guide to password authentication in Kinde including security features, password strength requirements, and reset options. + +password authentication, password strength, password reset, security, hash encryption, MFA +authenticate + +Password authentication is where an end user supplies and maintains their own password to access your app or project. Depending on your authentication needs and security requirements, you might be okay to allow users to authenticate with a password. However, we recommend using a more secure method, such as through one-time-passwords, or by adding [multi-factor authentication](/authenticate/multi-factor-auth/about-multi-factor-authentication/) to the sign in experience. ## Passwords and identity verification To reset a password for a user, or allow them to reset their own password, they need to have a [verified contact identit](/authenticate/about-auth/identity-and-verification/)y such as an email in their Kinde profile. You’ll need this to securely set a temporary password or to trigger a password reset for a user. ## Password visibility and encryption The way Kinde is built ensures that user passwords can only be stored as hash-encrypted strings, meaning they are not visible and cannot be deciphered or accessed to be exploited. Neither you in your business or Kinde can see any passwords that a user has set. ## Password strength Kinde supports the following password requirements: - 8 character minimum - Blocking of 1,000,000 most common passwords - 5 incorrect attempts locks account out for 5 minutes - No complexity requirements or character limitations - combined with allowing long passwords, this provides better security and ease of use. For example, it’s harder for a computer to crack `FiremanSoccerPoodleLemon` than `FireSoc!22`, and also easier for a human to remember. If using passwords for authentication, we do recommend adding multi-factor authentication as a requirement or option, for added security. ## Options for resetting a password There are several ways to reset a user’s password. ### The user can select ‘forgot password’ User’s can trigger a password reset by selecting ‘forgot password’ when they attempt to sign in. When they do this, they will be sent a one-time passcode via email. When they enter the code, they will be prompted to reset their password. ### Force a password reset via Kinde or API You can trigger a password reset via the Kinde admin or via API. This is only suitable if you have an email for the user, as they will be sent a one-time passcode when they try to sign in next. They must enter the code to reset their password. See [Reset a user’s password](/manage-users/access-control/reset-user-password/). ### Issue a temporary password You can set a single-use password for new or existing users via the Kinde admin or via the Kinde Management API. Once you set the password, you need to communicate it to the user via your own chosen method - it cannot be sent from Kinde. The user enters the temporary password to sign up or sign in, then they set their own password. See [Set a temporary password](/manage-users/access-control/set-temporary-password/). ## Enable password authentication across apps 1. Go to **Settings > Authentication**. 2. In the **Password** section, select **Configure** on the relevant password tile: **Email + password** or **Username**. A configuration window opens. 3. Scroll to the bottom and switch password authentication on for the apps you want. 4. Select **Save**. ## Enable password authentication for a single app 1. Go to **Settings > Applications**. 2. Select **Configure** on the relevant application tile. 3. Select **Authentication** in the menu. 4. Switch on the password options you want. 5. Select **Save**. + +# Authenticate - Authentication methods - Passwordless authentication + +> Guide to passwordless authentication using one-time passcodes (OTP) via email or phone, including setup and security considerations. + +passwordless authentication, OTP, one-time passcode, email code, phone code, security +authenticate + +Passwordless authentication is a type of authentication that does not require end-users to set or maintain passwords for access to an application. Instead, they authenticate using a one-time passcode (OTP). ## About one-time passcodes (OTPs) Kinde does not support magic links as a password alternative, instead, we prefer to use one-time passcodes (OTPs) as they are more secure, and require manual entry as opposed to a single click. For example, someone with access to your email could click a link to get instant access to an application, but they cannot use the code unless they have initiated the correct sign in flow and have your sign-in identity as well. If you receive the OTP via SMS, someone would need to have your device and unlock code, to access it. A OTP can be issued via email or phone, depending how you have set up authentication. It is also common to use OTPs as a factor in [multi-factor authentication](/authenticate/multi-factor-auth/about-multi-factor-authentication/). Passcodes issued from Kinde expire after 2 hours. ## Set up passwordless authentication 1. In Kinde, go to **Settings >** **Authentication**. 2. In the **Passwordless** section, select **Configure** on the relevant tile. 3. If you select the **Email + code** tile: 1. Select which applications will use this authentication method. 2. Select **Save**. 4. If you select the **Phone** tile: 1. Select which applications will use this authentication method. 2. Select **Save**. 5. If you select the **Username + code** tile: 1. Select which applications will use this authentication method. 2. Select **Save**. ## If a user does not receive a code It should not happen often, but occasionally users do not receive their passcode. Here's a few suggestions. - Tell the user to check their junk folder - some email providers, systems, and devices have security in place to prevent spam. An OTP from an unknown provider (like Kinde) might get accidentally treated as such. - Once or twice we have come across a domain provider who has added Kinde to a denylist and OTPs from us get rejected. You'll need to contact us so we can investigate and arrange allowlisting. This is a very rare cause of failed OTPs. ## Attack protection settings Kinde allows you to control the number of sign-in attempts a user gets, how long they get locked out after a failed sign-in attempt, etc. See [Attack protection](/build/set-up-options/attack-protection/). + +# Authenticate - Authentication methods - Set up phone or SMS authentication + +> Complete setup guide for phone/SMS authentication using Twilio, including configuration, MFA integration, and message formatting. + +phone authentication, SMS, Twilio, MFA, A2P messaging, 10DLC, verification code +authenticate + +You can allow users to use their phone as a primary method for authentication. This is a passwordless method, where the user is sent a verification code via SMS. SMS can also be included as a secondary factor if you have [multi-factor authentication](/authenticate/multi-factor-auth/about-multi-factor-authentication/) set up. ## (Existing phone auth Twilio users only) Switch on SMS for MFA 1. In Kinde, go to **Settings > Environment > SMS**. 2. Scroll to the bottom and switch on the **Use this service for SMS MFA** option. 3. Select **Save**. ## Benefits of using a third-party SMS service instead of Kinde - Gives you full control over the SMS delivery nuances, such as SenderID, country registrations, and detailed delivery metrics. - You can register dedicated short codes or sender IDs in countries that have strict SMS sending regulations like Ireland, NZ and Canada, which will greatly improve deliverability. - Access to delivery logs and other service quality details for troubleshooting. ## SMS provider requirements (Twilio) SMS authentication requires the services of a messaging provider, in this case, [Twilio](https://www.twilio.com/en-us). You need a [Twilio](https://www.twilio.com/en-us) business account to ensure messaging works for local and overseas phone numbers. Phone authentication interactions are also known as [A2P (Application to Person)](https://www.twilio.com/docs/glossary/what-a2p-sms-application-person-messaging) messaging. Before you implement A2P, check if you need to register your business for 10DLC (10 Digit Long Code) support to be able to send messages, as this is required in some locations. We also recommend you check [Twilio’s guidelines for setting up messaging](https://www.twilio.com/en-us/guidelines/sms), and carefully follow procedures for registration, and SMS policies for all relevant countries. ## What you need You’ll need the following details that are in the dashboard of your [Twilio account](https://www.twilio.com/en-us). - The SID of your Twilio account - The Auth Token for your Twilio account - Your Twilio phone number or the Messaging Service SID (if you set one up) ![Twilio account info](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/1da93a0a-9fd3-437f-5357-be90f3f3c200/public) Refer to the [Twilio documentation](https://www.twilio.com/docs/messaging/services/tutorials/send-messages-with-messaging-services) for assistance setting up. ## Configure phone SMS auth in Kinde After you set this up, you can use SMS for both phone authentication and SMS MFA. 1. In Kinde, go to **Settings > Environment > SMS**. 2. Select the **Default country** that you want to show on the authentication screen when users sign in. 3. Enter the Twilio details from your Twilio account (see above) in the relevant fields. ![twilio details](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/4c857ff9-ff87-44ea-a488-3e2b511caf00/public) 4. In the **SMS source** field, select either the **Use** **Messaging service** or **Use phone number**. Verification codes will be sent from whichever you choose. 5. Depending on your selection in the previous step, enter either the **Messaging service SID** or Twilio **Phone number** in the relevant field. ![Twilio config](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/749a80bc-d6b7-40b0-950a-650c7775b900/public) 6. Select if you want to use a fallback service if the provider service is interrupted. ![option to use kinde sms as fallback](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/9bdd2ef1-c308-4307-c84e-bc8ffdbfe200/public) 7. Select **Save**. ## Switch on phone authentication for an application After you have set up Twilio details, you’re ready to switch on phone or SMS auth for your applications. 1. Go to **Settings > Environment > Authentication**. 2. In the **Passwordless** section, select **Configure** on the **Phone** tile. 3. Switch on the auth method for the applications you want. 4. Select **Save**. ## Switch on SMS as a factor in MFA If MFA is required or optional for your users, you may want to use the Twilio service for SMS MFA. 1. Go to **Settings > Environment > Multi-factor auth**. 2. Under **Additional authentication methods**, switch on **SMS**. 3. Select **Save**. ## SMS message format You can’t customize the code message that user’s receive. We use a standard format as follows, to allow for easier translation. **Your verification code is [xxxxxx]** ## Connection ID When you configure phone authentication, you’ll see that a Connection ID is automatically assigned. If you’re building a [custom authentication experience](/authenticate/custom-configurations/custom-authentication-pages/), you’ll need the ID to trigger the phone authentication workflow. + +# Authenticate - Authentication methods - Select authentication options + +> Comprehensive guide to configuring all authentication methods in Kinde including email, phone, username, social, and enterprise connections. + +authentication setup, email auth, phone auth, username auth, social auth, enterprise auth, SAML, OAuth +authenticate + +Kinde supports many authentication options that let you control how users access your applications. You can set different authentication requirements for different applications, and also for different organizations (if you use [organizations](/build/organizations/add-and-manage-organizations/)). Set up all your required authentication methods at the Environment level first. ## Switch on **email authentication** 1. Go to **Settings > Environment > Authentication**. 2. Select **Configure** on the **Email** tile in either the **Passwordless** or **Password** section. 3. In the window that appears, switch the authentication option on or off for each application you have. Note that you **cannot** use passwordless and password authentication for the same app. 4. Select **Save**. ## Switch on phone authentication You can allow users to authenticate using their phone number as their sign in identity. For full details, see [Set up phone authentication](/authenticate/authentication-methods/phone-authentication/). 1. Go to **Settings > Environment > Authentication**. 2. In the **Passwordless** section, select **Configure** on the **Phone** tile. 3. In the window that appears, switch the authentication option on or off for each application you have. 4. Select **Save**. ## Switch on username + password authentication You can allow users to authenticate using a username as their sign-in identity. They will still need to provide an email on sign-up, but will be able to sign in with a username-password combination from then on. Learn more about using [usernames for auth](/authenticate/authentication-methods/username-authentication/). 1. Go to **Settings > Environment > Authentication**. 2. In the **Password** section, select **Configure** on the **Username** tile. 3. In the window that appears, switch the authentication option on or off for each application you have. 4. Select **Save**. ## Switch on username + passwordless authentication You can allow users to authenticate using a username as their sign-in identity. They will still need to provide an email on sign-up, but will be able to sign in with a username-OTP combination from then on. Learn more about using [passwordless auth](/authenticate/authentication-methods/passwordless-authentication/). 1. Go to **Settings > Environment > Authentication**. 2. In the **Passwordless** section, select **Configure** on the **Username + code** tile. 3. In the window that appears, switch the authentication option on or off for each application you have. 4. Select **Save**. ## Switch on **social authentication** 1. Go to **Settings > Environment > Authentication**. 2. In the **Social connections** section, select **Add connection**. 3. In the window that appears, select the social apps you want and then select **Save**. 4. You need to set up the connection to each social app you chose, see [Add social sign in](/authenticate/social-sign-in/add-social-sign-in/). ## Use enterprise or custom authentication Follow the instructions for the relevant authentication method. See: - [Microsoft Entra ID](/authenticate/enterprise-connections/azure/) (was Azure AD) - [SAML](/authenticate/enterprise-connections/custom-saml/) ## Add and manage social and enterprise connections via API Use [Kinde’s management API](/kinde-apis/management#tag/connections) to manage social and enterprise connections. You can view a list of connections, add a new connection, identify a connection, and update existing connections. + +# Authenticate - Authentication methods - SMS deliverability in Kinde + +> Guide to SMS deliverability including regional considerations, sender ID configuration, and country-specific delivery rates. + +SMS deliverability, Twilio, sender ID, regional delivery, 10DLC, A2P messaging +authenticate + +Kinde encourages customers to configure their own SMS sender, so that verification, country registrations, sender IDs, and deliverability metrics are controlled and managed by you. When SMS messages are sent via Kinde, we use our regional shared service provider and attempt delivery on a best-effort basis. As Kinde is a service provider, there are limitations when applying for dedicated short codes or sender IDs in countries with strict SMS-sending regulations. This topic describes SMS delivery via Kinde, deliverability factors, and some common reasons why delivery can fail. ## Manage your own SMS sender By default, when you first start using Kinde, all SMS messages are sent from Kinde's shared service provider. We recommend configuring your own SMS sender so that users receive authentication messages branded with your business. Configure this before your production environment goes live. Simply add your SMS details in Kinde settings. See [Set up phone or SMS authentication](/authenticate/authentication-methods/phone-authentication/) for step-by-step instructions. ## Deliverability factors when using Kinde's default SMS shared service provider Kinde provides no guarantees on SMS delivery and attempts delivery as best effort only. ### Countries with known good delivery due to Kinde involvement The following countries have been tested and are known to have good delivery due to Kinde registering with the respective regulatory bodies. - Australia (LONG CODE, SENDER ID) - Canada (LONG CODE) - Great Britain (SENDER ID) - Ireland (SENDER ID) - United States (TOLL FREE) ### Countries with known good delivery without Kinde involvement The following countries have known good delivery without Kinde registering with the respective regulatory bodies. - Generally the rest of the EU - South Africa ### Countries with known bad delivery The following countries have known bad delivery rates. - India - New Zealand - United Arab Emirates ## Sender ID Kinde has set up a shared Sender ID for all customers using the default SMS shared service provider. This cannot be changed. **Sender ID:** `KindeAuth` To brand the Sender ID to your business, you will need to configure your own SMS delivery provider. See [Set up phone or SMS authentication](/authenticate/authentication-methods/phone-authentication/). ## SMS content The content of the SMS is not editable due to strict one-time passcode requirements and industry best practices. An example of the SMS content is below. ``` 123456 is your one-time code to sign in to {Business Name} @business.kinde.com #123456 ``` + +# Authenticate - Authentication methods - Username authentication + +> Guide to username-based authentication including unique constraints, sign-up flow, and integration with password/passwordless methods. + +username authentication, unique usernames, case insensitive, sign-up flow, identity verification +authenticate + +Along with email and phone number, Kinde supports authentication where a username is the user’s sign-in identity. On sign-up or registration, the user will need to do a one-time validation of their identity via email - for security - but they can subsequently use a username to sign in. ## Usernames must be unique There are several ways usernames can be added to a user’s profile: - Manually in Kinde - Via API - Self-created by the user on registration - imported with user profiles Kinde treats usernames as case-insensitive. In other words, we ignore case. We do this because it eliminates the possibility of auth issues and fraud when two usernames are identical in every aspect except the case of one of their letters. We are happy to support users choosing an aesthetically pleasing username combination, like `RosyRose` or `BuilderBob`. We just don't also support separate identities for `rosYrosE` and `BUilderbob`. Regardless of how a username is added, it must be unique (in more than case). If a username already exists, an error will be returned. ## The sign-up flow For security reasons, Kinde doesn’t allow fully anonymous users. So when a user signs up, they will need to supply an email, in addition to a username. The email can then be used to verify their identity. The username can be supplied by you, or can be created by the user. ## The sign-in flow When a user signs in, they enter their username and proceed with a [password](/authenticate/authentication-methods/password-authentication/) or a [passwordless OTP](/authenticate/authentication-methods/passwordless-authentication/). Either way, it’s a quick process for sign in. ## Why an email is required In order to be sure that you are signing up a real person, you need to have a way of contacting new users to verify their identity. Without identity verification, the authentication experience you provide could be vulnerable to security threats, fraud, bots, etc. Once an email is verified, we add this email identity for the user. If the auth method is passwordless, this is where we send the OTPs. An email is also required for [password resets](/manage-users/access-control/reset-user-password/). ## Enable username authentication in Kinde 1. In Kinde, go to **Settings > Authentication**. 2. Select **Configure** on the **Username** (password) or the **username + code** (passwordless) tile. A configuration window opens. 3. Select which apps will support username authentication. 4. Select **Save**. The sign up flow will be updated for the applications you selected. ## Rules for usernames - Usernames must be unique - 2-64 characters, no spaces - Can include letters, numbers, -dashes, \_underscores (no special characters) - Case is ignored. Jane and jane are treated the same. ## One password for multiple identities Users can only have a single password in Kinde. If you allow both email-password and username-password authentication for a user, the password is shared across both their identities. For example, changing a user’s password for username affects their email sign-in and vice-versa. See [the password rules](/authenticate/authentication-methods/password-authentication/#password-strength). + +# Authenticate - Custom configurations - Manage organization-level auth features + +> Guide to advanced organization features including custom policies, default roles, email senders, custom domains, and organization-level MFA. + +advanced organizations, organization policies, default roles, custom email sender, custom domains, organization MFA +authenticate + + When you enable advanced organizations features, you can access extended features for individual organizations. Customizations include: - Additional access control via [policies](/build/organizations/organization-access-policies/) - Select [default roles](/manage-users/roles-and-permissions/default-user-roles/#enable-default-roles-in-an-organization) for users who join an organization - Set [custom email sender details](/build/organizations/email-sender-organization/), so users in specific orgs receive OTP and other emails from the custom address (requires own SMTP) - Organization-level [custom domains](/build/domains/organization-custom-domain/) - Organization-level [multi-factor authentication](/authenticate/multi-factor-auth/mfa-per-org/) Read our blog about why you might need [advanced organizations in Kinde](https://kinde.com/blog/authentication/advanced-organizations/). ## Enable advanced organization features 1. In Kinde, go to **Organizations**. 2. Search or browse for the organization you want and select the name to show the org details. 3. Select **Authentication**. 4. In the **Activate advanced organization features** box, select **Activate**. ## Disable advanced organization features 1. In Kinde, go to **Organizations**. 2. Search or browse for the organization you want and select the name to show the org details. 3. Scroll to the bottom of the **Details** page and select **Remove advanced org features**. 4. In the confirmation window, follow the prompts. + +# Authenticate - Custom configurations - Manage the authentication experience + +> Comprehensive guide to customizing the authentication experience including unified sign-up, name requirements, marketing consent, and profile picture settings. + +authentication experience, unified sign-up, seamless registration, marketing consent, Gravatar, login_hint +authenticate + +Kinde aims to give you as much control of your user’s sign up and sign in experience as possible, without compromising security. Here are some options for customizing the authentication experience in your applications. You’ll find these in Kinde: **Settings > Applications > View details** on your application. Application switches for custom sign in behaviour ## Use your own sign up and sign in screens Kinde offers custom authentication, allowing you to use your own sign up and sign in screens, bypassing the landing screens provided by Kinde. You can enable this for social sign in, email, phone, enterprise connections, or any combination of these sign up methods you support. See [Custom sign-up and sign-in pages](/authenticate/custom-configurations/custom-authentication-pages/) for more details. ## Create a unified sign-up / registration experience (seamless sign up) You can allow all users to register and sign from the same authentication screen, without forcing them to create an account first. To do this: 1. Update your app to redirect all authentication through the registration flow. To do this, change the link for the `sign in` button to go to the `register` button on the authentication screen. In Next.js, for example, you would change `` to use `` instead. 2. Switch off the requirement to ask for first name and last name on registration (see section below). 3. Go to **Settings > Applications > View details** on your application. Scroll to the **Authentication experience** section. 4. Switch off the **Show 'Already have an account? Sign in' on registration page** option. 5. Go to **Design > Page content**, then select **Sign up page** in the dropdown. Update the copy on the sign up page to cater for both the registration and sign in experience. 6. Select **Save**. The result is: - Users with an account will authenticate - Users without an account will be registered - Nobody will see a prompt to create an account You can do this for any authentication method, e.g. email + password, email + OTP, phone + SMS OTP, social connection, or enterprise connection. ![Example before and after register screen shot](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/03883607-f9f2-4b1a-b3cf-9773d2683400/public) ## Ask for first name and last name on sign up By default, the Kinde sign up flow includes fields for users to enter their first name and last name. However, if you don’t want to collect user’s names, you can easily switch this off. This can make the sign up experience a bit faster, because when a user goes to sign up, all they need is their email, phone number, or their social sign in. **To switch off the name requirement for sign up** 1. Go to **Settings > Applications > View details** on your application. 2. Scroll to the **Authentication experience** section. 3. Switch off **Ask for user first name and last name**. 4. Select **Save**. ## Request consent for marketing on sign up If you want, you can add a checkbox to the sign up screen for collecting user consent to receive marketing communications. See [Request user consent for marketing on sign up](/design/pages/marketing-consent/) for details. ## Switch off Gravatar fallback for profile pictures Typically, Kinde receives user profile pictures via the email provider, e.g. Google. If no picture is attached to a profile, Kinde sets the picture to use a Gravatar URL instead. Gravatar sends us a profile URL and either the user picture (if available) or a blank avatar is displayed in Kinde. To avoid blank avatars and to handle profile pictures a different way, you can switch off the Gravatar fallback. 1. Go to **Settings > Applications** and select **View details** on your application. 2. Scroll to the **Authenticaton experience** section and switch off the **Use Gravatar fallback** option. 3. Select **Save**. Read more about [email authentication](/authenticate/authentication-methods/email-authentication/). ## Pre-populate user identity for sign in Create a smoother sign up and sign in experience for users by passing `login_hint` with the auth URL. This prefills the user’s sign in identity, saving them from manually entering their email or phone number. You might want to do this, for example, if you invite users to sign up via email and you want to reduce friction and make signing in faster. See [Pre-populate user identity on sign in](/authenticate/custom-configurations/prepopulate-identity-sign-in/) for details. ## Include 'escape hatch' URLs for authentication errors You can include URLs in error messages so that users can click them to go back to the sign in screen or your home page. 1. Go to **Settings > Applications** and select **View details** on your application. 2. Set the **Application homepage URI** and the **Application login URI**. 3. Select **Save**. + +# Authenticate - Custom configurations - Custom sign-up and sign-in pages + +> Step-by-step guide to creating custom authentication pages while maintaining Kinde's security for verification and MFA processes. + +custom authentication pages, connection ID, login_hint, social auth, email auth, phone auth, enterprise auth +authenticate + +You can host your own custom sign up and sign in pages to use with Kinde. Integrate your own designs for the initial sign up and sign in page, and still get the security of Kinde’s auth (and verification) process. This gives you the best of both worlds: the security of hosted auth, and the ability to customize the initial sign-up experience for your users. ## Custom sign in for social authentication If you only allow users to sign up and sign in with social authentication - such as Google or Apple - then you can achieve a headless-type experience. Users sign up or sign in from your custom screen, then get pushed straight through to the social provider’s account selection screen. For example: ## Custom sign in for email authentication If you allow email sign up and sign in, the initial Kinde screen can be bypassed, but the Kinde code verification screen will still appear before sign in is completed. When a user signs up (say, via email), they do this in fields on your custom sign in screen. Then for verification, they see Kinde’s verification code screen. After that, it’s all you again. ## Screens that remain securely hosted by Kinde This feature lets you to bypass Kinde’s initial sign in screens, but the following screens are still hosted by Kinde and are part of our secure auth experience. - Enter password or One-time password (OTP) screens (see example above) - Multi-factor authentication screens - The organization switcher (if you support multiple organizations) - The screen where users can choose to create an account if one was not found ## Step 1: Switch on the custom auth option for your application 1. Go to **Settings** > **Applications**. 2. Select **View details** on the application you want to switch on custom auth for. 3. Scroll down and switch on the **Use your own sign-up and sign-in screens** option in the **Authentication experience** section. 4. Select **Save**. ## Step 2: Get the auth method connection ID Each authentication type you have set up in Kinde has a unique **Connection ID** attached to it. You need to add this connection ID to your screen design code, so that the Kinde screens get bypassed when users interact. 1. Go to **Settings > Authentication.** 2. Select **Configure** on the relevant authentication method tile. For example, the **Google** tile under the **Social connections** section. 3. Copy the **Connection ID** and paste it somewhere you can access later. 4. Select **Save** or **Cancel**. 5. Repeat for each authentication method you want to be included on your custom sign in screen. ## Step 3: Add the Connection ID to your design code There are different steps depending on the authentication method you use. Update your code for all that apply. ### Social sign in Add the `connectionId` to the auth url. Here is an example using React: ```jsx ``` You can now test if it works by signing in to your project or app. ### Email sign in Add the `connectionId` and `loginHint` params to the auth url. The `login_hint` enables you to pre-populate the email for the user, skipping the step where they have to enter their identity/email. It also tells us where to send their one time password for passwordless verification. Here is an example using React. ```jsx ``` You can now test if it works by signing in to your project or app. ### Phone sign in Add `connectionId` and `loginHint` params to the auth url. The `loginHint` enables you to pre-populate the phone for the user, skipping the step where they have to enter their phone number. It also tells us where to send their one time password for passwordless verification. The `loginHint` needs to be in one of these formats `phone::` or `phone:<+intl_number>:`. The ‘+’ symbol is optional, as long as the country code is included. Here is an example using React: ```jsx ``` You can now test if it works by signing in to your project or app. ### Enterprise sign in (Entra ID or SAML) Add the `connectionId` to the auth url. This takes the user directly to the enterprise authentication process. Here is an example using React: ```jsx ``` + +# Authenticate - Custom configurations - Disable self sign-up + +> Guide to disabling self sign-up for your business or specific organizations, allowing only selective user addition via import, manual addition, or API. + +disable sign-up, self sign-up, invitation only, user management, organization policies +authenticate + +You can prevent users from signing up to your business, and only add users selectively. You might do this if you only want to give access to employees or members. Disabling sign-ups applies across an environment. Depending on your Kinde plan, you may can also [manage sign-ups per organization](/build/organizations/allow-user-signup-org/). ## Disable self sign-up for your business 1. Go to **Settings > Environment > Policies**. 2. Switch off the **Allow self-sign up** option. You can then [import users](/manage-users/add-and-edit/import-users-in-bulk/), [add them manually](/manage-users/add-and-edit/add-and-edit-users/), or add them [via the Kinde API](/kinde-apis/management#tag/users/post/api/v1/user). ## Disable self sign-up to an organization You can disable self sign-up per organization. However, if you allow self sign-up in your business (and have not disabled it as per the above procedure), at least one organization must allow sign-ups. 1. Go to **Organizations**. 2. Select the organization you want to disable sign-ups for. 3. Go to **Policies**. 4. Switch off the **Allow org members to be auto-added** option. 5. Select **Save**. + +# Authenticate - Custom configurations - Pre-populate user identity on sign in + +> Guide to pre-populating user identity fields using login_hint parameter for email, phone, and username authentication to improve user experience. + +login_hint, pre-populate, user identity, email, phone, username, authentication UX +authenticate + +You can create a smoother sign-up and sign-in experience by passing a login_hint when users authenticate. When the user arrives at the sign-in page, their credentials are pre-filled, saving them time. This works for emails, phone numbers, and usernames. You might want to do this, for example, to reduce friction and make signing up extra easy. ## Enable login_hint Add the `login_hint` parameter to the sign up/sign in request on your app or site. ### Email example ```jsx ``` ### Phone example ```jsx ``` ### Username example ```jsx ``` + +# Authenticate - Custom configurations - Proxy your Kinde auth pages through Cloudflare + +> Guide to proxying Kinde authentication pages through Cloudflare to leverage advanced security features like WAF and bot mitigation. + +Cloudflare proxy, WAF, bot mitigation, custom domain, DNS, SSL, security +authenticate + +You can take advantage of Cloudflare’s advanced security features such as their WAF and bot mitigation tools by proxying your Kinde hosted auth pages through Cloudflare. ## What you need - A Cloudflare account - A domain managed in Cloudflare ## Set up the custom domain 1. Set up a custom domain in your Kinde business, see [Use your own custom domain](/build/domains/pointing-your-domain/). 2. Set up DNS records for the domain in Cloudflare. We will change this from DNS once the records have been validated. DNS validation confirms the record before we set the proxy. ## Set up the proxy Once you receive the email that the custom domain has been set up in Kinde, go to Cloudflare and change the custom domain record from **DNS only** to **Proxied**. ## Create a Cloudflare Managed Challenge To test the proxied domain, create a WAF rule to show a Cloudflare Managed Challenge on all incoming requests. For example, create a rule to match the hostname of the custom domain used in Kinde and the request originating from Australia. The action is to show a **Managed Challenge**. + +# Authenticate - Custom configurations - Redirect users + +> Guide to redirecting users after authentication using cookies, local storage, or the state parameter for secure post-auth navigation. + +user redirect, callback URL, state parameter, CSRF protection, local storage, cookies +authenticate + +After authenticating a user in Kinde, you can return them to a specific page within your application. Users are initially redirected back to the requested [Callback url](/get-started/connect/callback-urls/) you have included in your allowlist within Kinde. This is necessary to complete the token exchange and finalize the authentication flow. ## When to set a specific redirect A callback URL is not always where you want users redirected after authentication. You may want users to land on a specific dashboard page, or to trigger authentication if a user tries to access a protected page in your application. In both those cases, you can store a URL to redirect the user back to their intended page (after authentication) to provide a more seamless experience. ## Redirect without an SDK Most of our SDKs include a mechanism for redirecting users. However, if you are not using a Kinde SDK, use one of the following methods. 1. Store the intended URL in a cookie or local storage. 2. Use the `state` parameter. ## Store the URL in a cookie or local storage For single page applications the simplest is probably to leverage local storage to store the desired URL. Prior to redirecting to Kinde: ```jsx localStorage.setItem("nextUrl", "/some-protected-route"); ``` After authentication is complete: ```jsx const nextUrl = localStorage.getItem("nextUrl"); window.location.replace(nextUrl); ``` For server-side applications you can achieve the same thing with a cookie - essentially setting the next URL before redirecting to Kinde and fetching the value post-authentication. The implementation will depend on your language or framework choice. ## Use the state parameter You should be using the state parameter already to protect against CSRF attacks. [(Here's how Kinde uses the State param)](/get-started/learn-about-kinde/kinde-product-security/#csrf-protections-via-state-parameter). Essentially it's a random string that you would store in your application, so when you receive the response from Kinde you can validate it matches the one you sent. Because it is just a string, you can leverage it to store additional information, like the intended destination of your user. 1. Generate a random string in your application. For this example we will use:`BlueFox0101`. 2. Use this string as key for an object with the value of your application state and store this locally. For example: ```jsx { "BlueFox0101" : { nextUrl: '/some-protected-route', } } ``` 3. When you redirect your user to Kinde to complete the authentication flow, include the random string as the `state` param: ```jsx https://.kinde.com/oauth2/auth ?response_type=code &client_id= &redirect_uri= &scope=openid%20profile%20email &state=BlueFox0101 ``` 4. After the user has authenticated, they will be redirected back to your application and the `state` value will be included in the url: ```jsx https://.com/auth/callback ?code= &scope=openid%20profile%20email &state=BlueFox0101 ``` 5. As part of your callback processing and response validation, verify that the `state` returned in the URL above matches the random string you stored locally. If it does, retrieve the rest of the application state (like the nextUrl). 6. Use the `code` param to complete the token exchange (as per the [Use Kinde without an SDK](/developer-tools/about/using-kinde-without-an-sdk/#handling-the-callback) guide) and once the exchange is complete use the `nextUrl` to redirect the user. ## **Limitations and considerations** - Choose a storage method based on your application type. | App Type | Recommended storage | | --------------- | ------------------- | | Regular Web App | Cookie or session | | SPA | Local browser | | Native App | Memory or local | - `State` parameter values are not unlimited. `414 Request-URI Too Large` means you should try a smaller value. - Passing URLs in plain text or in any predictable way is unsafe. Ensure that the `state` parameter value is unique and opaque to ensure that it can be used for defence against CSRF and phishing attacks. - If the `state` parameter value is stored in a cookie, it should be signed to prevent forgery. ## A secure way to store redirect information The `state` parameter can mitigate [**CSRF attacks**](https://en.wikipedia.org/wiki/Cross-site_request_forgery) by using a unique and non-guessable value associated with each authentication request about to be initiated. That non-guessable value allows you to prevent the attack by confirming that the value coming from the response, matches the one you sent. The `state` parameter is also a string, so you can encode any information in it. You can send a random value when starting an authentication request and validate the received value when processing the response. You store something on the client application side (in cookies, session, or local storage) that allows you to perform the validation. Kinde SDKs handle `state` generation and validation automatically. + +# Authenticate - Custom configurations - Static IP + +> Guide to using a static IP address for your Kinde business. + +static-ip, infrastructure, whitelist +authenticate + + For companies who work in highly regulated industries such as government, financial services, or education, it is a common requirement to maintain strict 'whitelists' for accessing the internet. For customers with these requirements, Kinde can provide static IP addresses. ## Dynamic IPs are used by default Kinde uses AWS public cloud to host our services. We make use of AWS's highly scalable infrastructure to ensure the best availability and performance. This infrastructure design means that your Kinde business is assigned a DNS address created during onboarding, which will have a dynamic IP address managed by AWS. You then whitelist the Kinde business domain or your custom domain, to ensure that your customers can access authentication to your product. ## Request a static IP address For Kinde enterprise customers who have strict IP-based whitelists, Kinde can provide a pair of static IP addresses. We use AWS's Global Accellerator to provision 2 IP addresses assigned to your Kinde business and custom domain, which will ensure that the IP addresses are always the same. Please reach out to our team at support@kinde.com to discuss your requirements. + +# Authenticate - Device authorization flow - Call your API using device authorization flow + +Once you've received an access token from the device authorization flow, you can use it to call your protected APIs. This guide shows you how to validate tokens, handle scopes, and make authenticated API requests. ## Use the access token from the device authorization flow The access token you receive from the device authorization flow is a standard OAuth 2.0 Bearer token. Include it in the `Authorization` header of your API requests: ```bash curl -X GET https://your-api.com/protected-resource \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ## Token validation in the device authorization flow Before processing API requests, validate the access token to ensure it's valid and hasn't expired: ### Validate with Kinde's userinfo endpoint ```bash curl -X GET https://.kinde.com/oauth2/v2/user_profile \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` **Success response**: ```json { "sub": "kp_c3143a4b50ad43c88e541d9077681782", "provided_id": "some_external_id", "name": "John Snow", "given_name": "John", "family_name": "Snow", "updated_at": 1612345678, "email": "john.snow@example.com", "email_verified": true, "picture": "https://example.com/john_snow.jpg", "preferred_username": "john_snow", "id": "kp_c3143a4b50ad43c88e541d9077681782" } ``` **Error response** (invalid token): ```json { "error": "invalid_token", "error_description": "The access token is invalid or expired" } ``` ### Validate with your own API You can also validate tokens in your own API by verifying the JWT signature and claims: ```javascript +// Node.js example using jsonwebtoken with JWKS +const jwt = require("jsonwebtoken"); +const jwksClient = require("jwks-rsa"); + +const client = jwksClient({ + jwksUri: "https://.kinde.com/.well-known/jwks" +}); + +function getKey(header, callback) { + client.getSigningKey(header.kid, (err, key) => { + const signingKey = key.publicKey || key.rsaPublicKey; + callback(null, signingKey); + }); +} + +function validateToken(token) { + return new Promise((resolve, reject) => { + jwt.verify(token, getKey, { algorithms: ["RS256"] }, (err, decoded) => { + if (err) { + resolve({ valid: false, error: err.message }); + } else { + resolve({ valid: true, user: decoded }); + } + }); + }); +} ``` ## Scope enforcement for device authorization Access tokens include scopes that determine what resources the user can access. Check the required scopes before processing requests: ```javascript // Example: Check if user has required scope function hasRequiredScope(token, requiredScope) { const decoded = jwt.decode(token); const tokenScopes = decoded.scope.split(" "); return tokenScopes.includes(requiredScope); } // Usage if (!hasRequiredScope(accessToken, "read:users")) { return res.status(403).json({error: "Insufficient scope"}); } ``` ## Common API patterns for device authorization ### Protected resource endpoint ```javascript // Express.js example app.get("/api/protected-resource", authenticateToken, (req, res) => { // req.user contains the decoded token payload res.json({ message: "Access granted", user: req.user }); }); function authenticateToken(req, res, next) { const authHeader = req.headers["authorization"]; const token = authHeader && authHeader.split(" ")[1]; if (!token) { return res.status(401).json({error: "Access token required"}); } // Validate token with Kinde fetch("https://.kinde.com/oauth2/v2/user_profile", { headers: { Authorization: `Bearer ${token}` } }) .then((response) => { if (!response.ok) { throw new Error("Invalid token"); } return response.json(); }) .then((user) => { req.user = user; next(); }) .catch((error) => { return res.status(401).json({error: "Invalid token"}); }); } ``` ### Error handling for device authorization Handle common token-related errors: ```javascript function handleTokenError(res, error) { switch (error.error) { case "invalid_token": // Token is invalid or expired return res.status(401).json({error: "Please re-authenticate"}); case "insufficient_scope": // Token doesn't have required permissions return res.status(403).json({error: "Insufficient permissions"}); default: return res.status(500).json({error: "Authentication error"}); } } ``` ## Security best practices for device authorization ### Token storage - **Never store tokens in localStorage**: Use secure HTTP-only cookies or memory storage - **Validate tokens server-side**: Always validate tokens on your backend, not just the client ### Rate limiting Implement rate limiting for token validation requests: ```javascript const rateLimit = require("express-rate-limit"); const tokenValidationLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15 minutes max: 100, // limit each IP to 100 requests per windowMs message: "Too many token validation requests" }); app.use("/api/protected-resource", tokenValidationLimiter); ``` ### Logging and monitoring Log authentication events for security monitoring: ```javascript function logAuthEvent(token, action, success) { console.log({ timestamp: new Date().toISOString(), action: action, success: success, userId: token.user_id, scopes: token.scope }); } ``` ## Testing your API Test your protected endpoints with the access token: ```bash # Test with curl curl -X GET https://your-api.com/protected-resource \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" # Test with JavaScript fetch('https://your-api.com/protected-resource', { headers: { 'Authorization': 'Bearer YOUR_ACCESS_TOKEN' } }) .then(response => response.json()) .then(data => console.log(data)); ``` + +# Authenticate - Device authorization flow - About the device authorization flow + +Kinde's device authorization flow adheres to `RFC 8628`, also known as the OAuth 2.0 Device Authorization Grant. It enables authorization for devices with limited input capabilities, such as smart TVs, gaming consoles, or IoT devices. Users authenticate on a secondary device (like a phone or computer) while the primary device receives the access token. ## How the device authentication flow works 1. **Device requests authorization**: The device requests a device code and user code from Kinde. 2. **User authenticates**: The user visits a verification URI on another device and enters the user code. 3. **Device polls for token**: The device polls the token endpoint until authorization is complete. 4. **Access granted**: The device receives an access token and can call protected APIs. ## Endpoints for the device authorization flow ### Device authorization endpoint **URL**: `https://.kinde.com/oauth2/device/auth` **Method**: `POST` **Content-Type**: `application/x-www-form-urlencoded` **Parameters**: - `client_id` (optional): Your application's client ID - can be omitted if you have set an application as the default for device flows - `audience` (optional): The audience to use for the request **Response**: ```json { "device_code": "kinde_dc_device_code_here", "user_code": "CSLDFDUU", "verification_uri": "https://.kinde.com/device", "verification_uri_complete": "https://.kinde.com/device?user_code=CSLDFDUU", "expires_in": 600, "interval": 5, "qr_code": "data:image/png;base64,..." } ``` ### Token endpoint **URL**: `https://.kinde.com/oauth2/token` **Method**: `POST` **Content-Type**: `application/x-www-form-urlencoded` **Parameters**: - `grant_type`: `urn:ietf:params:oauth:grant-type:device_code` - `client_id`: Your application's client ID - `device_code`: The device code received from the authorization endpoint **Success response**: ```json { "access_token": "eyJ...", "expires_in": 86400, "scope": "", "token_type": "bearer" } ``` The scope field may be empty because granted scopes are carried in the access token’s scope claim. **Example error response**: ```json { "error": "authorization_pending", "error_description": "The user has not yet completed the authorization" } ``` ## Polling behavior The device must poll the token endpoint at regular intervals until the user completes authentication: - **Initial interval**: Use the `interval` value from the device authorization response (typically 5 seconds). - **Slow down**: If you receive a `slow_down` error, increase the polling interval by 5 seconds. - **Maximum time**: Stop polling after the `expires_in` time (typically 30 minutes). ## Device authorization flow error codes | Error Code | Description | Action | | ----------------------- | ------------------------------------ | ------------------------------ | | `authorization_pending` | User hasn't completed authentication | Continue polling | | `slow_down` | Polling too frequently | Increase interval by 5 seconds | | `access_denied` | User denied the authorization | Stop polling | | `expired_token` | Device code has expired | Request a new device code | | `server_error` | Misconfigured device code | Request a new device code | ## Security considerations for device authorization - **User code format**: User codes are formatted as `XXXXXXXX` for easy entry. - **Verification URI**: Users should verify they're on the correct domain. - **Token expiration**: Access tokens expire after 1 hour by default. ## Specifying an audience in a device authorization request If an `audience` is specified in the request, the access token will include the audience in the `aud` claim. Kinde supports requesting multiple audiences. The API must be authorized for the device authorization application. ## Scopes and permissions for a device authorization request If an audience is specified in the request, any scopes which are belong to that audience that are granted to the user by their role will also be granted to the device. The list of scopes will be displayed on the consent screen. If the user consents, the scopes will be included in the `scope` claim of the access token. + +# Authenticate - Device authorization flow - Quick start + +The 'Device Authorization Flow' allows users to authenticate on one device (like a TV or smart device) using another device (like a phone or computer). This is perfect for devices with limited input capabilities. In this quick start, you'll learn how to implement the device authorization flow using Kinde in just 5 minutes. ## Prerequisites for the device authorization flow - `curl` or a similar HTTP client ## Step 1: Create a Device Authorization app 1. From the Kinde home page select **Add application**. 2. Enter a name for the application. 3. Choose **Device and IoT**. 4. Select **Save**. 5. Make a note of the Client ID, you'll need this later. ## Step 2: Enable an authentication method for your application 1. Go to **Settings > Authentication**. 2. Select **Configure** on the **Passwordless** > **Email + code** card. 3. Under **Applications** select the application you created in step 1. 4. Select **Save**. ## Step 3: Request a device code Request a device code from Kinde's authorization endpoint: ```bash curl -X POST https://.kinde.com/oauth2/device/auth \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "client_id=" ``` The response will include a `device_code`, `user_code`, and `verification_uri`: ```json { "device_code": "kinde_dc_...", "user_code": "CSLDFDUU", "verification_uri": "https://.kinde.com/device", "verification_uri_complete": "https://.kinde.com/device?user_code=CSLDFDUU", "expires_in": 600, "interval": 5, "qr_code": "data:image/png;base64,..." } ``` ## Step 4: Display the user code Show the `user_code` to the user and provide the `verification_uri_complete` or QR code from the response. The user should: 1. Visit the `verification_uri_complete` URL on their phone or computer. 2. Complete the authentication process. ## Step 5: Poll for the access token While the user is authenticating, poll the token endpoint: ```bash curl -X POST https://.kinde.com/oauth2/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=urn:ietf:params:oauth:grant-type:device_code" \ -d "client_id=" \ -d "device_code=" ``` Continue polling every 5 seconds (or the `interval` value from the response) until you receive a successful response like: ```json { "access_token": "eyJ...", "expires_in": 86400, "scope": "", "token_type": "bearer" } ``` ## Step 6: Use the access token Once you have received the access token, you can call your protected APIs: ```bash curl -X GET https://your-api.com/protected-resource \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" ``` ## Default app for device flows When you set up a default app for device flows, this will be the application that is used if no Client ID is specified in the request. 1. Select **Settings** > **Applications** 2. Select the Device Authorization application you want to set as default 3. Select **Set as default** 4. Select **Save** + +# Authenticate - Device authorization flow - Troubleshooting device authorization + +This guide helps you diagnose and resolve common issues with device authorization flow. Learn how to handle errors, debug problems, and implement proper error recovery. ## Common error codes during device authorization ### authorization_pending **Error**: `authorization_pending` **Description**: The user hasn't completed the authorization process yet. **Solution**: Continue polling the token endpoint. This is normal behavior. ```javascript // Example: Handle authorization_pending if (error === "authorization_pending") { console.log("User has not completed authorization yet. Continue polling..."); // Wait for the specified interval before next poll setTimeout(pollForToken, interval * 1000); } ``` ### slow_down **Error**: `slow_down` **Description**: You're polling too frequently. **Solution**: Increase the polling interval by 5 seconds. ```javascript // Example: Handle slow_down if (error === "slow_down") { console.log("Polling too fast. Increasing interval..."); interval += 5; // Increase interval by 5 seconds setTimeout(pollForToken, interval * 1000); } ``` ### access_denied **Error**: `access_denied` **Description**: The user denied the authorization request. **Solution**: Stop polling and inform the user they need to try again. ```javascript // Example: Handle access_denied if (error === "access_denied") { console.log("User denied authorization"); showErrorMessage("Authorization was denied. Please try again."); stopPolling(); } ``` ### expired_token **Error**: `expired_token` **Description**: The device code has expired (typically after 30 minutes). **Solution**: Request a new device code. ```javascript // Example: Handle expired_token if (error === "expired_token") { console.log("Device code expired"); showErrorMessage("This code has expired. Please request a new one."); requestNewDeviceCode(); } ``` ## Polling mistakes during device authorization ### Too frequent polling **Problem**: Polling more frequently than the recommended interval. **Solution**: Always respect the `interval` value from the device authorization response. ```javascript // Good: Respect the interval function pollForToken(deviceCode, interval = 5) { setTimeout(() => { // Make token request checkTokenStatus(deviceCode); }, interval * 1000); } // Bad: Polling too frequently function pollForToken(deviceCode) { setInterval(() => { // This polls every 1 second - too frequent! checkTokenStatus(deviceCode); }, 1000); } ``` ### Not handling `slow_down` properly **Problem**: Not increasing the interval when receiving `slow_down` errors. **Solution**: Implement exponential backoff. ```javascript let currentInterval = 5; // Start with 5 seconds function pollForToken(deviceCode) { checkTokenStatus(deviceCode).then((response) => { if (response.error === "slow_down") { currentInterval += 5; // Increase by 5 seconds console.log(`Increasing interval to ${currentInterval} seconds`); } // Continue polling with updated interval setTimeout(() => pollForToken(deviceCode), currentInterval * 1000); }); } ``` ### Not stopping on errors **Problem**: Continuing to poll after receiving fatal errors. **Solution**: Stop polling for non-recoverable errors. ```javascript function pollForToken(deviceCode) { checkTokenStatus(deviceCode).then((response) => { if (response.error) { switch (response.error) { case "authorization_pending": // Continue polling setTimeout(() => pollForToken(deviceCode), interval * 1000); break; case "slow_down": // Increase interval and continue interval += 5; setTimeout(() => pollForToken(deviceCode), interval * 1000); break; case "access_denied": case "expired_token": // Stop polling - these are fatal errors stopPolling(); handleError(response.error); break; } } else { // Success - stop polling handleSuccess(response); } }); } ``` ## Network issues during device authorization ### Connection timeouts **Problem**: Network requests timing out. **Solution**: Implement proper timeout handling and retry logic. ```javascript function checkTokenStatus(deviceCode) { return fetch("https://.kinde.com/oauth2/token", { method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ grant_type: "urn:ietf:params:oauth:grant-type:device_code", client_id: "", device_code: deviceCode }), timeout: 10000 // 10 second timeout }) .then((response) => response.json()) .catch((error) => { console.error("Network error:", error); // Retry after a delay setTimeout(() => checkTokenStatus(deviceCode), 5000); }); } ``` ### DNS resolution issues **Problem**: Cannot resolve the Kinde domain. **Solution**: Verify your domain configuration and network connectivity. ```bash # Test DNS resolution nslookup .kinde.com # Test connectivity curl -I https://.kinde.com/oauth2/v2/device_authorization ``` + +# Authenticate - Enterprise connections - Manage enterprise connections + +> Comprehensive overview of enterprise authentication connections including SAML, Microsoft Entra ID, Google Workspace, Okta, and Cloudflare with provisioning options. + +enterprise connections, SAML, Microsoft Entra ID, Google Workspace, Okta, Cloudflare, SSO, JIT provisioning +authenticate + +Enterprise authentication is a common method for managing user access to systems in large organizations. Kinde supports a number of enterprise connection types, including: - [Custom SAML](/authenticate/enterprise-connections/custom-saml/) - [Microsoft Entra ID](/authenticate/enterprise-connections/azure/) (was Azure AD) WS Federated or Open ID - [Microsoft Entra ID (SAML)](/authenticate/enterprise-connections/entra-id-saml/) - [Google Workspace](/authenticate/enterprise-connections/custom-saml-google-workspace/) (via SAML) - [Okta](/authenticate/enterprise-connections/okta-saml-connection/) (via SAML) - [Cloudflare](/authenticate/enterprise-connections/cloudflare-saml/) (via SAML) - [LastPass](/authenticate/enterprise-connections/lastpass-sso/) (via SAML) ## Provisioning for enterprise connections Kinde offer a number of provisioning options for enterprise connections, including **just in time (JIT)** provisioning and **pre-provisioning** options. See [Provisioning users with enterprise connections](/authenticate/enterprise-connections/provision-users-enterprise/) ## How identities are handled in enterprise connections Users with enterprise identities in Kinde can’t also have other identity types in Kinde. E.g. a user can have an email identity and a social identity. But if a user has an enterprise identity, they cannot have other identities. In this case, identity information is sourced with the identity provider (IdP) and is managed via the identity provider, not in Kinde. Learn more about [identities in Kinde](/authenticate/about-auth/identity-and-verification/). ## Enterprise connections for B2B businesses Many businesses have businesses for customers (B2B), and use Kinde organizations to manage authentication and access. Kinde lets you set a number of enterprise authentication features at the organization level, see [Enterprise authentication for B2B](/authenticate/enterprise-connections/enterprise-connections-b2b/). ## Session sign out behavior When enterprise connection users sign out, they are only signed out of the Kinde session, they are not signed out of the identity provider. We do not force sign out of the IdP because this could break existing sessions the user is signed into, for other applications. This behavior also applies for social connections, where a third party is the identity provider. ## Routing in enterprise connections When users sign up via an enterprise connection with single-sign-on (SSO), they are routed to the identity provider (IdP) for identity verification. This happens when they select the SSO button on the home screen. You can set up a more seamless routing option using home realm discovery. ### Home realm discovery Home realm discovery routes users based on their email domain. So when a user enters their email and selects the continue button, they are routed to their IdP based on the email domain, to authenticate. For example if the user enters [chris@acme.com](mailto:chris@acme.com) Kinde checks which IdP uses the [**acme.com**](http://acme.com/) domain and silently verifies his identity. He only signs in once. Note that this feature has nothing to do with security or access control and everything to do with routing. Not to be confused with setting access restrictions for [domain allowlists](/authenticate/enterprise-connections/enterprise-connections-b2b/). Learn more about [home realm discovery](/authenticate/enterprise-connections/home-realm-discovery/). ## Show or hide the SSO sign-in button on the auth page When you set up enterprise auth in Kinde, an SSO button appears on the authentication page which is linked to the IdP by default. Users can select this as a sign up method, similar to how they might select a Google or Facebook sign-in option. For a more seamless experience, you can hide the SSO button by entering a home realm domain for the connection (more info above). Users will be routed silently via their IdP when they enter their credentials. If you have multiple enterprise auth methods (E.g. SAML and Entra ID), you may not want to show multiple SSO buttons. Here's the options for showing and hiding, depending how many enterprise auth methods you add: ### (Option 1) Hide all SSO buttons If you configure home realm discovery in each enterprise auth method, all SSO buttons will be hidden by default. The user enters their credentials and they are silently authenticated against the relevant IdP based on email domain. ### (Option 2) Show a universal SSO button for all If you would prefer users explicitly choose to sign in with SSO, you can add a universal button to the sign in screen. 1. Go to **Settings > Applications > Your application**. 2. On the **Details** page scroll down to the **Authentication experience** section. 3. Switch on **Show 'Sign in with SSO' button**. Users click the universal button, enter their credentials, and get routed silently to the IdP for verification. ## Enterprise connections only allow service provider log in, not identity provider log in If you run a B2B business, you might allow your business customers to use their own identity provider setup (like Okta SAML) to access your app. When you set up an enterprise connection to support this, make them aware they can only sign in via your app's auth gateway, with Kinde as the auth service provider. The customer cannot sign in to your app via their own connection setup - also known as IdP-initiated login. ## Disable an enterprise connection 1. Navigate to the connection in Kinde. Via **Organization > Authentication** or via **Settings > Authentication**. 2. For an organization-level connection: 1. Select the three dots menu on the connection tile. 2. Select **Disable connection**. 3. Confirm the action in the confirmation window. 3. For an enterprise level connection: 1. Select **Configure** on the connection tile. 2. Scroll down and disable the connection for each application. 3. Select **Save**. Confirm the action in the confirmation message. ## Delete an enterprise connection 1. Navigate to the connection in Kinde. Via **Organization > Authentication** or via **Settings > Authentication**. 2. Select the three dots menu on the connection tile. 3. Select **Delete connection**. 4. Confirm the action in the confirmation window. + +# Authenticate - Enterprise connections - Advanced SAML configurations + +> Advanced SAML configuration options including Name ID formats, signing algorithms, protocol bindings, and upstream parameters for enterprise authentication. + +SAML, Name ID, signing algorithm, protocol binding, upstream parameters, RSA-SHA256, HTTP POST binding +authenticate + +When you set up a SAML connection, you might need to include advanced configurations to meet identity provider requirements, and to get the connection running properly and securely. Here's some of the advanced options you will come across when setting up a connection. ## Name ID Name ID (Name Identifier) is a key element in a SAML assertion that uniquely identifies the user (subject) within a given SAML context. It is included in the `Subject` element of the SAML assertion and is critical for identifying and linking user identities between your Identity Provider (IdP) and Kinde. Available Name ID formats: - **Unspecified**: No particular format is required - **EmailAddress**: A user is identified by their email address - **Persistent**: A stable, opaque identifier intended to remain consistent across sessions - **Transient**: A short-lived identifier, often used in single sign-on (SSO) scenarios for one-time use The Name ID you select in Kinde must be supported and configured in your IdP. ## Sign request algorithm The Sign Request Algorithm defines the cryptographic algorithm used to sign SAML requests (AuthnRequest). Signing ensures the authenticity and integrity of SAML messages. Available algorithms: - **RSA-SHA256**: A commonly used and secure option. - **RSA-SHA1**: Older and less secure; often deprecated. Secure configurations favor SHA256 or stronger algorithms to protect against vulnerabilities. ## Protocol binding Protocol Binding refers to the transport mechanism used to send the SAML authentication request from Kinde to your IdP. Common Binding Types: - **HTTP Redirect Binding**: The SAML request is sent as a URL parameter using a GET request. It is lightweight but limited in message size. - **HTTP POST Binding**: The SAML request is sent via an HTML form using the POST method. It supports larger payloads and is commonly used for transmitting signed requests. The choice of binding affects security, performance, and compatibility. POST Binding is generally preferred for secure communications due to its ability to handle signed messages and larger payloads. ## Key attributes Key Attributes are additional pieces of information about the user that come from your IdP to Kinde. These attributes provide more context about the authenticated user and are often used for access control or personalization. Kinde-supported key attributes: - Email Address: The user’s email, often used for identification or communication. - First Name / Last Name: Used for personalization or internal system mapping. - User ID: The attribute in the SAML token that contains the user ID. Only configure key attributes if supported by your IdP. ## Upstream parameters You can pass provider-specific parameters to an Identity Provider (IdP) during authentication. These are also known as 'upstream params'. The values your pass can either be static per connection or dynamic per user. You can use upstream params to create a smoother sign in experience - by passing the email through, or to offer an account switcher (such as the Google account switcher) during sign in. Note that every identity provider has their own set of supported parameters and values, so you'll need to check their documentation to determine which URL parameters are supported. For more information, see [Pass parameters to identity providers](/authenticate/auth-guides/pass-params-idp/). + +# Authenticate - Enterprise connections - MS Entra ID (was Azure AD) enterprise auth + +> Step-by-step guide to setting up Microsoft Entra ID (formerly Azure AD) enterprise authentication with WS Federated and OAuth 2.0 protocols. + +Microsoft Entra ID, Azure AD, WS Federated, OAuth 2.0, enterprise auth, group sync, upstream params +authenticate + +Kinde supports the use of Microsoft Entra ID as an authentication method. We support WS Federated and OAuth2.0 (follow the topic below), and [Microsoft Entra ID SAML](/authenticate/enterprise-connections/entra-id-saml/) which is covered in a separate topic. If you [import users into Kinde](/manage-users/add-and-edit/import-users-in-bulk/), their Entra ID will be picked up and matched to the relevant connection based on their email address, for a seamless transition to Kinde. You can also pass [upstream params](/authenticate/auth-guides/pass-params-idp/) to the IdP as part of this procedure. ## Before you begin - Register an app in the [Microsoft Entra Admin Center](https://entra.microsoft.com/#home) See the docs [here](https://learn.microsoft.com/en-us/entra/identity-platform/quickstart-register-app/). - Copy the Client ID and Client Secret from the Microsoft app. - We recommend you test connections in a non-production environment before activating in a live environment. ## Step 1: Add and configure the connection in Kinde ### Add a connection for a specific organization 1. Go to **Organizations** and open the organization. 2. In the menu, select **Authentication**, then select **Add connection**. 3. In the **Add connection** window, select **New enterprise connection**, then click **Next**. 4. Select the Microsoft connection type you want (WS Federated or OAuth2.0) and then select **Next**. 5. Next: 'Step 2: Configure the connection'. ### Add a connection that can be shared across multiple organizations 1. Go to **Settings > Environment > Authentication**. 2. Scroll to the **Enterprise connection** section and select **Add connection**. The **Add connection** window opens. 3. Select the Microsoft connection type you want (WS Federated or OAuth2.0) and then select **Save**. 4. Next: 'Step 2: Configure the connection'. ## Step 2: Configure the connection 1. Enter a **Connection name.** Make this something you can easily identify, especially if you are adding multiple connections for different business customers. 2. Enter your **Microsoft Entra domain.** ![Configure screen](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/27b313dc-73c7-4bd5-927f-f8f3d5121800/public) 3. Enter the **Client ID** and **Client secret** as they appear in the MS Entra application. Make sure you use the **Value** of the client secret. 4. Enter **Home realm domains**. This speeds up the sign in process for users of those domains. Note that all home realm domains must be unique across all connections in an environment. For more information about how, see [Home realm domains or IdP discovery](/authenticate/enterprise-connections/home-realm-discovery/). 5. If you use home realm domains, the sign in button is hidden on the auth screen by default. To show the SSO button, select the **Always show sign-in button** option. 6. If you want, select the **Use common endpoint** option. Recommended if you use multi-tenancy. ![Provisioning config for entra oauth2](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/c92fad8c-8c81-4481-e891-670a310fe300/public) 7. Select **Extended profile** if you want to sync the additional information stored in a user’s Microsoft profile to their Kinde user profile. Extended attributes data is included in the `extra_claims` object of the access token. 8. If you want to sync user groups, select **Get user groups**. Recommended if you manage permissions and access via user groups in Microsoft. You also need to do some additional setup, see below. 9. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 10. If you want, select **Sync user profiles and attributes on sign in**. Recommended to keep Kinde user profile data in sync with user profile data from Microsoft. If you choose this option, ensure that the global profile sync preference is also switched on in **Settings > Environment > Policies**. 11. If you want to enable just-in-time (JIT) provisioning, select the **Create a user record in Kinde** option. This saves time adding users manually or via API later. 12. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 13. Copy the **Callback URL**. You’ll need to enter this in your Entra ID app. 14. Select **Save**. ## Step 3: Add the callback URL to your Entra ID app 1. Open your application in the [Portal](https://entra.microsoft.com/#home). 2. Select the **Redirect URIs** links on the right. 3. Select **Add URI**. 4. In the relevant field, enter your callback URL (from the 'Configure the connection' procedure above) 5. Select **Save**. ## Step 4: Enable the connection in Kinde Make sure you test the connection before enabling in production for your users. 1. Open the connection configuration page in Kinde. 2. Switch on the connection. This will make it instantly available to users if this is your production environment. 1. For environment-level connections, scroll down and select the apps that will use the auth method. 2. For organization-level connections, scroll down and select if you want to switch this on for the org. 3. Select **Save**. ## (Optional) Sync Entra ID groups with Kinde ### Add groups claim to MS Entra ID app 1. Open your application in the [Portal](https://entra.microsoft.com/#home). 2. Go to **Token configuration** in the left menu. 3. Select **Add groups claim**. 4. In the window that appears, select the groups to be included in tokens. ![image of edit groups claim screen](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/fed278be-bdcd-43b6-7130-8c866928b700/public) 5. If you want, customize the token properties by type. 6. Save your changes. For reference, see this Microsoft doc about [configuring optional claims](https://learn.microsoft.com/en-us/entra/identity-platform/optional-claims?tabs=appui/) ### Customize ID token in Kinde 1. Open your application in Kinde. 2. Go to **Tokens**. 3. Scroll to **Token customization** and select **Configure** on the **ID tokens** tile. 4. Switch on **Social identity** as an additional claim. 5. Select **Save**. ### Access group info in tokens - ID token - `ext_provider > claims > profile > groups` - Access token - `ext_groups` ## Step 4: Test the connection 1. Go to your test application and attempt to sign in. 2. If you left the **Home realm domains** field blank in Kinde, when you launch your application, you should see a button to sign in. Click it and go to step 4. 3. If you completed the **Home realm domains** field, you should be redirected immediately to your IdP sign in screen. 4. Enter your IdP details and complete any additional authentication required. + +# Authenticate - Enterprise connections - Use Cloudflare as a SAML identity provider + +> Step-by-step guide to integrating Cloudflare as a SAML identity provider with Kinde for enterprise authentication and access control. + +Cloudflare, SAML, identity provider, IdP, Zero Trust, enterprise auth, SSO, access policies +authenticate + +If you use Cloudflare to centralize authentication and authorization in your business, you can integrate Kinde as a service provider for these processes. This gives you the benefits of Kinde’s robust auth capabilities, while keeping the familiar Cloudflare structure. You need to set up an enterprise connection in Kinde for this, and add a Cloudflare application. We recommend setting up and testing the connection in a non-production environment before making available to users. ## Advanced configurations Depending on your SAML set up, you may need to include advanced configurations for your connection. See [Advanced SAML configurations](/authenticate/enterprise-connections/advanced-saml-configurations/) ## Step 1: Add the connection in Kinde ### Add a connection for a specific organization 1. Go to **Organizations** and open the organization. 2. In the menu, select **Authentication**, then select **Add connection**. 3. In the **Add connection** window, select **New enterprise connection**, then click **Next**. 4. Select the Cloudflare connection and then select **Next**. 5. Next: 'Step 2: Configure the connection'. ### Add a connection that can be shared across multiple organizations 1. Go to **Settings > Environment > Authentication**. 2. Scroll to the **Enterprise connection** section and select **Add connection**. The **Add connection** window opens. 3. Select the Cloudflare connection and then select **Next**. 4. Next: 'Step 2: Configure the connection'. ## Step 2: Configure the connection 1. Enter a name for the connection. It should match the connection name in Cloudflare. 2. Enter a random string value for Entity ID, for e.g. `870sa9fbasfasdas23aghkhc12zasfnasd`. 3. Enter the **IdP metadata URL**. This URL comes from your identity provider. ![optional fields for saml](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/4f1851db-5c34-496b-ced1-07c1cd272b00/public) 4. Enter a **sign in URL** if your IdP requires a specific URL. 5. If you want, select the **Sign request algorithm** and **Protocol binding**. The options you choose will depend on what your identity provider prefers or requires. 6. Select a **Name ID** format. This helps identify and link user identities between your IdP and Kinde. 7. Enter an **Email key attribute**. This is the attribute in the SAML token that contains the user’s email. Setting this value ensures that the email address returned in the SAML response is correctly retrieved. We do not recommend leaving this field blank, but if you do we will set ‘email’ as the attribute. 8. (Optional) Add a first name and last name key attribute. ![Home realm domains in SAML configuration](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/dbdccca5-2e6c-4dd8-eaec-e029574daf00/public) 9. Enter any relevant **Home realm domains**. This is how SAML recognizes a user’s credentials and routes them to the correct sign in page. Note that home realm domains need to be unique across all connections in an environment. [Read more about home realm domains](/authenticate/enterprise-connections/home-realm-discovery/). 10. If you use home realm domains, the sign in button is hidden on the auth screen by default. To show the SSO button, select the **Always show sign-in button** option. ![ACS URL and custom domain option](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/885eda9c-ca4f-4340-db17-224023b8c300/public) 11. Copy the relevant reply URL: 1. If you don't use a custom domain, copy the **ACS URL**. 2. If you do use a custom domain, select the **Use custom domain instead** option and copy the custom domain URL. Later, add this URL to your identity provider configuration. 12. If you want to enable just-in-time (JIT) provisioning for users, select the **Create a user record in Kinde** option. This saves time adding users manually or via API later. ![Provisioning configuration for SAML](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/947baea7-bfd4-48b7-de2d-5b041b8c8300/public) 13. (Temporary feature) Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. 14. (Optional) In the **Sign SAML request** section, paste in the **Signed certificate** and **Private key**. You may have got these from your IdP or you may have generated yourself (see procedure above). 15. Enter any [upstream params](/authenticate/enterprise-connections/advanced-saml-configurations/#upstream-parameters) that you want to pass to the identity provider. Not all providers support this, so check their documentation first. 16. Select **Save**. ## Step 3: Add and configure your Cloudflare application 1. Sign in to your Cloudflare account. 2. In the menu, select **Zero trust**. 3. Go to **Access > Applications**, then select **Add an application**. 4. Select SaaS as the type of application. The **Add application** window opens. ![Application settings](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/7a600656-63c7-42a1-73c6-8780c6d4f400/public) 5. Enter an application name or select an application. 6. Choose **Select SAML** for the authentication protocol. 7. Select **Add Application**. The **Configure application** page opens. ![Configure application in Cloudflare](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/64549f6e-4a94-41a0-7018-0fb7b7becf00/public) 7. Add the **Entity ID** and **ACS URL** from Kinde. 8. Copy the **SAML Metadata endpoint** to your clipboard. You'll need to enter this back in Kinde. 9. Scroll through the other sections and then select **Save configuration**. The **Add policies** page opens. 10. Add a policy to define who can access your application. You might do this via an allowlist and groups, or other strategy. 11. Complete any other relevant sections of the window, and then select **Done**. ![Screen shot of Application list in Cloudflare](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/c11f72f1-22ff-428c-a7db-a13493ea5f00/public) ## Step 4: Finish setting up your Cloudflare connection 1. Open the connection in Kinde. Via **Organization > Authentication** or via **Settings > Authentication**. 2. Scroll to the **IdP metadata URL** field and paste the **Metadata URL** you copied from your Cloudflare app. 3. Switch on the connection. This will make it instantly available to users if this is your production environment. 1. For environment-level connections, scroll down and select the apps that will use the auth method. 2. For organization-level connections, scroll down and select if you want to switch this on for the org. 4. Select **Save**. + +# Authenticate - Enterprise connections - Custom SAML with Google Workspace + +> Step-by-step guide to setting up Google Workspace SAML authentication including metadata file hosting and Admin Console configuration. + +Google Workspace, SAML, enterprise auth, metadata hosting, Admin Console, SSO +authenticate + +You can set up SAML to work with your Google Workspace. ## Hosting the SAML metadata XML file Google does not support hosting your SAML metadata XML file on their web services, but Kinde requires access to the file via URL so that certificates are always up to date. We recommend you host the file on a public web service that can be accessed by Kinde. For example, you could use an [AWS S3](https://aws.amazon.com/s3/) bucket, [Cloudflare R2](https://developers.cloudflare.com/r2/), or public website. ## Advanced configurations Depending on your SAML set up, you may need to include advanced configurations for your connection. See [Advanced SAML configurations](/authenticate/enterprise-connections/advanced-saml-configurations/). ## Step 1: Add Google Workspace SAML in Kinde You can make a connection available only to a specific organization, or you can create it so it can be used across any organization in your business. ### Add a connection for a specific organization 1. Go to **Organizations** and open the organization. 2. In the menu, select **Authentication**, then select **Add connection**. 3. In the **Add connection** window, select **New enterprise connection**, then click **Next**. 4. Select the connection type you want and then select **Next**. 5. Next: 'Step 2: Configure the connection'. ### Add a connection that can be shared across multiple organizations 1. Go to **Settings > Environment > Authentication**. 2. Scroll to the **Enterprise connection** section and select **Add connection**. The **Add connection** window opens. 3. Select the connection type you want and then select **Next**. 4. Next: 'Step 2: Configure the connection'. ## Step 2: Configure the connection 1. Enter the **Connection name**. This name is what will appear on the button on the authentication screen. We will call it ‘Google Workspace’ for this example. 2. Enter an **Entity ID**. This field can be any mix of numbers and letters, as long as it matches your IdP configuration. Copy this somewhere you can access it later. 3. If you are adding this connection to a live environment, you will be prompted to enter an **IdP Metadata URL** before you can save. If you are not sure of the file location, enter any URL and we will update this later. ![connection window](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/4fa556a1-7f8e-4926-d7ef-a274409e7700/public) 4. Enter a **sign in URL** if your IdP requires a specific URL. 5. If you want, select the **Sign request algorithm** and **Protocol binding**. The options you choose will depend on what your identity provider prefers or requires. 6. Select a **Name ID** format. This helps identify and link user identities between your IdP and Kinde. 7. Enter an **Email key attribute**. This is the attribute in the SAML token that contains the user’s email. Setting this value ensures that the email address returned in the SAML response is correctly retrieved. We do not recommend leaving this field blank, but if you do we will set ‘email’ as the attribute. 8. (Optional) Add a first name and last name key attribute. ![Home realm domains in SAML configuration](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/dbdccca5-2e6c-4dd8-eaec-e029574daf00/public) 9. Enter any relevant **Home realm domains**. This is how SAML recognizes a user’s credentials and routes them to the correct sign in page. Note that home realm domains need to be unique across all connections in an environment. [Read more about home realm domains](/authenticate/enterprise-connections/home-realm-discovery/). 10. If you use home realm domains, the sign in button is hidden on the auth screen by default. To show the SSO button, select the **Always show sign-in button** option. ![ACS URL and custom domain option](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/885eda9c-ca4f-4340-db17-224023b8c300/public) 11. Copy the relevant reply URL: 1. If you don't use a custom domain, copy the **ACS URL**. 2. If you do use a custom domain, select the **Use custom domain instead** option and copy the custom domain URL. Later, add this URL to your identity provider configuration. 12. If you want to enable just-in-time (JIT) provisioning for users, select the **Create a user record in Kinde** option. This saves time adding users manually or via API later. ![Provisioning configuration for SAML](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/947baea7-bfd4-48b7-de2d-5b041b8c8300/public) 13. (Temporary feature) Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. 14. (Optional) In the **Sign SAML request** section, paste in the **Signed certificate** and **Private key**. You may have got these from your IdP or you may have generated yourself (see procedure above). 15. Enter any [upstream params](/authenticate/enterprise-connections/advanced-saml-configurations/#upstream-parameters) that you want to pass to the identity provider. Not all providers support this, so check their documentation first. 16. Select **Save**. ## Step 3: Configure Google Workspace Admin Console 1. Sign in to your [Google Workspace Admin Console](https://admin.google.com/). 2. In the main menu, go to **Apps > Web and Mobile Apps**. 3. Select **Add App > Add custom SAML app.** ![adding custom saml app](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/d02e7219-70e1-437c-41b3-b60263568900/public) 4. Complete the **App details** window: 1. Enter a name in the **App name** field. 2. Enter a **Description** for the app. 3. If you want, upload an icon for the app. 4. Select **Continue**. ![identity details](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/859218b5-4ca0-4fab-2475-3146088dc700/public) 5. Copy the **Google Identity Provider details** by selecting **DOWNLOAD METADATA** under Option 1. This is the file you will need to upload to a file storage location and provide a URL to finish setting up in Kinde. 6. Select **Continue**. ![Service provider details](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/91f8d1a9-bcd0-4b11-702e-c4593ac73d00/public) 7. Enter the **Service provider details**: 1. Enter or paste in the **ACS URL** you copied from Kinde earlier. 2. Enter or paste the **Entity ID**, this needs to match what was entered in Kinde earlier. 3. Set the **Name ID format** as **EMAIL**. 4. Select **Continue**. 8. On the **Attribute mapping** page, select **Finish**. 9. If you want to grant access to other users, select the chevron in the right corner of the **User access** panel. This opens additional options. ![user access panel](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/c7e3c185-e1db-49b2-8e02-25ca7320cf00/public) 10. If you want, you can change the access to suit your organization’s needs. You can do this per Organizational unit or switch **ON for everyone.** 11. Select **Save**. ## Step 4: Upload metadata file As mentioned at the start, you need to upload the **metadata file** that you downloaded, to somewhere publicly accessible. This is because Google does not provide a publicly available URL for the metadata file. 1. Upload the metadata file to your storage location. 2. Copy the URL for the file. ## Step 5: Complete Kinde configuration 1. Open the connection's configuration page in Kinde. 2. In the **IdP metadata URL** field, paste the URL for the metadata file. 3. Switch on the connection. This will make it instantly available to users if this is your production environment. 1. For environment-level connections, scroll down and select the apps that will use the auth method. 2. For organization-level connections, scroll down and select if you want to switch this on for the org. 4. Select **Save**. ## Test the connection Once you have completed the above steps, you should be able to see a **Google Workspace** sign-in button on your product’s authentication screen. Note: if you gave the enterprise connection a different name in Kinde, the button will have the name you entered. If you can’t see the button: - Check that the metadata URL and other connection details are correct in Kinde. - Check that user access is set up in your app, in the Google Workspace Console. Try to sign in and hopefully - success!! + +# Authenticate - Enterprise connections - Custom authentication with SAML + +> Complete guide to setting up custom SAML authentication with any identity provider including certificate generation, advanced configurations, and testing. + +SAML, custom SAML, identity provider, IdP, service provider, SP, certificate, private key, JIT provisioning +authenticate + +In Kinde, you can use SAML as your authentication protocol. Kinde acts as a service provider (SP), so you still need to bring your own identity provider (IdP) to set it up. Identity providers can include Google, Microsoft, Cloudflare, and others. Note: Since there are differences between set ups for each IdP, we are unable to provide full details on how to configure them all to connect with Kinde. However, the fields we mention below, should have similar names in your IdP. Some concepts are explained in the [advanced SAML configurations](/authenticate/enterprise-connections/advanced-saml-configurations/) topic. ## User provisioning Before you set up SAML, you can [import users in bulk](/manage-users/add-and-edit/import-users-in-bulk/), add them via [API](/kinde-apis/management#tag/users/post/api/v1/user), or [manually](/manage-users/add-and-edit/add-and-edit-users/) in Kinde. Alternatively, you can also take advantage of just-in-time (JIT) provisioning (Step 13 below) when you set up the connection. ## (Optional) Signed certificate and private key You can increase SAML security by adding a certificate and private key pair to your setup. Your IdP will check that the certificate and private key matches, each time a user authenticates this way. You can obtain the certificate and key from your IdP or you can generate yourself, see below. ### Generate a certificate and private key pair 1. In your preferred system, run a command to generate a certificate and key. For example, on \*nix systems, the command is: `openssl req -x509 -nodes -sha256 -days 3650 -newkey rsa:2048 -keyout private_key.key -out certificate.crt`. 2. This command may also work in other systems, such as WSL on Windows. Alternatively, you can try installing openssl binaries for your system. 3. Once the files are generated, save them locally. 4. Add the certificate to your IdP settings. The certificate there and the one in Kinde must match exactly. Instructions for how to do this varies, depending on your IdP. 5. Copy the certificate and private key details into Kinde as per the procedure below. ## Advanced configurations Depending on your SAML set up, you may need to include advanced configurations for your connection. See [Advanced SAML configurations](/authenticate/enterprise-connections/advanced-saml-configurations/) ## Step 1: Add SAML connection in Kinde ### Add a connection for a specific organization 1. Go to **Organizations** and open the organization. 2. In the menu, select **Authentication**, then select **Add connection**. 3. In the **Add connection** window, select **New enterprise connection**, then click **Next**. 4. Select the connection type you want and then select **Next**. 5. Next: 'Step 2: Configure the connection'. ### Add a connection that can be shared across multiple organizations 1. Go to **Settings > Environment > Authentication**. 2. Scroll to the **Enterprise connection** section and select **Add connection**. The **Add connection** window opens. 3. Select the connection type you want and then select **Next**. 4. Next: 'Step 2: Configure the connection'. ## Step 2: Configure the connection 1. Enter a name for the connection. It must match the name in your SAML setup. 2. Enter an **Entity ID.** This is a value you can make up using a random alphanumeric string, e.g. `5836g209gbhw09r8y0913`. The Entity ID you enter here must be configured exactly the same in your identity provider (unless your IdP is Microsoft Azure). ![SAML configuration screen](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/740dba80-b1a3-410e-f03b-c07e9261f000/public) 3. If Microsoft is your provider and your app is a bit older, you may need to add `spn:` to the beginning of the **Entity ID** string in Kinde, e.g. `spn:5836g209gbhw09r8y0913`. This is not required for newly created apps. 4. Enter the **IdP metadata URL**. This URL comes from your identity provider. ![optional fields for saml](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/4f1851db-5c34-496b-ced1-07c1cd272b00/public) 5. Enter a **sign in URL** if your IdP requires a specific URL. 6. If you want, select the **Sign request algorithm** and **Protocol binding**. The options you choose will depend on what your identity provider prefers or requires. 7. Select a **Name ID** format. This helps identify and link user identities between your IdP and Kinde. 8. Enter an **Email key attribute**. This is the attribute in the SAML token that contains the user’s email. Setting this value ensures that the email address returned in the SAML response is correctly retrieved. We do not recommend leaving this field blank, but if you do we will set ‘email’ as the attribute. 9. (Optional) Add a first name and last name key attribute. ![Home realm domains in SAML configuration](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/dbdccca5-2e6c-4dd8-eaec-e029574daf00/public) 10. Enter any relevant **Home realm domains**. This is how SAML recognizes a user’s credentials and routes them to the correct sign in page. Note that home realm domains need to be unique across all connections in an environment. [Read more about home realm domains](/authenticate/enterprise-connections/home-realm-discovery/). 11. If you use home realm domains, the sign in button is hidden on the auth screen by default. To show the SSO button, select the **Always show sign-in button** option. ![ACS URL and custom domain option](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/885eda9c-ca4f-4340-db17-224023b8c300/public) 12. Copy the relevant reply URL: 1. If you don't use a custom domain, copy the **ACS URL**. 2. If you do use a custom domain, select the **Use custom domain instead** option and copy the custom domain URL. Later, add this URL to your identity provider configuration. 13. If you want to enable just-in-time (JIT) provisioning for users, select the **Create a user record in Kinde** option. This saves time adding users manually or via API later. ![Provisioning configuration for SAML](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/947baea7-bfd4-48b7-de2d-5b041b8c8300/public) 14. (Temporary feature) Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. 15. (Optional) In the **Sign SAML request** section, paste in the **Signed certificate** and **Private key**. You may have got these from your IdP or you may have generated yourself (see procedure above). 16. Enter any [upstream params](/authenticate/enterprise-connections/advanced-saml-configurations/#upstream-parameters) that you want to pass to the identity provider. Not all providers support this, so check their documentation first. 17. Switch on the connection. This will make it instantly available to users if this is your production environment. 1. For environment-level connections, scroll down and select the apps that will use the auth method. 2. For organization-level connections, scroll down and select if you want to switch this on for the org. 18. Select **Save**. Next: Complete any additional configuration in your identity provider’s settings, such as adding the **Entity ID** and **return URL**. ## Step 3: Test the connection Once you have entered the ACS URL in your identity provider, the connection should be enabled. 1. Go to your test application and attempt to sign in. 2. If you left the **Home realm domains** field blank in Kinde, when you launch your application, you should see a button to sign in. Click it and go to step 4. 3. If you completed the **Home realm domains** field, you should be redirected immediately to your IdP sign in screen. 4. Enter your IdP details and complete any additional authentication required. + +# Authenticate - Enterprise connections - Enterprise connections for B2B + +> Guide to setting up enterprise connections for B2B businesses including organization-level connections and domain-based access control. + +B2B, enterprise connections, organization-level, domain restrictions, JIT provisioning, allowed domains +authenticate + + Enterprise connections are common for B2B setups where each business customer is represented as an organization in Kinde, and that organization is linked to one or more connections. There are two different ways to scope an enterprise connection and restrict it to the organization level. - When the `org_code` is passed to Kinde as part of the authentication url, the correct sign-in options are shown. - Users can only self-join the organization if this was enabled as part of the connection configuration. - Organization access is locked down to allow access based only on connection - including switches between organizations. - If you are using home realm discovery, connections do not have to be enabled at the application level to support redirects to the correct IDP. This behaviour is domain-agnostic and is purely concerned with the connection being used. ## (Recommended) Create the enterprise connection in the Kinde organization The easiest way to restrict an enterprise connection to an organization, is to add the connection to the organization and not create it as a shared connection (at the environment level). To do this, follow the relevant procedure for adding a connection in the relevant topic. ## Select a shared enterprise connection for the organization 1. Open the relevant organization in Kinde and select **Authentication** in the menu. 2. Add a connection and select **existing connection**. Switch on the relevant enterprise connection from the list. 3. Select **Save**. ## Org provisioning and access via allowed domains To manage organization access, you can [set policies](/build/organizations/organization-access-policies/) that restrict access to a list of allowed domains. You can also enable just-in-time (JIT) provisioning via allowed domains. 1. Open the relevant organization in Kinde and select **Policies** in the menu. 2. Select **Allow org members to be auto-added**. 3. Enter all the allowed domains in the **Allowed domains** list. 4. Enable JIT provisioning for all new organization members by selecting **Auto-add users from allowed domains**. 5. Select **Save**. Here’s what happens: - When the `org_code` is passed to Kinde as part of the authentication url, the correct sign-in option is shown. - Kinde checks that users belong to one of the allowed domains before authorizing access. - The user joins the organization if the domain matches any of the allowed domains. - Because this check only happens during sign up, you can still separately add users with email domains which fall outside of this restriction. This can be useful if you wish to add contractors or auditors who may have email addresses not in the domain allowlist. ## Enterprise connections only allow service provider log in, not identity provider log in If you set up an enterprise connection for a customer using their IdP credentials, they can only sign in to your app via your app, with Kinde as the auth service provider. The customer cannot sign in to your app via their own connection setup - known as IdP-initiated login. + +# Authenticate - Enterprise connections - MS Entra ID (SAML) enterprise connection + +> Step-by-step guide to setting up Microsoft Entra ID SAML enterprise authentication including application configuration and group synchronization. + +Microsoft Entra ID, SAML, Azure AD, enterprise application, group claims, federation metadata +authenticate + +Kinde supports the use of Microsoft Entra ID (SAML) as an enterprise-level authentication method. This service used to be Azure AD. If you are [importing users into Kinde](/manage-users/add-and-edit/import-users-in-bulk/), their Entra ID will be picked up and matched to the relevant connection based on their email address, for a seamless transition to Kinde. ## Before you begin - You need a Microsoft developer account to register an application. - Test the connection in a non-production environment before activating in a live environment. ## Advanced configurations Depending on your SAML set up, you may need to include advanced configurations for your connection. See [Advanced SAML configurations](/authenticate/enterprise-connections/advanced-saml-configurations/). ## Step 1: Add the connection in Kinde ### Add a connection for a specific organization 1. Go to **Organizations** and open the organization. 2. In the menu, select **Authentication**, then select **Add connection**. 3. In the **Add connection** window, select **New enterprise connection**, then click **Next**. 4. Select the Microsoft connection type you want and then select **Next**. Currently we support WS Federated and OpenID types. 5. Next: 'Step 2: Configure the connection'. ### Add a connection that can be shared across multiple organizations 1. Go to **Settings > Environment > Authentication**. 2. Scroll to the **Enterprise connection** section and select **Add connection**. The **Add connection** window opens. 3. Select the Microsoft connection type you want and then select **Next**. Currently we support WS Federated, SAML, and OpenID types. 4. Next: 'Step 2: Configure the connection'. ## Step 2: Configure the connection in Kinde 1. Enter a **Connection name.** Make this something you can easily identify, especially if you are adding multiple connections for different business customers. 2. For the **Entity ID**, enter a random string like `hEb876ZZlkg99Dwat64Mnbvyh129`. Make a copy of the string as you will add this to your SAML application later. Note that some older Entra ID tenants require the Entity ID to have a prefix of `spn:` If your connection fails, this could be why. 3. Enter the **IdP metadata URL**. This URL comes from your identity provider. If you don't know it, enter any URL and update this later. 4. Enter a **sign in URL** if your IdP requires a specific URL. ![optional fields for saml](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/4f1851db-5c34-496b-ced1-07c1cd272b00/public) 5. If you want, select the **Sign request algorithm** and **Protocol binding**. The options you choose will depend on what your identity provider prefers or requires. 6. Select a **Name ID** format. This helps identify and link user identities between your IdP and Kinde. 7. Enter an **Email key attribute**. This is the attribute in the SAML token that contains the user’s email. Setting this value ensures that the email address returned in the SAML response is correctly retrieved. We do not recommend leaving this field blank, but if you do we will set ‘email’ as the attribute. 8. (Optional) Add a first name and last name attribute. 9. Enter **Home realm domains**. This speeds up the sign in process for users of those domains. Note that all home realm domains must be unique across all connections in an environment. For more information, see [Home realm domains or IdP discovery](/authenticate/enterprise-connections/home-realm-discovery/). ![SAML configuration screen](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/dbdccca5-2e6c-4dd8-eaec-e029574daf00/public) 10. If you use home realm domains, the sign in button is hidden on the auth screen by default. To show the SSO button, select the **Always show sign-in button** option. 11. Copy the relevant reply URL: 1. If you don't use a custom domain, copy the **ACS URL**. 2. If you do use a custom domain, select the **Use custom domain instead** option and copy the custom domain URL. Later, add this URL to your identity provider configuration. ![ACS URL and custom domain option](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/885eda9c-ca4f-4340-db17-224023b8c300/public) 12. If you want to enable just-in-time (JIT) provisioning, select the **Create a user record in Kinde** option. This saves time adding users manually or via API later. 13. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 14. Enter any [upstream params](/authenticate/enterprise-connections/advanced-saml-configurations/#upstream-parameters) that you want to pass to the identity provider. Not all providers support this, so check their documentation first. 15. Select **Save**. ## Step 3: Create and configure an Entra ID enterprise application 1. On the [Microsoft Entra admin center](https://entra.microsoft.com/#home) home screen, select **Applications > Enterprise Applications**. 2. Select **New application** and in the next screen select **Create your own application**. A side panel opens. 3. Enter the name for the application. 4. Select the **Integrate any other application you don't find in the gallery (Non-gallery)** option and then select **Create**. It can take a few seconds for the application to be created. 5. Select **Get started** on the **2. Set up single sign on** tile, then select the SAML tile. 6. Edit the **Basic SAML Configuration**. The side panel opens. ![SAML config side panel](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/cb24d39d-07a8-4622-bf7f-2f8eeca1fb00/public) 7. Select **Add identifier**, then enter the same random string like you did previously for the Entity ID in Kinde. E.g. `hEb876ZZlkg99Dwat64Mnbvyh129`. 8. Select **Add reply URL** and paste the ACS URL that you copied from the connection configuration screen in Kinde, then select **Save**. 9. Close the panel. 10. Select **Edit** on the **Attributes & Claims** section. Copy the values of the identifiers (Principal name, Given name, Surname), for example: ![Example identifiers to copy](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/79037f34-5b20-443f-39ca-d3cb70e9b800/public) 11. In the **SAML certificates** section, copy the **App federation metadata URL**. You'll add this as the **IdP metadata URL** in the Kinde connection. 12. Download the Federation metadata XML file. This is the SAML signed certificate. ## Step 4: Finish configuring the connection in Kinde 1. Open the SAML connection in Kinde. Via **Organization > Authentication** or via **Settings > Authentication**. 2. Paste in the data you got from the SAML app: - IdP metadata URL 3. Update the attributes - Email key attribute (Email), such as `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress` - First name attribute (Given name), such as `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname` - Last name attribute (Surname), such as `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname` 4. (Optional) if you want to sign the SAML httpRequest: 1. Open the **Federation Metadata XML** file in a text editor. 2. Copy the certificate and private contents of the file to the Sign SAML request section. 5. Paste them into the **Signing certificate** field in the Kinde connection. 6. Switch on the connection. This will make it instantly available to users if this is your production environment. 1. For environment-level connections, scroll down and select the apps that will use the auth method. 2. For organization-level connections, scroll down and select if you want to switch this on for the org. 7. Select **Save**. ## Step 5: Test the connection Make sure you test the connection before enabling in production for your users. 1. Go to your test application and attempt to sign in. 2. If you left the **Home realm domains** field blank in Kinde, when you launch your application, you should see a button to sign in. Click it and go to step 4. 3. If you completed the **Home realm domains** field, you should be redirected immediately to your IdP sign in screen. 4. Enter your IdP details and complete any additional authentication required. ## Sign out behaviour for user session If your users sign in via the Entra ID (formerly Azure AD) enterprise connection in Kinde, when they sign out, they are just signing out of Kinde. They are not fully being signed out of Entra ID. It also works this way for social connections, where a third party is the identity provider. ## (Optional) Sync Entra ID groups with Kinde ### Add groups claim to MS Entra ID app 1. Open your application in the [MS Azure Portal](https://portal.azure.com/). 2. Go to **Token configuration** in the left menu. 3. Select **Add groups claim**. 4. In the window that appears, select the groups to be included in tokens. ![image of edit groups claim screen](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/fed278be-bdcd-43b6-7130-8c866928b700/public) 5. If you want, customize the token properties by type. 6. Save your changes. For reference, see this Microsoft doc about [configuring optional claims](https://learn.microsoft.com/en-us/entra/identity-platform/optional-claims?tabs=appui/) ### Customize ID token in Kinde 1. Open your application in Kinde. 2. Go to **Tokens**. 3. Scroll to **Token customization** and select **Configure** on the **ID tokens** tile. 4. Switch on **Social identity** as an additional claim. 5. Select **Save**. ### Access group info in tokens - ID token - `ext_provider > claims > profile > groups` - Access token - `ext_groups` + +# Authenticate - Enterprise connections - Home realm or IdP discovery + +> Guide to home realm discovery (HRD) for seamless enterprise authentication routing based on email domains and identity provider selection. + +home realm discovery, HRD, IdP discovery, email domain routing, enterprise auth, SSO button +authenticate + +Home realm discovery (HRD) provides a seamless sign-in experience for your enterprise auth users. When HRD is configured and a user sign in, Kinde checks which IdP or connection group a user belongs to, before authenticating them. It is also known as Identity Provider or IdP discovery. When HRD is set up in Kinde, users are authenticated based on the **Home Realm Domain** (email domain) that is entered. HRD is usually applied where your identity provider (IdP) is a third party, such as Microsoft Entra ID, Google, Cloudflare, etc, and you are using an enterprise or SAML auth setup. By default, Kinde provides a universal login page where users of any enterprise connection can sign in. They are then silently routed and verified via the relevant IdP. ## How it works When you set up a [Microsoft Entra ID](/authenticate/enterprise-connections/azure/) or [custom SAML](/authenticate/enterprise-connections/custom-saml/) connection, you’ll configure the home realm (or domains) to be recognized during authentication. All home realm domains must be unique across all connections in the environment. If HRD is not in place, the end-user must select the relevant log in button to be taken through to the right authentication URL. When you apply HRD in Kinde, the end-user is recognized and authenticated based on their email domain, without having to select or click anything. For example, you could configure two different connections as follows: - Email addresses ending with `enterpriseA.com` use SAML connection A - Email addresses ending with `enterpriseB.com` use Entra ID connection B In the back end, the end-user is linked to the correct identity provider via the connection, and they are silently authenticated. So when Jude Watson arrives at the sign in window and enters `judewatson@enterpriseA.com`, they are routed to the IdP for SAML connection A, and authenticated. ## Showing or hiding the sign in buttons Even if you have set up HRD, you can choose to show an SSO sign in button so the user has to click to proceed. Learn more [here](/authenticate/enterprise-connections/about-enterprise-connections/#show-or-hide-the-sso-sign-in-button-on-the-auth-page). + +# Authenticate - Enterprise connections - Use LastPass as a SAML identity provider + +> Step-by-step guide to integrating LastPass as a SAML identity provider with Kinde for enterprise authentication and access control. + +LastPass, SAML, identity provider, IdP, enterprise auth, SSO, access policies +authenticate + +If you use LastPass to centralize authentication and authorization in your business, you can integrate Kinde as a service provider for these processes. This gives you the benefits of Kinde’s robust auth capabilities, while keeping the familiar LastPass structure. ## Before you begin Here's what you need to do before you add the connection: - Sign up for a LastPass business account to add a LastPass application. - Generate a SAML Metadata XML file as LastPass does not support hosting this for you (more information below). ## Recommendations - Open the Kinde Enterprise connection in one browser tab, and the LastPass app configuration in another tab, as you will need to copy connection information across between them. - Set up and testing the connection in a non-production environment before making available to users. ## Advanced configurations Depending on your SAML set up, you may need to include advanced configurations for your connection. See [Advanced SAML configurations](/authenticate/enterprise-connections/advanced-saml-configurations/) ## Step 1: Add the connection in Kinde ### Add a connection for a specific organization 1. Go to **Organizations** and open the organization. 2. In the menu, select **Authentication**, then select **Add connection**. 3. In the **Add connection** window, select **New enterprise connection**, then click **Next**. 4. Select the LastPass connection and then select **Next**. 5. Next: 'Step 2: Configure the connection'. ### Add a connection that can be shared across multiple organizations 1. Go to **Settings > Environment > Authentication**. 2. Scroll to the **Enterprise connection** section and select **Add connection**. The **Add connection** window opens. 3. Select the LastPass connection and then select **Next**. 4. Next: 'Step 2: Configure the connection'. ## Step 2: Configure the connection 1. Enter a name for the connection. It should match the connection name in LastPass. 2. Enter a random string value for Entity ID, for e.g. `870sa9fbasfasdas23aghkhc12zasfnasd`. 3. Enter the **IdP metadata URL**. This URL comes from your identity provider. ![optional fields for saml](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/4f1851db-5c34-496b-ced1-07c1cd272b00/public) 4. Enter a **sign in URL** if your IdP requires a specific URL. 5. If you want, select the **Sign request algorithm** and **Protocol binding**. The options you choose will depend on what your identity provider prefers or requires. 6. Select `Email` as the **Name ID** format. This helps identify and link user identities between your IdP and Kinde. 7. Enter `emailAddress` as the **Email key attribute**. This is the attribute in the SAML token that contains the user’s email. Setting this value ensures that the email address returned in the SAML response is correctly retrieved. 8. (Optional) Add a first name and last name key attribute. This is not necessary for LastPass. ![Home realm domains in SAML configuration](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/dbdccca5-2e6c-4dd8-eaec-e029574daf00/public) 9. Enter any relevant **Home realm domains**. This is how SAML recognizes a user’s credentials and routes them to the correct sign in page. Note that home realm domains need to be unique across all connections in an environment. [Read more about home realm domains](/authenticate/enterprise-connections/home-realm-discovery/). 10. If you use home realm domains, the sign in button is hidden on the auth screen by default. To show the SSO button, select the **Always show sign-in button** option. ![ACS URL and custom domain option](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/885eda9c-ca4f-4340-db17-224023b8c300/public) 11. Copy the relevant reply URL: 1. If you don't use a custom domain, copy the **ACS URL**. 2. If you do use a custom domain, select the **Use custom domain instead** option and copy the custom domain URL. Later, add this URL to the LastPass configuration. 12. If you want to enable just-in-time (JIT) provisioning for users, select the **Create a user record in Kinde** option. This saves time adding users manually or via API later. ![Provisioning configuration for SAML](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/947baea7-bfd4-48b7-de2d-5b041b8c8300/public) 13. (Temporary feature) Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. 14. (Optional) In the **Sign SAML request** section, paste in the **Signed certificate** and **Private key**. You may have got these from your IdP or you may have generated yourself (see procedure above). 15. Enter any [upstream params](/authenticate/enterprise-connections/advanced-saml-configurations/#upstream-parameters) that you want to pass to the identity provider. Not all providers support this, so check their documentation first. 16. Select **Save**. ## Step 3: Add and configure your LastPass application View the [LastPass docs](https://support.lastpass.com/s/document-item?language=en_US&bundleId=lastpass&topicId=LastPass/uac_applications_sso_apps.html&_LANG=enus) for the full procedure. 1. Sign in to your LastPass business account. 2. In the menu, select **AdminConsole**. 3. Go to **Applications**, then select **SSO apps**. 4. Select **Search the catalogue**. A side panel slides out. ![Initialize SAML keys in LastPass](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/b11e3815-b261-4960-e4c3-6d26ce297800/public) 6. Follow the prompt to initialize SAML keys. This will take up to 15 minutes to process. 7. Refresh the page and select **Search the catalogue** again. The side panel slides out showing a list. 8. Scroll and select **Custom service**. 9. Select **Add a new domain** if prompted. The configuration panel opens. ![Add app name](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/c87f07cb-3284-4ddd-f346-7e8b2dfd8400/public) 10. Enter a **Name** and select which groups will be able to sign in using this SSO connection. 11. At the top of the **Configuration section** select **Export SAML IdP Metadata**. 12. Select Copy or download, then select **OK**. ![Configure application in LastPass](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/bf384b65-ff19-490d-974d-34d807519700/public) 13. In the **Service Provider entity ID** field, enter the random ID you generated for the **Entity ID** in Kinde. 14. In the **Assertion consumer service** field, enter the **ACS URL** or your custom domain, from Kinde. 15. Make sure the **Name ID format** is `emailAddress` and the **Name ID** is `Email address'. 16. Enter any custom attributes required. ![Custom attributes in LastPass](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/cd749576-b884-42e9-d7cb-caf6bca32400/public) 17. Select **View key** under the **Key field**. 18. Copy the key. You will need this to finishe setting up the Kinde connection. 19. Make sure the **Service is enabled** option is selected. 20. Select **Save**. ## Step 4: Finish setting up your LastPass connection in Kinde 1. Open the connection in Kinde. Go to **Organization > Authentication** or via **Settings > Authentication**. 2. In the **IdP metadata URL** field paste the **IDP Entity ID** you copied from LastPass. 3. In the **Sign-in URL** field paste the **Single Sign-on URL** you copied from LastPass. 4. In the **Signing certificate** field paste the **IDP Metadata XML** file content. [@Viv not sure about this - is this where hosting the certificate is advised??] 5. In the **Private key** field paste in the **Key** you copied from LastPass. 6. Switch on the connection. This will make it instantly available to users if this is your production environment. 1. For environment-level connections, scroll down and select the apps that will use the auth method. 2. For organization-level connections, scroll down and select if you want to switch this on for the org. Note that it will be automatically available for all apps if you choose this option. 7. Select **Save**. Test the connection works by trying to sign in to your test environment using this method. Re-test when you deploy the option to users. + +# Authenticate - Enterprise connections - Mapping and syncing users for enterprise auth + +> Guide to mapping and syncing users for enterprise authentication including user ID mapping, profile sync, and webhook integration. + +user mapping, user syncing, enterprise auth, webhooks, profile sync, user ID, API integration +authenticate + +When you use Kinde to authenticate users via an enterprise connection such as SAML, you also need a way for users to be identified in Kinde so they match the identities stored in your Identity Provider (IdP). In general, an email address can be used to map users across systems, but because enterprise connection users can have aliases and proxy addresses, there are better ways to keep identities in sync. Here’s how we recommend mapping user profiles and keeping them synced for enterprise connections. ## Map the Kinde user ID to your product When users are imported or added to Kinde, a unique user ID is generated. For example, `kp:1876b10742894a0c9M8e725048e7a323`. We recommend you map each user’s Kinde ID back to your product, and use this as the primary auth identifier. This will keep profiles in sync and support a seamless authentication experience. ### Get Kinde user IDs via API You can access user IDs [via the API](http://localhost:4321/kinde-apis/management#tag/users/post/api/v1/users/{user_id}/identities) by calling GET `/api/v1/users`. This will return a response with a users array with the following data: ```json { "code": "string", "message": "string", "users": [ { "id": "string", "provided_id": "string", "email": "string", "username": "string", "last_name": "string", "first_name": "string", "is_suspended": true, "picture": "string", "total_sign_ins": 0, "failed_sign_ins": 0, "last_signed_in": "string", "created_on": "string", "organizations": ["string"], "identities": [ { "type": "string", "identity": "string" } ] } ], "next_token": "string" } ``` Where: - `id` is the kinde ID - `provided_id` is the ID you may have provided when you imported your users. This ID can also be useful to match imported users to your local database records. ## Switch on profile sync As part of your business authentication setup, we recommend switching on user profile sync to keep enterprise and social profiles up to date across providers. 1. Go to **Settings > Policies**. 2. Switch on **Sync user profiles on sign in**. 3. Select **Save**. ## Sync users with webhooks Webhooks are a method of being notified when an event occurs in Kinde, e.g. a user is created. You can [register your own endpoint URLs](/integrate/webhooks/add-manage-webhooks/) in Kinde, and each time the event occurs, data for that event will be sent to your endpoint. Here’s some examples of webhook events that can be used to keep your users in sync: - `user.created` - when a user is created in Kinde either via the admin UI or registering - `user.updated` - when a user is added to an organization, or their roles or permissions change - `user.deleted` - when a user is deleted via the UI or via the API Here’s an example json schema for user.updated that could be used to sync your data: ```json { "id": "et_018df239698d29177684be3f5ad1266d", "code": "user.updated", "name": "User updated", "origin": "kinde", "schema": { "$id": "https://kinde.com/user.updated.schema.json", "type": "object", "title": "User Updated Webhook Event", "$schema": "https://json-schema.org/draft/2020-12/schema", "properties": { "data": { "type": "object", "properties": { "user": { "type": "object", "properties": { "id": { "type": "string", "pattern": "kp[:_][0-9a-f]{32}", "description": "ID of the user" }, "phone": { "type": ["null", "string"] }, "last_name": { "type": ["string", "null"], "description": "The users updated last name" }, "first_name": { "type": ["string", "null"], "description": "The users updated first name" }, "is_suspended": { "type": "boolean", "description": "The users updated status" }, "organizations": { "type": ["array", "null"], "items": [ { "type": "object", "properties": { "code": { "type": "string", "pattern": "org[:_][0-9a-f]{11}" }, "roles": { "type": ["array", "null"], "items": [ { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "key": { "type": "string" } } } ] }, "permissions": { "type": ["array", "null"], "items": [ { "type": "object", "properties": { "id": { "type": "string", "format": "uuid" }, "key": { "type": "string" } } } ] } } } ] }, "is_password_reset_requested": { "type": "boolean", "description": "The users updated password reset status" } }, "description": "User event data" } }, "description": "Webhook event data" }, "type": { "constant": "user.updated" }, "source": { "enum": ["api", "admin"], "description": "Source of the action" }, "event_id": { "type": "string", "pattern": "event_[0-9a-f]{32}", "description": "ID of the event" }, "timestamp": { "type": "string", "format": "date-time", "description": "Datetimestamp of the action" } }, "description": "Webhook detail the user updated event" }, "version": 1 } ``` You can see a full list of events in the Kinde UI under **Settings > Webhooks**, or by calling the [Kinde management API](/kinde-apis/management#tag/webhooks) which also provides the JSON schema GET `/api/v1/event_types`. Read more [about webhooks](/integrate/webhooks/about-webhooks/). + +# Authenticate - Enterprise connections - Use Okta as a SAML identity provider + +> Step-by-step guide to integrating Okta as a SAML identity provider with Kinde, including application setup and troubleshooting. + +Okta, SAML, identity provider, IdP, enterprise auth, SSO, application assignment +authenticate + +If you use Okta to centralize authentication and authorization in your business, you can integrate Kinde as a service provider for these processes. This gives you the benefits of Kinde’s robust auth capabilities, while keeping the familiar Okta structure. You need to set up an enterprise connection in Kinde for this, and add an Okta application. See steps below. ## Advanced configurations Depending on your SAML set up, you may need to include advanced configurations for your connection. See [Advanced SAML configurations](/authenticate/enterprise-connections/advanced-saml-configurations/). ## Step 1: Add an Okta connection in Kinde ### Add a connection for a specific organization 1. Go to **Organizations** and open the organization. 2. In the menu, select **Authentication**, then select **Add connection**. 3. In the **Add connection** window, select **New enterprise connection**, then click **Next**. 4. Select the Okta connection and then select **Next**. 5. Next: 'Step 2: Configure the connection'. ### Add a connection that can be shared across multiple organizations 1. Go to **Settings > Environment > Authentication**. 2. Scroll to the **Enterprise connection** section and select **Add connection**. The **Add connection** window opens. 3. Select the Okta connection and then select **Save**. 4. On the tile for the new connection, select **Configure**. 5. Next: 'Step 2: Configure the connection'. ## Step 2: Configure the connection 1. Enter a name for the connection. 2. Enter a random value for the **Entity ID**, e.g. `870sa9fbasfasdas23aghkhc12zasfnasd`. ![Okta connection config window](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/a06249d4-d368-43f7-bba1-9df10d80aa00/public) 3. Enter the **IdP metadata URL**. This URL comes from your identity provider. If you haven't set up your app yet, you can add this later. ![optional fields for saml](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/4f1851db-5c34-496b-ced1-07c1cd272b00/public) 4. Enter a **sign in URL** if your IdP requires a specific URL. 5. If you want, select the **Sign request algorithm** and **Protocol binding**. The options you choose will depend on what your identity provider prefers or requires. 6. Select a **Name ID** format. This helps identify and link user identities between your IdP and Kinde. 7. Enter an **Email key attribute**. This is the attribute in the SAML token that contains the user’s email. Setting this value ensures that the email address returned in the SAML response is correctly retrieved. We do not recommend leaving this field blank, but if you do we will set ‘email’ as the attribute. 8. (Optional) Add a first name and last name key attribute. ![Home realm domains in SAML configuration](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/dbdccca5-2e6c-4dd8-eaec-e029574daf00/public) 9. Enter any relevant **Home realm domains**. This is how SAML recognizes a user’s credentials and routes them to the correct sign in page. Note that home realm domains need to be unique across all connections in an environment. [Read more about home realm domains](/authenticate/enterprise-connections/home-realm-discovery/). 10. If you use home realm domains, the sign in button is hidden on the auth screen by default. To show the SSO button, select the **Always show sign-in button** option. ![ACS URL and custom domain option](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/885eda9c-ca4f-4340-db17-224023b8c300/public) 11. Copy the relevant reply URL: 1. If you don't use a custom domain, copy the **ACS URL**. 2. If you do use a custom domain, select the **Use custom domain instead** option and copy the custom domain URL. Later, add this URL to your identity provider configuration. 12. If you want to enable just-in-time (JIT) provisioning for users, select the **Create a user record in Kinde** option. This saves time adding users manually or via API later. ![Provisioning configuration for SAML](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/947baea7-bfd4-48b7-de2d-5b041b8c8300/public) 13. (Temporary feature) Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. 14. (Optional) In the **Sign SAML request** section, paste in the **Signed certificate** and **Private key**. You may have got these from your IdP or you may have generated yourself (see procedure above). 15. Enter any [upstream params](/authenticate/enterprise-connections/advanced-saml-configurations/#upstream-parameters) that you want to pass to the identity provider. Not all providers support this, so check their documentation first. 16. Select **Save**. ## Step 3: Add and configure your Okta application 1. Sign in to the Okta admin console. 2. Select **Applications > Applications**. ![Okta config window](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/63dee3f1-b0ba-4961-33e9-a8f928a07d00/public) 3. Select **Create App Integration**. The **Sign-in method** options opens. 4. Select SAML 2.0 and then select **Next**. The app’s general settings opens. ![Okta console](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/ff6393ec-43bb-4b25-e12c-26f7a05aa800/public) 5. Add a name in the **App name** field then select **Next**. The **Configure SAML** screen opens. ![Okta config screen](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/bb3bf35b-3322-433e-8224-5297a71da300/public) 6. In the **SAML settings** section, enter the following values: 1. **Single sign-on URL:** Paste the **Assertion Customer Service (ACS) URL** you copied from Kinde. 2. **Audience URI (SP Entity ID)**: Paste the **Entity ID** you copied from Kinde. 3. **Name ID format:** Select **EmailAddress**. 4. **Application username**: Select **Email**. 5. Leave all other options to their default value and select **Next**. 7. Select **Finish**. You will be redirected to the newly created application in Okta. 8. Select the **Sign on** tab and copy the metadata URL. ![Metadata URL in Okta](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/9bdcb215-054e-45c1-11a7-2df2f4be7800/public) ## Step 4: Finish setting up your SAML connection in Kinde 1. Open the connection in Kinde. Via Organization > Authentication or via Settings > Authentication. 2. Scroll to the **IdP metadata URL** field and paste the **Metadata URL** you copied from Okta. 3. Enter the signed certificate and key information if you have it. You can do this later as well. 4. Switch on the connection. This will make it instantly available to users if this is your production environment. 1. For environment-level connections, scroll down and select the apps that will use the auth method. 2. For organization-level connections, scroll down and select if you want to switch this on for the org. 5. Select **Save**. You can now use Okta as an IdP for the selected applications. ## Troubleshooting the connection If you get an error in Okta that says **User is not assigned to this application**, it means you need to assign a user or group to your Okta application. 1. Go to the **Applications** section in your Okta Admin Console. 2. Select the SAML 2.0 app you set up. 3. Under the **Assignments** tab, click **Assign > Assign to People or Assign to Groups**. 4. Choose the user or group you want to assign to this application and save your changes. + +# Authenticate - Enterprise connections - Provisioning users for enterprise connections + +> Comprehensive guide to user provisioning for enterprise connections including JIT provisioning, pre-provisioning, and troubleshooting SSO issues. + +user provisioning, JIT provisioning, enterprise connections, SSO, identity management, troubleshooting +authenticate + +When you set up Kinde with enterprise authentication like SAML or Cloudflare, you’ll want to make sure that users are set up with the correct access and identity from day one. How you do this depends on how you ‘provision’ their enterprise user identity. Users in Kinde are able to have multiple identities to support all the ways they can sign in, such as via email, social sign-in, etc. However, users managed through enterprise connections can only have an enterprise identity. ## Just-in-time (JIT) provisioning for user creation (recommended) JIT provisioning is the simplest way to add users to Kinde and allow them to authenticate. Rather than importing or pre-provisioning, your users are added to Kinde at the point of their first authentication. To enable JIT provisioning, select the **Create a user record in Kinde** option when you set up your enterprise connection. ![option for JIT in the enterprise connection screen](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/74717fdb-d6d2-4f0b-dcf6-2aef95cb7600/public) The first time the user authenticates, Kinde creates a new user record for them with the identity information passed from your IdP. ## Pre-provision or pre-create users Sometimes, JIT provisioning is not the right path or may not be possible. For example: - The user already exists in Kinde and you're switching the auth method to SSO. - You are importing users from another system and there is existing data related to the user you also wish to import. - You only want to add a sub-set of users from your directory. ### Add users to Kinde In all these cases, the users must first exist in Kinde to implement enterprise SSO. You can add users to Kinde [via import](/manage-users/add-and-edit/import-users-in-bulk/) or [via API](/kinde-apis/management#tag/users/post/api/v1/user). All users must have an email address that matches their email with the IdP. This is not necessarily the email identity for sign in, it is purely for initial matching against the IDP provided email. ### Provisioning method 1: Assign a connection identity to a user (recommended) This method of provisioning requires you to add the enterprise connection as part of the user’s identity in Kinde. **Add the enterprise connection identity via API** Post identity details to this endpoint `POST /api/v1/users/{user_id}/identities` with `enterprise` as the type and the `connection_id`. For more information, see [Create identity](https://docs.kinde.com/kinde-apis/management/#tag/users/post/api/v1/users/{user_id}/identities). You can search connections via API and filter them by domain. This can help you obtain the connection ID. **Add the enterprise connection identity manually** 1. Open a user’s profile and select **Add identity**. 2. In the window that appears, select **Enterprise SSO** as the **Identity type**. 3. Select the relevant **Enterprise connection** from the list. 4. Enter the user’s email as it appears in the identity provider directory. 5. Select **Save**. The user’s profile is updated to show only the enterprise connection identity. ### Provisioning method 2: Set the connection to trust emails from the IDP A slightly less secure option is to set the enterprise connection to trust emails from your IdP. This does save you adding and linking users as per method 1 above, but it also overrides any existing identity information in Kinde (such as email or phone number) with the connection data from the IdP. To employ this method, select the **Trust email addresses provided by this connection** option in the connection configuration. **Settings > Authentication > Enterprise connections > Configure.** ![Screen shot of trust emails switch](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/92f20fc4-7dcb-4ce1-9fb2-74b4db67e200/public) When the user signs in with an SSO connection that provides an email that matches the pre-provisioned users email, we will automatically combine the users. Their original email identity will be removed and from this point on they can only authenticate via the SSO connection. ## Troubleshoot SSO issues **We can’t find your account** If a user goes to sign in and encounters the ’We can’t find your account’ message, it could be because **Self-joining** for the organization is switched off. This is the right behaviour if you don’t want users without the `org_id` to join the org, but the message is confusing. Switch this on via **Organization > Policies**. **Duplicate identities** If duplicate identities are created for users in Kinde, it may because the **Trust email addresses provided by this connection** option is not switched on in the connection configuration. **Customer's SSO auth not working** Some B2B businesses allow their customers to sign in using their own enterprise SSO. When setting this up, a common mistake is that they supply incorrect values for the Client ID and Client Secret, based on the identity provider information. Double check these if you come across connection issues. + +# Authenticate - Enterprise connections - Refresh SAML certificate + +> Quick guide to refreshing SAML certificates and private keys for enterprise authentication security maintenance. + +SAML certificate, private key, certificate refresh, enterprise auth, security maintenance +authenticate + +If you secure your authentication setup with SAML certificate and private key, you’ll need to update or refresh these periodically. Your IdP might issue new certificates, or you can generate a certificate and private key yourself. See the [main SAML topic](/authenticate/enterprise-connections/custom-saml/#optional-signed-certificate-and-private-key). 1. In Kinde, go to **Settings > Authentication**. 2. In the **Enterprise connections** section, select **Configure** on the SAML tile. 3. Scroll to the **Sign SAML request** section and override the **Signing certificate** and **Private key** with the new certificate content. 4. Select **Save**. + +# Authenticate - Manage authentication - Change authentication for an application + +> Guide to configuring different authentication methods for different applications including mobile apps and platform-specific auth. + +application authentication, mobile auth, platform-specific auth, Google auth, Apple auth +authenticate + +If you want, you can select different authentication methods for different applications. You might want to do this, for example, so users sign in with Google for your Android app and Apple for your iOS app. You first need to [set up all your auth methods](/authenticate/authentication-methods/set-up-user-authentication/) and [set up each application](/build/applications/add-and-manage-applications/). 1. Go to **Settings > Environment > Applications**. 2. Select **View details** on the application you want to edit. 3. In the **Application details** screen, select **Authentication** in the left menu. 4. Use the toggle switches to change the authentication methods for the app. 5. If there is a method that you want that is not listed, [set it up](/authenticate/authentication-methods/set-up-user-authentication/). 6. When you’re finished, select **Save**. 7. Repeat for each application. + +# Authenticate - Manage authentication - Build a switch to navigate between organizations + +> Step-by-step guide to building an organization switcher for B2B applications using ID tokens and React components. + +organization switcher, B2B, ID tokens, React, multi-organization, org navigation +authenticate + +A common pattern in B2B products is for users who belong to multiple organizations to be able to switch between them. This topic demonstrates how to achieve this. ## Step 1: Add org data to ID tokens The first step is to include a list of organizations a user belongs to, in their ID token. 1. In Kinde, open the application you want to enable a switcher for. For example, go to **Settings > Applications > [View details] > Tokens.** 2. Scroll down to the **Token customization** section and select **Configure** on the **ID token** card. The **Customize ID token** window opens. 3. Select the **Organizations (array)** checkbox in the **Additional claims** section. 4. Select **Save**. This adds the organization `id` and `name` to the user’s ID token, in the following format: ```jsx "organizations": [ { "id": "org_4ba6821b521", "name": "Golden Finance" }, { "id": "org_b7226a3b5f0", "name": "UTM Bank" }, { "id": "org_16374a4fc3f", "name": "Trueblue Pty Ltd" } ] ``` You can now extract the `organizations` claim from ID tokens in the way you normally would. Typically the SDK you are using will have a method for this. For example, in React you could use: ```jsx const { getClaim } = useKindeAuth() getClaim('organizations', 'idToken').then((organizations) => { console.log('value:', organizations?.value) }) ``` ## Step 2: Build the switcher To build a simple list of orgs, use something like the following React example. You’ll need to include a call to the `login` method for each organization, passing in the id. In this example, we’ve also included a check to see if this is the current organization. ```jsx const { login, getClaim, getOrganization } = useKindeAuth() const [orgs, setOrgs] = useState<{ id: string; name: string }[]>([]) const [currentOrgCode, setCurrentOrgCode] = useState(null) useEffect(() => { getClaim('organizations', 'idToken').then((organizations) => { setOrgs(organizations?.value ?? []) }) getOrganization().then((org) => { setCurrentOrgCode(org) }) }, [getClaim, getOrganization])
    {orgs.map((item) => (
  • ))}
``` With some extra styling, a switcher might look something like this: + +# Authenticate - Manage authentication - Set custom authentication per organization + +> Guide to setting custom authentication methods per organization including shared connections and enterprise connections for B2B customers. + +organization authentication, custom auth, shared connections, enterprise connections, B2B auth +authenticate + + You can set different authentication methods for each organization you manage in Kinde. You might want to do this if your customers are businesses that require unique auth setups. ## Environment-level and organization-level auth methods Most authentication methods need to be [set up at the environment level](/authenticate/authentication-methods/set-up-user-authentication/), including social sign in and core mthods such as passwordless, phone auth, etc. These are known as 'Shared connections'. You might also have [organization-level enterprise connections](/authenticate/enterprise-connections/enterprise-connections-b2b/), which are unique to an organization. The way each of these connection types is managed, is very similar. ## Set authentication methods for an organization This procedure covers adding shared connections, but you can also [add enterprise connections directly to an organization](/authenticate/enterprise-connections/about-enterprise-connections/). 1. In Kinde, view details of the organization. 2. Select **Authentication** in the menu. 3. Activate the advanced features for this org, if you haven’t already. 4. Select **Add connection**. The **Add connection** window opens. 5. Select **Existing connection**, then select **Next**. A list of all existing connections appears. 6. Use the switches to enable and disable authentication methods for the organization. 7. When you’ve finished making changes, select **Save**. ## Disable authentication method for an organization If you remove an auth method for an organization, users can use any remaining methods to authenticate. If you remove all authentication methods, the organization will revert back to using the default auth set up from the environment level. 1. In Kinde, view details of the organization. 2. Select **Authentication** in the menu. 3. Select the three dots menu on the connection you want to remove, and select **Disable connection**. 4. A confirmation window opens. 5. Confirm that you want to disable the connection. For shared connections, the connection can be easily added back. For org-level enterprise connection, the connection can be re-enabled. + +# Authenticate - Manage authentication - Session management per organization + +> Guide to managing Kinde authenticated sessions at the organization level including session persistence and inactivity timeouts for enterprise customers. + +organization session management, SSO session, session cookies, inactivity timeout, enterprise auth +authenticate + + If you are on the Kinde Scale plan, you can change Kinde authenticated session configuration at the organization level as well as the environment level. An authenticated session (or SSO session) is the time during which a user is authenticated via Kinde, regardless of their activity. You can define if a session persists even after a browser is closed, and how long can lapse before making the organization's user re-authenticate. These settings only apply to Kinde sessions and not sessions you maintain through your own application. ## Limitations of Kinde session configuration - Session cookies are not destroyed when a tab is closed, the full browser window must be closed. - Modern browsers usually allow session restoration. Restoring a browser session can also restore a session cookie. ## Manage SSO session behaviors and policies per organization When you change session settings at the organization level, this overrides session settings at the environment level. 1. In Kinde, go to **Organizations** and open the organization whose session settings you want to configure. 2. Select **Sessions** in the side menu. 3. In the **SSO sessions** section, decide on the policy for session cookies. A persistent session leaves the cookie active when the browser is closed. A non-persistent session is terminated when the browser window closes (unless the limitations listed above apply). 4. In the **Session inactivity timeout** section, set how long a session can be inactive before prompting re-authentication. This setting is applied in seconds - where 3,600 seconds is one hour; 86,400 seconds is one day. 5. When you're finished, select **Save**. The session settings will now be applied to members of this organization. ## Manage organization session behavior via API Use this endpoint to update session settings [via API](https://docs.kinde.com/kinde-apis/management/#tag/organizations/patch/api/v1/organizations/{org_code}/sessions/). `PATCH /api/v1/organizations/{org_code}/sessions` + +# Authenticate - Manage authentication - Session management + +> Guide to managing Kinde authenticated sessions including session persistence, inactivity timeouts, and browser session behavior. + +session management, SSO session, session cookies, inactivity timeout, browser session +authenticate + +You can manage Kinde authenticated sessions via your application settings. An authenticated session (or SSO session) is the time during which a user is authenticated via Kinde, regardless of their activity. You can define if a session persists even after a browser is closed, and how long can lapse before making a user re-authenticate. These settings only apply to Kinde sessions and not sessions you maintain through your own application. If you want, you can [change session settings for an organization](/authenticate/manage-authentication/session-management-per-organization/), without affecting other organizations. ## Limitations - Session cookies are not destroyed when a tab is closed, the full browser window must be closed. - Modern browsers usually allow session restoration. Restoring a browser session can also restore a session cookie. ## Manage SSO session behaviors and policies 1. Go to **Settings > Environment > Applications.** 2. Select **View details** on the application tile. 3. Select **Sessions** in the side menu. 4. In the **SSO sessions** section, decide on the policy for session cookies. A persistent session leaves the cookie active when the browser is closed. A non-persistent session is terminated when the browser window closes (unless the limitations listed above apply). 5. In the **Session inactivity timeout** section, set how long a session can be inactive before prompting re-authentication. This setting is applied in seconds - where 3,600 seconds is one hour; 86,400 seconds is one day. 6. When you're finished, select **Save**. + +# Authenticate - Manage authentication - Sign users in to last organization + +> Guide to automatically signing users into their most recent organization instead of showing an organization switcher for improved UX. + +last organization, organization switcher, B2B, user experience, automatic sign-in +authenticate + +A common pattern in B2B products is for users who belong to multiple organizations, to be able to [switch between them](/authenticate/manage-authentication/navigate-between-organizations/). However, if you have a switcher in your application, you may want users to be signed in to the most recent organization instead. If you switch this function on, users will not be shown an organization switcher on the authentication screen, and instead will be signed in to the most recent organization. ## Sign users in to the last used organization 1. In Kinde, go to **Settings > Policies**. 2. In the **Sign in** section, select the **Sign users in to most recent org** option. 3. Select **Save**. + +# Authenticate - Manage authentication - Keep your product in sync with Kinde + +> Comprehensive guide to keeping your application in sync with Kinde using refresh tokens, API calls, and webhooks for real-time data consistency. + +sync with Kinde, refresh tokens, API integration, webhooks, token claims, real-time sync +authenticate + +Kinde’s main object delivery method is to include claims in ID and access tokens when a user authenticates. This is a very efficient delivery method because as soon as a user signs in, you have everything you need to give them access, including their permissions. A minor downside of relying on claims, is that tokens go stale and data can get out of sync, and users may not be able to see the updates you make until they are issued a new token. This is the classic ‘eventual consistency’ problem. If you make frequent updates to permissions, flags, or other objects, this is likely an issue for you and your users, and this topic will help. Here are some options. ## Sync using refresh tokens You can use [refresh tokens](/build/tokens/refresh-tokens/) to extend the longevity of an access token. A refresh token is a way to request a new access token, without disrupting a session. Most of our SDKs handle refreshing tokens for you automatically. ### Auto-updating of token claims For optimum performance our tokens are cached, so that when a new access token is issued it contains the same claims as the previous token. A token cache becomes invalid, however, when user information is updated in the UI or via API. This includes updates to profile information, organization membership, roles, permissions, properties, and user-level feature flags. So when you use a refresh token to renew the access token (and user info has been updated), the claims will also be updated. One way to minimize periods of inconsistency is to set a low value for the [access token lifetime](/build/tokens/configure-tokens/), to trigger a refresh token. ### Force-update of token claims There are events that do not trigger individual users tokens to be updated. These include: - Feature flag changes at an organization or environment level that are inherited by a user - Permissions added to a role that the user has For these type of changes you can force a token update using your backend to call the [Refresh User Claims](/kinde-apis/management#tag/users/post/api/v1/users/{user_id}/refresh_claims) endpoint of our Kinde management API. This invalidates the cache for a specific user and means the next time an access token is issued for that user the claims will reflect the current state in Kinde. ## Sync through the Kinde Management API You can use the Kinde management API to keep your product in sync with Kinde. Calls to the API are always real time, meaning you have a few sync options. ### Force a real-time update Even if you are using refresh tokens (above), there might be a few sensitive areas of your application where immediate consistency is vital, for example checking a permission for a payments flow. To deal with this, you could make a call to out to the permissions API when that flow is triggered. This gives you the additional security of real time data where it counts. ### Periodic polling Another option for syncing is to make an initial call to the API when your user logs in and store the claim information locally. Then, periodically poll the API to update your stored claim with a real-time response. This could be overkill for things that are not mission-critical, but might be useful for important areas like permissions. ### Refresh user claims endpoint As mentioned above, the [Refresh User Claims](/kinde-apis/management#tag/users/post/api/v1/users/{user_id}/refresh_claims) API endpoint can be used to invalidate the cache for a user, which will ensure they receive updated claims on the next token refresh. ## Webhooks Webhooks let you subscribe your own url endpoints to events, and receive updates as they occur. Events refer to activities that occur within your Kinde business, for example user creation, updates to users, etc. When an event occurs, such as `user.created`, Kinde sends all the event data to any subscribed endpoints. You can then trigger your own application code in response, or just maintain your own copy of the event data. Webhooks can be managed directly in the Kinde admin area, or by using the Kinde Management API Webhook endpoints. ### Webhook subscription events Call the `/api/v1/event_types` endpoint in the Kinde Management API to view the full list of available events and the schema for the data you receive. See the [webhooks documentation](/integrate/webhooks/about-webhooks/) for more information. + +# Authenticate - Manage authentication - Authenticated sessions across multiple applications + +> Guide to sharing authenticated sessions across multiple applications using SSO cookies, refresh tokens, and multi-domain authentication. + +multi-application sessions, SSO cookies, refresh tokens, offline scopes, multi-domain auth +authenticate + +Kinde supports shared authenticated sessions across applications. For example, in a scenario where you have multiple apps running on separate subdomains, and you want to share a session between apps without prompting the user to sign in again. ## Session cookies On the first sign in, Kinde creates an SSO cookie for the authenticated user. Until this cookie expires or you request that the user signs in again (using the [prompt parameter](/developer-tools/about/using-kinde-without-an-sdk/#prompt)), all your apps can initiate sign in requests without prompting. ## Offline scopes and refresh tokens If you include an `offline` scope in your request, you can maintain long-running sessions via refresh tokens. This works both in back-end apps and in web apps. Kinde supports short-lived refresh and refresh token rotation for increased security of browser-based and mobile apps. In this case, on page reload, the SDK will resume the session via the refresh token exchange. [About refresh tokens](/build/tokens/refresh-tokens/) See also [multi-domain authentication](/authenticate/about-auth/about-authentication/#multi-domain-authentication). ## Set up overview 1. Create two or more Kinde apps. 2. Enable the same authentication method for both apps. 3. In each app, create a link to the other app using the applicable `login` method. You might do this using an application switcher, for example. 4. Sign in to one app. 5. Select a link to sign in to the second app. You should be signed in to the second app without re-authentication. ## Example Say you are signed into your **Admin app** and want to switch to the **Employee app**. Here’s how it might look. As long as an authenticated session exists, users should be able to move seamlessly between applications. + +# Authenticate - Multi factor auth - About multi-factor authentication + +> Comprehensive overview of multi-factor authentication (MFA) including available factors, user experience, recovery codes, and organization-level enforcement. + +multi-factor authentication, MFA, authenticator app, SMS, email, recovery codes, security +authenticate + +To increase security for your product, you can enable multi-factor authentication (MFA). This means that your users sign in using at least two authentication methods, for example, password _plus_ verification code. If you don't want to apply MFA settings for all users, you can set [MFA per organization](/authenticate/multi-factor-auth/mfa-per-org/) if you're on the Kinde Scale plan. ## **Available MFA factors** Kinde supports the following secondary factors for MFA. - **Email** - users are sent a one-time-password (OTP) via email - **SMS** - users receive a one-time-password (OTP) via SMS - **Authenticator app** - users receive a verification code via an authentication app. You might recommend a specific app or allow users to choose. We recommend against choosing a secondary factor that is the same as the primary auth method. For example, if the primary method is email/passwordless, then choose SMS or Authenticator app as the secondary factor. ## **The MFA experience for users** If you make MFA optional, users will be prompted to opt in to MFA when they next sign in. If mandatory or after they opt in, users will be prompted to use (or choose) a secondary authentication method, through which they will receive a verification code. They will also be offered a set of recovery codes (See below). We suggest you advise users ahead of time if you are changing your sign-in requirements, and if you require them to download an authenticator app such as Google Authenticator. ### MFA **using an authenticator app** - On first time use, the user can scan a QR code to enable the verification method and get a verification code sent to their app of choice. - On subsequent sign in, a verification code will appear in their authenticator app of choice, or they can use a recovery code to sign in. ### MFA **using email verification** - A code is sent to their email that they need to enter into the verification code field on the sign up / sign in screen. ### MFA **using SMS verification** - A code is sent via SMS that the user must enter into the verification code field on the sign up / sign in screen. ## **Recovery codes** When a user signs in for the first time, or signs up as a new user (and MFA is activated), they will be offered a set of recovery codes that they can store for future use. They can then use a recovery code if they don’t have access to their device or authenticator app. ## MFA can be enforced for individual organizations Customers on the Kinde Scale plan are able to set MFA at the organization level. This is especially useful for B2B businesses who have many organizations, with varying auth requirements. See [Set MFA for an organization](/authenticate/multi-factor-auth/mfa-per-org/). + +# Authenticate - Multi factor auth - Enable multi-factor authentication + +> Step-by-step guide to enabling multi-factor authentication including mandatory and optional settings for enhanced security. + +enable MFA, multi-factor authentication, mandatory MFA, optional MFA, security setup +authenticate + +Add security to the authentication process by enabling multi-factor authentication (MFA). MFA means users sign in using at least two authentication factors, for example, password _plus_ SMS code. You can make MFA mandatory for users, or optional. Kinde supports the following secondary factors. - **Email** - users are sent a one-time-password (OTP) via email. - **SMS** - users receive a one-time-password (OTP) via SMS. - **Authenticator app** - users receive a verification code via an authentication app. We recommend against enabling a secondary factor that is the same as the primary auth method. ## **Set up MFA** When you set up MFA using this procedure, it will apply to all users in the environment. If you want, you can [enforce MFA for individual organizations](/authenticate/multi-factor-auth/mfa-per-org/), so it only affects users in that organization. 1. In Kinde, go to **Settings > Environment >** **Multi-factor auth**. 2. To make MFA mandatory, in the **Require multi-factor authentication** section, select **Yes**. Users will be required to set up MFA when they first sign up or next sign in. 3. To make MFA optional, in the **Require multi-factor authentication** section, select **Optional**. Users will have the option to set up MFA when they first sign up or next sign in. 4. Select the additional authentication options that you want to be available to your users. Such as an authenticator app, email, or SMS. 5. Select **Save**. Users will now be directed to use multi-factor authentication when they sign in. + +# Authenticate - Multi factor auth - Set multi-factor authentication for an organization + +> Advanced guide to setting multi-factor authentication per organization including role exemptions and enterprise connection exemptions for B2B customers. + +organization MFA, role exemptions, enterprise connections, B2B MFA, advanced org features +authenticate + + As part of being able to set unique authentication methods for an organization, you can also set how multi-factor authentication (MFA) works per organization. You might want to use MFA for some of your orgs, such as for business customers that require their users to have MFA as part of sign in. This is common in finance and government sectors. As part of this feature, you can: - exempt certain roles within the organization from having to use MFA. For example, you may only want Admins to use MFA. - exempt MFA authentication for certain enterprise connection types, such as SAML authentication. You might want to do this if MFA is already set up with the enterprise auth provider. ## Configure environment-level MFA settings If you do not want every organization in your business to use MFA, you must switch off the environment-level requirement. In Kinde, go to **Settings > Environment > Multi-factor auth**. ![Screen shot of Require MFA switches](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/78708a19-58c6-4cdd-a1e7-0c34c88dfb00/public) - Select **No** - If you want MFA to be applied in only some organizations or for some connections in your business. You will then need to set MFA in each organization separately. - Select **Yes** or **Optional** - If you want everyone, in every organization to use MFA’. Note that if you select **Yes** here, MFA will apply in all organizations regardless of what you set at the organization level. Whatever you select here, you can still exempt roles from MFA per organization. ## Switch on MFA for an organization MFA methods selected here will replace those selected at the environment level. 1. In Kinde, go to **Organizations**. 2. Browse or search for the organization. 3. In the list, select the organization to open the **Details** page. 4. Select **Multi-factor auth** in the menu. 5. If applicable, activate the advanced organization feature. 6. Toggle the **Enforce multi-factor authentication for this organization** switch on. 7. Select the authentication **Methods**. You can choose more than one. 8. Select **Save**. ## Add and remove exempt roles from MFA You need to have roles set up in Kinde. 1. In the **Exempt roles** section of the MFA page for the organization. 2. Select **Add exempt role** and select a role from the list. 3. Press **Enter**. 4. Repeat step 2 to add more roles. 5. You can remove an exempt role by selecting the three dots menu and selecting **Remove**. 6. Select **Save**. If a user has a mix of exempt and non-exempt roles, MFA will apply as default. ## Add and remove exempt enterprise connections from MFA You need to have enterprise connections set up in Kinde. 1. In the **Exempt enterprise connections** section of the MFA page for the organization. 2. Select **Add exempt enterprise connection** and select a connection from the list. 3. Press Enter. 4. Repeat step 2 to add more connections. 5. You can remove an exempt connection by selecting the three dots menu and selecting **Remove**. 6. Select **Save**. If a user signs in via Okta (exempt) and has an Admin role (not exempt), they will not be prompted for MFA. ## Switch off MFA for an organization This procedure only works if you have also switched off the environment-level setting for MFA. 1. In Kinde, go to **Organizations** and browse or search for the organization. 2. In the list, select the organization to open the **Details** page. 3. Select **Multi-factor auth** in the menu. 4. Toggle the **Enforce multi-factor authentication for this organization** switch off. 5. Select **Save**. + +# Authenticate - Social sign in - Add and manage social connections + +> Comprehensive guide to adding and managing social sign-in connections including setup, security considerations, and provider-specific configurations. + +social sign-in, social connections, OAuth, client ID, client secret, trusted providers +authenticate + +Social connections enable you to sign up and sign in users with credentials from their existing social accounts, such as Google or GitHub. An advantage of social sign in is that users don't have to create new credentials to use your app or service, making it more convenient and secure for them. If they have a gravatar picture associated with their social account, it will flow through to Kinde. ## Set up a social connection Follow the docs below for each social provider you want to use. This will give you the `Client ID` and `Client secret` (keys) you need to set up each auth method on the Kinde side. - [Apple](/authenticate/social-sign-in/apple/) - [Bitbucket](/authenticate/social-sign-in/bitbucket-sso/) - [Discord](/authenticate/social-sign-in/discord/) - [Facebook](/authenticate/social-sign-in/facebook/) - [GitHub](/authenticate/social-sign-in/github/) - [GitLab](/authenticate/social-sign-in/gitlab/) - [Google](/authenticate/social-sign-in/google/) - [LinkedIn](/authenticate/social-sign-in/linkedin/) - [Microsoft](/authenticate/social-sign-in/microsoft-sso/) - [Roblox](/authenticate/social-sign-in/roblox-sso/) - [Slack](/authenticate/social-sign-in/slack/) - [Twitch](/authenticate/social-sign-in/twitch/) - [Twitter](/authenticate/social-sign-in/twitter/) - [Xero](/authenticate/social-sign-in/xero-sso/) ### When an email is not provided Some social providers don't require an email for sign up, e.g. X. When a user signs up or in with one of these providers, Kinde will ask for an email (just once). This is so we can verify the user's identity and be sure it's a genuine sign up. We treat social identities different to email identities in Kinde, and record social providers as a social identity in their user profile. For more information, see [User identity and verification](/authenticate/about-auth/identity-and-verification/). ## Trusting emails from social providers There's no guarantee that the email kept on file with a social provider remains current. Because of this, Kinde does not automatically treat social provider emails as 'trusted', and therefore we do not automatically sync email profiles. When you add a social connection, you can choose whether to 'trust' provider emails for each connection type. For more information, see [User identity and verification](/authenticate/about-auth/identity-and-verification/#trusting-emails-from-providers). ## Delete a social connection 1. In Kinde, go to **Settings > Environment > Authentication**. 2. Scroll down to the **Social connections** section and select the three dots on the tile for the connection, then select **Delete connection**. 3. In the confirmation window, select **Delete connection**. ## Manage social connections via API You can [add, update, and delete social connections via the Kinde management API](/kinde-apis/management#tag/connections) using predefined endpoints. + +# Authenticate - Social sign in - Apple social sign in + +> Complete guide to setting up Apple social sign-in including Apple Developer account setup, Services ID configuration, and JWT client secret generation. + +Apple sign-in, Apple Developer, Services ID, JWT, client secret, private key, token renewal +authenticate + +You can enable users to sign up and sign in using their Apple credentials. It's also important to note that Apple limits the information it passes when users sign up this way. Avatars and profile pictures do not flow through to the auth experience in Kinde. The user's email may also be excluded, depending how they have their Apple ID set up. ## **What you need** - An [Apple Developer account](https://developer.apple.com/) including a subscription to the Apple developer program - Your Kinde callback URL (see below) - Some developer know-how ## **Copy the callback URL from Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. If you have not yet added the Apple connection, select **Add connection**, select **Apple**, then **Next**. 3. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the **Use custom domain instead** switch. 3. If you have only one custom domain, copy the **Custom domain** URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the provider app. 4. Select **Save**. 5. Use the copied Callback URLs to set up the app, see below. ## **Configure sign in for your app** ### **Set up your app** 1. In your Apple developer account, go to **Identifiers**. 2. Select the plus (+) icon next to **Identifiers**. 3. Select **App IDs**, then select **Continue**. 4. Select **App**, then select **Continue.** 5. Enter a description and Bundle ID. 6. In the **Capabilites** list, select **Sign in with Apple**. 7. Select **Register**. ### **Register** **services** 1. Select the plus icon (+) next to **Identifiers**. 2. Select **Services ID**, then select **Continue.** 3. Enter a description and identifier (make a note of this because it will be used as the Client ID). 4. Select **Register.** ### **Configure domains** 1. Click on the newly created service to edit. 2. Check the box to enable **Sign In with Apple** and click **Configure.** 3. In the **Domains and Subdomains** field, enter your Kinde URL, e.g. `yourdomain.kinde.com` (excluding the https:// protocol) 4. In the **Return URLs** field, enter your Kinde callback URL or custom domain callback URL, e.g. `https://yourdomain.kinde.com/login/callback`. 5. Add additional entries for all your organization custom domain callbacks, e.g. `account.customdomainone.com/login/callback`, `account.customdomaintwo.com/login/callback`, etc. 6. Select **Next**, then select **Done.** 7. In the **Edit your Services ID Configuration** window, select **Continue**, then select **Save.** ### **Set up keys** 1. Select **Keys** in the left hand menu and click the plus icon (+) next to the page title. 2. Enter a **Key Name**. 3. Select **Sign In with Apple** and next to this option, select **Configure**. 4. Select your app from the Primary App ID field, then select **Save.** 5. Select **Continue** then select **Register.** 6. Download your key as per the screen instructions. You will need this to generate the client secret. 7. When you have downloaded the key, select **Done**. ### **Generate the client secret** There are several ways to generate the client secret. An example is provided below. _**Example using Ruby**_ You can use open source libraries for creating and signing JWT tokens for your client secret (see [JWT.io](https://jwt.io/)). The below steps provide an example of accomplishing this using Ruby. 1. Install jwt using the following command: `gem install jwt`. 2. Create a file titled `client_secret.rb` and replace the empty values in your script as follows: - `key_file` is the p8 file containing your private key that you downloaded. - `team_id` can be found in the top right of your apple developer account under your name. - `client_id` is the identifier used for the service. - `key_id` was provided on the key creation screen. ```ruby require 'jwt' key_file = 'key.txt' team_id = '' client_id = '' key_id = '' ecdsa_key = OpenSSL::PKey::EC.new IO.read key_file headers = { 'kid' => key_id } claims = { 'iss' => team_id, 'iat' => Time.now.to_i, # Note that this is the maximum exp value of 6 months 'exp' => Time.now.to_i + 86400*180, 'aud' => 'https://appleid.apple.com', 'sub' => client_id, } token = JWT.encode claims, ecdsa_key, 'ES256', headers puts token ``` 3. Run the script with ruby `client_secret.rb` and copy the generated `client_secret`. 4. Add these credentials into Kinde. ## **Add credentials to Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. On the Apple tile, select **Configure**. 3. Paste the **Client ID** (Service ID) and **Client secret** (Private key) into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 6. Select which apps will use Apple sign in. 7. Select **Save**. Users will now see Apple as an option to sign up and sign in to your product. ## **Renew Apple token periodically** To continue to enable users to sign in with Apple, you will need to periodically renew the Apple token by generating a new client secret. Usually every six months. To do this, repeat the procedures from **Set up keys** to **Add credentials to Kinde**, above. ## **Third party references for this article** We do our best to test all our procedures, but sometimes third party companies change things without us knowing. Here’s the sources we used to create this article. - [Validating “Sign in with Apple” Authorization Code](https://p.agnihotry.com/post/validating_sign_in_with_apple_authorization_code/) - [Configuring your environment for Sign in with Apple](https://developer.apple.com/documentation/sign_in_with_apple/configuring_your_environment_for_sign_in_with_apple) - [Sign in with Apple REST API](https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api) - [Apple Developer Center](https://developer.apple.com/) + +# Authenticate - Social sign in - Bitbucket social sign in + +> Step-by-step guide to setting up Bitbucket social sign-in including Bitbucket app creation, OAuth configuration, and Kinde integration. + +Bitbucket sign-in, Bitbucket app, OAuth, client ID, client secret, callback URL, permissions +authenticate + +You can enable users to sign up and sign in using their Bitbucket credentials. To enable this, follow all the steps below to create a Bitbucket app and configure credentials in Kinde. ## **Get your Kinde callback URL** 1. In Kinde, go to **Settings** > **Authentication**. 2. In the **Social connections** section, select **Add connection.** 3. In the window that appears, select **Bitbucket,** then select **Next**. 4. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the Use custom domain instead switch. 3. If you have only one custom domain, copy the Custom domain URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the Bitbucket app. 5. Select **Save**. 6. Use the copied Callback URL to set up the app, see below. ## **Create and configure a Bitbucket app** 1. Create an account on [https://bitbucket.org/](https://bitbucket.org/). 2. Go to **Workspaces** if you are not automatically directed. 3. Create a workspace. 4. Enter a **Name** and **ID**. 5. Open **Settings** > **Apps and features** > **oauth consumers.** 6. Add a consumer. 7. Enter a name and add the callback URLs copied from your Kinde app. Add entries for all your organization custom domain callbacks, e.g. `account.customdomainone.com/login/callback`, `account.customdomaintwo.com/login/callback`, etc. 8. Under **Permissions**, in the **Account** section, select **email** and **read.** 9. Select **Save**. 10. Go back to **Apps and features** > **oauth consumers.** 11. Select the workspace you’ve just created and copy the key (client id) and secret (client secret) to paste into the kinde app. ## **Add Bitbucket app credentials to Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. On the **Bitbucket** tile, select **Configure**. 3. Paste the **Client ID** (key) and **Client secret** (secret) into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 6. Select which applications will allow Bitbucket social sign in. 7. Select **Save**. Users will now see Bitbucket as an option to sign up and sign in to the selected applications. + +# Authenticate - Social sign in - Discord social sign in + +> Step-by-step guide to setting up Discord social sign-in including Discord app creation, OAuth configuration, and Kinde integration. + +Discord sign-in, Discord app, OAuth, client ID, client secret, callback URL +authenticate + +You can enable users to sign up and sign in using their Discord credentials. To enable this, you’ll need a Discord app and some developer know-how. ## **Get your Kinde callback URL** 1. In Kinde, go to **Settings** > **Authentication**. 2. In the **Social connections** section, select **Add connection.** 3. In the window that appears, select **Discord,** then select **Next**. 4. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the Use custom domain instead switch. 3. If you have only one custom domain, copy the Custom domain URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the Discord app. 5. Select **Save**. 6. Use the copied Callback URL to set up the app, see below. ## Create and configure a Discord app 1. Log in to the [Discord developer site](https://discord.com/developers/applications/) and create a new app. 2. Give it a name and then go to **OAuth2** in the side menu. 3. In **OAuth2 > General**, copy the **Client ID** and **Client secret** somewhere you can access it later. If the client secret is not showing, select **Reset Secret**. 4. Paste in the **Callback URLs** (the ones you copied above), e.g. `https://yourdomain.kinde.com/login/callback`. Add entries for all your organization custom domain callbacks, e.g. `account.customdomainone.com/login/callback`, `account.customdomaintwo.com/login/callback`, etc. 5. Save your changes. ## **Add Discord credentials to Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. On the **Discord** tile, select **Configure**. 3. Paste the **Client ID** and **Client secret** from the Discord app into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 6. Select which applications will allow Discord social sign in. 7. Select **Save**. Users will now see Discord as an option to sign up and sign in to the selected applications. + +# Authenticate - Social sign in - Facebook social sign in + +> Comprehensive guide to setting up Facebook social sign-in including Meta app creation, OAuth configuration, and Kinde integration. + +Facebook sign-in, Meta app, OAuth, client ID, client secret, callback URL, Facebook Login for Business +authenticate + +You can enable users to sign up and sign in using their Facebook credentials. To enable this, you’ll need a Facebook app and some developer know-how. ## **Copy the callback URL from Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. If you have not yet added the Facebook social connection, select **Add connection** in the **Social authentication** section. 3. Select **Facebook**, then **Next**. 4. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the **Use custom domain instead** switch. 3. If you have only one custom domain, copy the Custom domain URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the Meta app. 5. Select **Save**. 6. Use the copied Callback URLs to set up the app, see below. ## **Create a Meta app** The following steps were correct when we published this, but third-party providers sometimes change things. [Here’s the Meta Developer docs](https://developers.facebook.com/docs/facebook-login/) in case you get stuck. 1. Go to the [Facebook/Meta developer space](https://developers.facebook.com/) and select **My apps**, then **Create app**. 2. On the **Business portfolio** page, select **Next**. 3. On the **Use cases** page, select **Authenticate and request data from users with Facebook Login** option and then select **Next.** 4. Follow the prompts and enter the app details, then select **Create app**. 5. In the confirmation window that appears, select **View dashboard**. 6. Under **App settings**, select **Basic** and copy the client ID and client Secret (labeled as **App ID** and **App Secret**) and paste them in a text file or somewhere you can easily copy them. ## **Configure the Meta app** The following steps were correct when we published this, but third party providers sometimes changes things. [Here’s the Meta Developer docs](https://developers.facebook.com/docs/facebook-login/) in case you get stuck. 1. In your Meta app dashboard, select **Use cases** then select **Configure** on the **Authentication and account creation** tile. 2. On the **Permissions** tab, make sure `email` and `public_profile` are selected. 3. On the **Settings** tab, add your callback URL in the **Redirect URI** field. E.g. `https://domain.kinde.com/login/callback` 4. Select **Save changes** at the bottom of the screen. 5. Go back to the Dashboard page (home icon). 6. In **App settings**, select **Basic**. 1. Paste your Kinde domain URL in the **App domains** field, but **do not** include the https/http or path. For example, paste `yourdomain.kinde.com`. 2. Add other details such as app icon, category, terms of service and privacy policy link. 3. Select **Save changes**. 7. Go to **Settings** > **Advanced.** 8. Under **Domain manager**, select **Add a domain** to add your Kinde domain. 1. When you add the domain here (include the https/http part of the URL). 2. Under the **Security** section, ensure the **Require app secret** switch is turned off. 3. Add any other relevant information. 4. Select **Save changes**. 9. Next, you'll need to complete the preparation tasks and submit your app for approval. Note that this requires providing business documentation, contacts, etc. See the **Review** area for more information. 10. Once the approval process is complete, you can publish the app. See the [Meta/Facebook docs](https://developers.facebook.com/docs/development/create-an-app/) for more information about apps. ## **Create a product in your Meta app** The following steps were correct when we published this, but third party providers sometimes changes things. [Here’s the Meta Developer docs](https://developers.facebook.com/docs/facebook-login/) in case you get stuck. 1. In your app dashboard, select **Add product**. 2. Select the **Opt in Facebook Login for Business** prompt**.** 3. When prompted, select **Switch to Facebook Login for business**. 4. In the confirmation window, select **Certain permissions aren’t available with this product** as the reason. 5. In the **Select the permissions you require** field that appears, select **email** and **public_profile**. 6. Select **Switch to Facebook Login**. 7. Enter the Kinde callback URLs in the **Valid OAuth Redirect URLs field**. Add entries for all your organization custom domain callbacks, e.g. account.customdomainone.com/login/callback, account.customdomaintwo.com/login/callback, etc. 8. Select **Save Changes**. 9. In the red warning message at the top of the page, select **Get Advanced Access**. The **Permissions and Features** page opens. 10. Next to the **email** entry: 1. Select **Request advanced access**. 2. In the confirmation window, select the checkbox and enter your facebook password. 3. Select **Submit**. 11. Next to the **public_profile** entry: 1. Select **Request advanced access**. 2. In the confirmation window, select the checkbox and enter your Facebook password. 3. Select **Submit**. ## **Add Facebook credentials to Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. On the **Facebook** tile, select **Configure**. 3. Paste the **Client ID** and **Client secret** from the Facebook app into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 6. Select which applications will allow Facebook SSO. 7. Select **Save**. Users will now see Facebook as an option to sign up and sign in to the selected applications. ### When an email is not provided Facebook does not require an email for sign up, but Kinde does. So if a user signs up with Facebook and an email is not detected, we will ask for one. The user only needs to provide their email once, then they can sign in via Facebook without disruption. If the email they provide is already detected in Kinde, we will automatically link the accounts so as not to duplicate. + +# Authenticate - Social sign in - GitHub social sign in + +> Step-by-step guide to setting up GitHub social sign-in including GitHub app creation, OAuth configuration, and Kinde integration. + +GitHub sign-in, GitHub app, OAuth, client ID, client secret, callback URL, webhooks +authenticate + +You can enable users to sign up and sign in using their GitHub credentials. To enable this, you’ll need some technical know-how and a [GitHub app](https://docs.github.com/en/apps/creating-github-apps/about-creating-github-apps/about-creating-github-apps) and credentials. ## **Get the Kinde callback URL** 1. In Kinde, go to **Settings** > **Authentication**. 2. In the **Social Connections** section, select **Add connection**. 3. In the window that appears, select **GitHub**, then select **Next**. 4. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the **Use custom domain instead** switch. 3. If you have only one custom domain, copy the Custom domain URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the provider app. 5. Select **Save**. 6. Use the copied Callback URL to set up the app, see below. ## **Create GitHub app** 1. Sign in to your GitHub account, select the **Account** dropdown menu at the top right corner, and choose **Settings**. 2. From the menu on the left, select **Developer settings**. ([https://github.com/settings/apps](https://github.com/settings/apps)) 3. Select **GitHub Apps** and then select **New GitHub app**. 4. Give the app a name. 5. Enter your app’s **Homepage URL**. 6. Enter or paste the Kinde callback URLs you copied earlier, into the **Authorization callback URL** field. Add entries for all your organization custom domain callbacks, e.g. account.customdomainone.com/login/callback, account.customdomaintwo.com/login/callback, etc. 7. Select the **Request user authorization (OAuth) during installation** option**.** 8. In the **Webhooks** section, deselect the Webhook **Active** option (unless you want to add webhook URL details). 9. (Recommended) In the **Permissions** section, open the **Account permissions** options and change the **Email addresses** access to **Read only**. This enables Kinde to more easily match up user accounts with access to all the users' email addresses. 10. Select **Create GitHub App**. The app is created. ## Copy Client ID and Client secret 1. On the App you just created, select **Edit**. 2. Copy the **Client ID.** 3. Select **Generate a new client secret**. 4. Copy these values to a text file or other temporary and secure place for adding to Kinde. ## **Add GitHub credentials to Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. On the GitHub tile, select **Configure**. 3. Paste the **Client ID** and **Client secret** into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 6. Select which applications will use GitHub sign in. 7. Select **Save**. Users will now see GitHub as an option to sign up and sign in to your product. + +# Authenticate - Social sign in - GitLab social sign in + +> Step-by-step guide to setting up GitLab social sign-in including GitLab app creation, OAuth configuration, and Kinde integration. + +GitLab sign-in, GitLab app, OAuth, client ID, client secret, callback URL, scopes +authenticate + +You can enable users to sign up and sign in using their GitLab credentials. To enable this, you’ll need some technical know-how and a GitLab app and credentials. Here’s some [GitLab docs](https://docs.gitlab.com/ee/integration/oauth_provider.html) that might help. ## **Get the Kinde callback URL** 1. In Kinde, go to **Settings** > **Authentication**. 2. In the **Social Connections** section, select **Add connection**. 3. In the window that appears, select **GitLab**, then select **Next**. 4. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the **Use custom domain instead** switch. 3. If you have only one custom domain, copy the Custom domain URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the GitLab app. 5. Select **Save**. 6. Use the copied Callback URL to set up the app, see below. ## **Create GitLab app** 1. Sign in to your GitLab account and follow [these instructions](https://docs.gitlab.com/ee/integration/oauth_provider.html) for adding a group-owned or user-owned application. 2. Ensure these scopes are enabled in your application: `read_user`, `openid`, `profile`, `email`. 3. Paste the Kinde callback URL in the **Redirect URI** field. Add additional entries for all your organization custom domain callbacks, e.g. `account.customdomainone.com/login/callback`, `account.customdomaintwo.com/login/callback`, etc. 4. Select **Save**. 5. Copy the **Application ID** and **Secret**, and paste them where you can access them later. ## **Add GitLab credentials to Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. On the GitLab tile, select **Configure**. 3. Paste the **Client ID** (**Application ID**) and **Client secret** (**Secret**) into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 6. Select which applications will have a GitLab sign in option. 7. Select **Save**. Users will now see GitLab as an option to sign up and sign in to your product. + +# Authenticate - Social sign in - Google social sign in + +> Step-by-step guide to setting up Google social sign-in including Google Cloud project setup, OAuth credentials, and Kinde integration. + +Google sign-in, OAuth, Google Cloud, client ID, client secret, callback URL, webview limitations +authenticate + +You can enable users to sign up and sign in using their Google credentials. To set this up, you need a Google cloud account and project, and a little technical know-how. Note that Google has provided a topic about [Google’s Create authorization credentials](https://developers.google.com/identity/sign-in/web/sign-in#create_authorization_credentials), but the steps don’t quite work. Until they update their docs, we recommend you use ours. ## **Before you begin** 1. Create a [Google Cloud](https://cloud.google.com/) account. 2. Create a [Google Project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#console). 3. Get Google credentials (see below). ### **Get the Kinde Callback URL** 1. Sign in to Kinde. 2. Go to the **Settings** page and select **Authentication**. 3. In the **Social connections** section, select **Add connection.** 4. In the window that opens, select **Google**, then select **Next**. 5. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the Kinde domain URL. 2. If you use custom domains, select the **Use custom domain instead** switch. 3. If you have only one custom domain, copy the Custom domain URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the Google app. 6. Select **Save**. 7. Use the copied Callback URL to set up the app, see below. ## **Get Google credentials** 1. Navigate to the [Google Cloud](https://cloud.google.com/) home page. 2. Click **Console** in the top menu bar. 3. In the left menu, select **APIs & Services.** 4. If you are prompted to, create a new project. 5. Select **OAuth consent** **screen.** 6. Select if your project is **Internal** or **External,** then select **Create**. 7. Complete all the app details (noting that you may need to go through the verification process if you upload a logo). 8. Select **Save** **and Continue**. 9. In the **Scopes** step, select **Add or remove scopes.** 10. In the screen that appears, add the following non-sensitive scopes: `./auth/userinfo.email` and `./auth/userinfo.profile` then select **Update**. 11. Select **Save and continue.** 12. Add test users if you want, then select **Save and continue**. 13. Back in the main menu, select **Credentials**. 14. Click **Create Credentials** at the top of the page and select **OAuth client ID**. 15. In the **Web application** dropdown menu, choose **Web Application**. 16. Name your OAuth 2.0 client. 17. Add your **Authorized redirect URIs**. These are the Callback URLs you copied in the previous procedure. Add entries for all your organization custom domain callbacks, e.g. `account.customdomainone.com/login/callback`, `account.customdomaintwo.com/login/callback`, etc. 18. Click **Create**. 19. Copy your **Client ID** and **Client Secret** from the confirmation window. ## **Add Google credentials to Kinde** 1. In Kinde, go to **Settings** and select **Authentication**. 2. On the Google tile, select the **Configure** link. 3. Paste your **Client ID** and **Client Secret** into the two fields. 4. Select if you want to treat this connection as a trusted provider (this is on by default for Google). A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. For example, you can pass a param that forces the Google account selector to display. 6. Select which applications to switch this on for. 7. Select **Save**. Your users will now be able to sign in using their Google credentials. + +# Authenticate - Social sign in - LinkedIn social sign in + +> Step-by-step guide to setting up LinkedIn social sign-in including LinkedIn app creation, OpenID Connect configuration, and Kinde integration. + +LinkedIn sign-in, OpenID Connect, OAuth, client ID, client secret, callback URL, LinkedIn developer +authenticate + +You can enable users to sign up and sign in using their LinkedIn credentials. To enable this, you’ll need a LinkedIn app and some developer know-how. ## **Get the Kinde Callback URL** 1. Sign in to Kinde. 2. Go to the **Settings** page and select **Authentication**. 3. In the **Social connections** section, select **Add connection.** 4. In the window that opens, select **LinkedIn**, then select **Next**. 5. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the Use custom domain instead switch. 3. If you have only one custom domain, copy the Custom domain URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the LinkedIn app. 6. Select **Save**. 7. Use the copied Callback URLs to set up the app, see below. ## **Create a LinkedIn app and set up** 1. Go to the [LinkedIn developer space](https://developer.linkedin.com/) and select **Create app**. 2. Complete the details, including name, logo, company LinkedIn page, privacy policy link, etc. 3. Select **Create app**. 4. In the **Products** tab, select **Request access** on the **Sign in with LinkedIn using OpenID Connect** tile. 5. In the dialog that opens, agree to the terms and conditions to continue. You can now view the endpoints. ## **Configure your LinkedIn app** 1. Go to the **Auth** tab. 2. In the **Auth 2.0 settings** area, select the edit icon next to the **Authorized redirect URLs for your app.** 3. Paste the **Callback URLs** you copied from Kinde in the first procedure. Add entries for all your organization custom domain callbacks, e.g. account.customdomainone.com/login/callback, account.customdomaintwo.com/login/callback, etc. 4. In the same tab, copy the **Client ID** and **Client Secret** and paste them in a text file or somewhere you can easily copy them. For additional help, see the [LinkedIn docs](https://learn.microsoft.com/en-gb/linkedin/consumer/integrations/self-serve/sign-in-with-linkedin). ## **Add LinkedIn credentials to Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. On the **LinkedIn** tile, select **Configure**. 3. Paste the **Client ID** and **Client secret** from the LinkedIn app into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 6. Select which applications will allow LinkedIn SSO. 7. Select **Save**. Users will now see LinkedIn as an option to sign up and sign in to the selected applications. + +# Authenticate - Social sign in - Microsoft social sign in + +> Step-by-step guide to setting up Microsoft social sign-in including Azure app registration, OAuth configuration, and Kinde integration. + +Microsoft sign-in, Azure, Entra ID, app registration, OAuth, client ID, client secret, home realm +authenticate + +You can enable users to sign up and sign in using their Microsoft credentials. To enable this, you’ll need a Microsoft Azure account and some developer know-how. ## **Get the Kinde Callback URL** 1. Sign in to Kinde. 2. Go to the **Settings** page and select **Authentication**. 3. In the **Social connections** section, select **Add connection.** 4. In the window that opens, select **Microsoft**, then select **Next**. 5. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the **Use custom domain instead** switch. 3. If you have only one custom domain, copy the Custom domain URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the Microsoft app. 6. Select **Save**. 7. Use the copied Callback URL to set up the app, see below. ## Register a Microsoft app and set up 1. Go to your account at [https://portal.azure.com/](https://portal.azure.com/). 2. Navigate to **Entra ID**. You can do this from links on the main screen or in the left side menu. 3. Select **Add+ > App registration** or go to **Manage > App registrations > New registration**. 4. Enter a name for the app. 5. Select a **Supported account types option**. In testing, we selected **Accounts in any organizational directory and personal Microsoft accounts**. 6. In the **Redirect URI (optional)** section, select **Web** in the **Select a platform** dropdown. 7. Enter the **Callback URL** from Kinde. The ones you copied in the procedure above. Add additional entries for all your organization custom domain callbacks, e.g. account.customdomainone.com/login/callback, account.customdomaintwo.com/login/callback, etc. 8. Select **Register**. Details of your new app appear. 9. Copy the **Application (client) ID** and paste it in a text file or somewhere you can easily access it again. 10. Select **Certificates and secrets** from the left menu, select + **New client secret.** 11. Enter a name and give it an expiry date (or accept the default), then select **Add**. Details of the secret are generated. 12. Copy the value in the **Value** column and paste it in a text file or somewhere you can easily access it again. Make sure you copy from the **Value** column, not the **Secret ID** column. ## Add Microsoft app credentials to Kinde 1. In Kinde, go to **Settings** > **Authentication**. 2. In the **Social connections** section, on the **Microsoft** tile, select **Configure**. 3. Paste the **Client ID** (Application (client) ID) and **Client secret value** (that you copied from the **Value** column at step 12 above) into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. When a user signs in with an email that matches an existing home realm domain (i.e. part of an enterprise connection), you can allow them to sign in using their existing credentials, rather than creating a new identity in Kinde. To make this happen automatically, select the **Auto redirect home realm users** option. 6. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 7. Select which applications will allow Microsoft social SSO. 8. Select **Save**. Users will now see Microsoft as an option to sign up and sign in to the selected applications. + +# Authenticate - Social sign in - Roblox social sign in + +> Step-by-step guide to setting up Roblox social sign-in including Roblox app creation, OAuth configuration, and Kinde integration. + +Roblox sign-in, Roblox app, OAuth, client ID, client secret, callback URL +authenticate + +You can enable users to sign up and sign in using their Roblox credentials. To enable this, you’ll need some technical know-how and a Roblox app. ## Get your Kinde callback URL 1. In Kinde, go to **Settings** > **Authentication**. 2. In the **Social connections** section, select **Add connection.** 3. In the window that appears, select **Roblox,** then select **Next**. 4. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the **Use custom domain instead** switch. 3. If you have only one custom domain, copy the **Custom domain** URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the Roblox app. 5. Select **Save**. 6. Use the copied Callback URLs to set up the app, see below. ## Create and configure a Roblox app 1. Sign up for a [Roblox](https://www.roblox.com/) account. 2. Follow [these instructions](https://create.roblox.com/docs/cloud/open-cloud/oauth2-registration/) to create an OAuth 2.0 app in Roblox. 3. Make sure you enable the `open id` and `profile` scopes. 4. Copy the app **Client ID** and **Secret**. You need these to set up Roblox in Kinde. ## Add Roblox credentials to Kinde You don’t need to wait for app approval to finish configuring Roblox in Kinde. 1. In Kinde, go to **Settings** > **Authentication**. 2. On the **Roblox** tile, select **Configure**. 3. Paste the **Client ID** and **Secret** from the Roblox app into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they provide is verified. We recommend leaving this off for maximum security. Depending on your selection, here’s the behaviour in Kinde: - trusted off + existing email - creates new user, only updates people_profiles - trusted off + new email - creates new email identity (adds to people_identities) - trusted on + existing email - merges accounts w/existing user - trusted on + new email - creates new email identity (adds to people_identities) 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 6. Select which applications will allow Roblox social sign in. 7. Select **Save**. Users will now see Roblox as an option to sign up and sign in to the selected applications. + +# Authenticate - Social sign in - Slack social sign in + +> Step-by-step guide to setting up Slack social sign-in including Slack app creation, OAuth configuration, and Kinde integration. + +Slack sign-in, Slack app, OAuth, client ID, client secret, callback URL, scopes +authenticate + +You can enable users to sign up and sign in using their Slack credentials. To enable this, you’ll need some technical know-how and a Slack app. ## **Copy the callback URL from Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. If you have not yet added the Slack social connection, select **Add connection** in the **Social authentication** section. 3. Select Slack, then **Next**. 4. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the Use custom domain instead switch. 3. If you have only one custom domain, copy the Custom domain URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the Slack app. 5. Select **Save**. 6. Use the copied Callback URL to set up the app, see below. ## **Create a Slack app** 1. Go to [Slack API Applications](https://api.slack.com/apps) and log in to your workspace. 2. Select **Create an App**. The **Create an app** window opens. 3. Choose how you’d like to configure your app’s scopes and settings. 4. If you are not sure, choose the **From scratch** option. 5. Enter your **App Name** and **Select a workspace**. 6. Click **Create App**. Your app is created. 7. Scroll to the **App Credentials** section and copy the **Client ID** and **Client Secret** and paste them in a text file or somewhere you can easily copy them. ### **Configure your Slack app** 1. In your Slack app, go to the **OAuth & Permissions** section. 2. Scroll to the **Redirect URLs** area and add the callback URLs you got from Kinde, then select **Save URLs**. Add additional entries for all your organization custom domain callbacks, e.g. account.customdomainone.com/login/callback, account.customdomaintwo.com/login/callback, etc. 3. To define what info will be shared when a user signs up or signs in with Slack, scroll to the **Scopes** section. 4. In the **User Token Scopes** area, select **Add an OAuth Scope** and from the dropdown menu choose **users.profile:read**. 5. Scroll up to the **OAuth Tokens for Your Workspace** section and select **Install to Workspace**. And when prompted, select **Allow**. 6. Select **Manage distribution** on the left and go to the **Share Your App with Other Workspaces** section. 7. Select **Remove Hard Coded Information** and in the area that appears, select the **I’ve reviewed and removed any hard-coded information** option. 8. Select **Activate Public Distribution**. Your app is now ready to use. ### **Add Slack credentials to Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. On the Slack tile, select **Configure**. 3. Paste the **Client ID** and **Client secret** from the Slack app into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 6. Select which applications will allow Slack SSO. 7. Select **Save**. Users will now see Slack as an option to sign up and sign in to the selected applications. + +# Authenticate - Social sign in - Twitch social sign in + +> Step-by-step guide to setting up Twitch social sign-in including Twitch app registration, OAuth configuration, and Kinde integration. + +Twitch sign-in, Twitch app, OAuth, client ID, client secret, callback URL, 2FA +authenticate + +You can enable users to sign up and sign in using their Twitch credentials. To enable this, you’ll need a Twitch account and some developer know-how. ## **Before you begin** **Enable Twitch 2FA** — Sign up for a Twitch account and [enable two-factor authentication](https://help.twitch.tv/s/article/two-factor-authentication?language=en_US) (2FA). You will need your mobile number and an authenticator app e.g. Google authenticator, to do this. ## **Get the Kinde callback URL** 1. In Kinde, go to **Settings** > **Authentication**. 2. In the **Social authentication** section, select **Add connection.** 3. Select **Twitch** and then select **Next.** 4. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the **Use custom domain instead** option. 3. If you have only one custom domain, copy the Custom domain URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the Twitch app. 5. Select **Save**. 6. Use the copied Callback URLs to set up the app, see below. ## **Register a Twitch app** 1. Go to the [Twitch developer console](https://dev.twitch.tv/) and select **Applications**. 2. Select **Register your application**. 3. Enter a name and the Kinde callback URLs you copied above. Add entries for all your organization custom domain callbacks, e.g. `account.customdomainone.com/login/callback`, `account.customdomaintwo.com/login/callback`, etc. 4. Select the **Category** as an **Application Integration**. 5. Select **Create**. See the [Twitch docs](https://dev.twitch.tv/docs/authentication/register-app#registering-your-app) for additional help. ## **Get app Client ID and Client secret** 1. In the **Application** section in Twitch, select **Manage** next to your application. 2. Copy the **Client ID.** 3. Select **New secret** and when prompted, confirm. 4. Copy and paste the **Client ID** and **Client Secret** into a text file or somewhere you can easily copy them. ## **Add Twitch credentials to Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. On the Twitch tile, select **Configure**. 3. Paste the **Client ID** and **Client secret** from the app into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 6. Select which applications will allow Twitch SSO. 7. Select **Save**. Users will now see Twitch as an option to sign up and sign in to the selected applications. ## When an email is not provided Twitch does not require an email for sign up, but Kinde does. So if a user signs up with Twitch and an email is not detected, we will ask for one. The user only needs to provide their email once, then they can sign in via Twitch without disruption. If the email they provide is already detected in Kinde, we will automatically link the accounts so as not to duplicate. + +# Authenticate - Social sign in - X (formerly Twitter) social sign in + +> Step-by-step guide to setting up X (formerly Twitter) social sign-in including X developer platform app creation, OAuth configuration, and Kinde integration. + +X sign-in, Twitter sign-in, X developer platform, OAuth, client ID, client secret, callback URL +authenticate + +You can enable users to sign up and sign in using their X credentials. To enable this, you’ll need an X developer platform account and some developer know-how. ## **Create an X app** Sign up for a X developer platform account and [add your app](https://developer.twitter.com/en/portal/dashboard). If you are signing up for the first time, you will be given a default app. If you already have apps, you’ll need to create a project and then add the new app within that project. ## **Get the Kinde callback URL** 1. In Kinde, go to **Settings** > **Authentication**. 2. In the Social connections section, select **Add connection.** 3. In the window that appears, select **X**, then select **Next**. 4. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the **Use custom domain instead** switch. 3. If you have only one custom domain, copy the **Custom domain** URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the X app. 5. Select **Save**. 6. Use the copied Callback URL to set up the app, see below. ## **Set up your X app** 1. Sign in to the [X Developer Platform](https://developer.twitter.com/). 2. In the side menu, select **Projects & apps** and then select your app. 3. In the **User authentication settings** section, select **Set up**. 4. Set the **App Permissions.** 5. Switch on **Request email from users.** 6. Select the **Type of App** as **Native app**. 7. Enter the Kinde callback URL you copied earlier. Add entries for all your organization custom domain callbacks, e.g. `account.customdomainone.com/login/callback`, `account.customdomaintwo.com/login/callback`, etc. 8. Enter your Kinde domain URL, e.g. `https://yourdomain.kinde.com`. 9. Enter details in other fields if you wish. 10. Select **Save**. 11. Select the **Key and tokens** tab at the top of the page. 12. Copy the **Client ID** and **Client Secret** from the **Oauth2.0** section and paste them into a text doc or other place where you can get them again later. View **X Developer Platform’s** docs for more info about [authentication](https://developer.twitter.com/en/docs/authentication/overview). ## **Add X credentials to Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. In the list of **Social connections**, select **Configure** on the **X** tile. 3. Paste the **Client ID** and **Client secret** from the X app into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 6. Select which applications will allow users to sign in with X. 7. Select **Save**. Users will now see X as an option to sign up and sign in to the selected applications. ## When an email is not provided X does not require an email for sign up, but Kinde does. So if a user signs up with X and an email is not detected, we will ask for one. The user only needs to provide their email once, then they can sign in via X without disruption. If the email they provide is already detected in Kinde, we will automatically link the accounts so as not to duplicate. + +# Authenticate - Social sign in - Xero social sign in + +> Step-by-step guide to setting up Xero social sign-in including Xero app creation, OAuth configuration, and Kinde integration. + +Xero sign-in, Xero app, OAuth, client ID, client secret, callback URL +authenticate + +You can enable users to sign up and sign in using their Xero credentials. To enable this, you’ll need a Xero app and some developer know-how. ## **Get your Kinde callback URL** 1. In Kinde, go to **Settings** > **Authentication**. 2. In the **Social connections** section, select **Add connection.** 3. In the window that appears, select **Xero,** then select **Next**. 4. In the **Callback URL** section: 1. If you use Kinde’s domain as your default, copy the **Kinde domain** URL. 2. If you use custom domains, select the **Use custom domain instead** switch. 3. If you have only one custom domain, copy the **Custom domain** URL. If you have custom domains for multiple organizations, select each one from the list and copy the callbacks for each. You need to enter all custom domain callbacks in the Xero app. 5. Select **Save**. 6. Use the copied Callback URLs to set up the app, see below. ## **Create and configure a Xero app** 1. Create a Xero developer account. [https://developer.xero.com/](https://developer.xero.com/) 2. Verify your email when prompted. 3. Select New app. 4. Give the app a name and select Web app as the type. 5. Add your company URL. 6. Enter your Kinde callback URL in the **Redirect URI** field. Add additional entries for all your organization custom domain callbacks, e.g. `account.customdomainone.com/login/callback`, `account.customdomaintwo.com/login/callback`, etc. 7. Accept the terms and conditions and select **Create App**. 8. Go to **Configuration** and copy the **Client id** somewhere you can access it later. 9. Generate a **Client secret** and copy it immediately somewhere you can access it again. You will not get to copy it again. ## **Add Xero credentials to Kinde** 1. In Kinde, go to **Settings** > **Authentication**. 2. On the **Xero** tile, select **Configure**. 3. Paste the **Client ID** and **Client secret** from the Xero app into the relevant fields. 4. Select if you want to treat this connection as a trusted provider. A [trusted provider](/authenticate/about-auth/identity-and-verification/) is one that guarantees the email they issue is verified. We recommend leaving this off for maximum security. 5. Add any [upstream params](/authenticate/auth-guides/pass-params-idp/) that you want to pass to the IdP. 6. Select which applications will allow Xero social sign in. 7. Select **Save**. Users will now see Xero as an option to sign up and sign in to the selected applications. + diff --git a/public/_llms-txt/billing.txt b/public/_llms-txt/billing.txt new file mode 100644 index 000000000..ef16a0d55 --- /dev/null +++ b/public/_llms-txt/billing.txt @@ -0,0 +1,278 @@ +--- +page_id: 0c1d2e3f-4a5b-6c7d-8e9f-0a1b2c3d4e5f +title: Kinde Documentation - Billing +description: "Complete documentation for Kinde's billing section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section for LLM training" +sidebar: + order: 1 +topics: + - llm + - documentation + - training + - billing +sdk: [] +languages: + - markdown + - text +audience: developers +complexity: beginner +keywords: + - llm training + - documentation + - billing + - section + - frontmatter + - metadata + - kinde +updated: 2025-09-18 +featured: false +deprecated: false +ai_summary: "Complete documentation for Kinde's billing section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section for LLM training" +--- + +# Kinde Documentation - Billing + +This is the complete documentation for Kinde's billing section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section. + +# Billing - About billing - About billing + +> Overview of Kinde billing capabilities including plan management, pricing tables, payment processing, and customer lifecycle management. + +billing, plans, pricing, Stripe, customer lifecycle, revenue, subscriptions +billing + +Kinde billing gives you the ability to charge customers for your services and collect revenue. As part of using this feature, you can: - Create and manage plans, and make them visible to your customers - Create and customize a pricing table for plan selection - Implement specific pricing models to suit your product - Use Stripe for secure handling of payments and invoicing - Link organizations (B2B) and individual customers (B2C) to a plan - Handle plan upgrade, downgrade, and cancellation - Enable self-serve account management for customers - Customize the pricing table to make the whole experience on-brand Billing makes the Kinde platform _the_ essential development infrastructure for managing the customer lifecycle across every part of your business. From registration to plan selection, authorization to provisioning, releases to upgrades. ## This is our first billing release Billing is a really complex area of app development, so while this release is tested and ready, we are actively working on improvements from day one. ### How to send feedback It would be amazing if you can send any feedback you have [support@kinde.com](mailto:support@kinde.com) so we can quickly collect and prioritize improvements. ## Known limitations These are current limitations that we are aware of and are working on adding. - Support for plan models with free trial periods - Annual and quarterly subscriptions. Only monthly is available right now. - Changes to the billing cycle (e.g. choose billing anniversaries, etc.) - Add-ons and discounts that can be applied to individual subscriptions + +# Billing - About billing - Billing concepts & terms + +> Comprehensive guide to billing concepts and terminology including plan groups, features, pricing models, and common billing terms. + +billing concepts, plan groups, features, pricing models, metered usage, fixed charges, multi-currency +billing + +'Billing' refers to the broad function of creating plans, setting pricing, collecting payments, etc. Here are some of the common concepts and terms you will come across. ## Billing identifiers - **Customer ID** - A `customer_id` uniquely identifies a user or org who has signed up to a plan. This is different to a `user_id` or `org_id` that identifies the user or org as an entity. - **Customer Agreement ID** - A `customer_agreement_id` identifies the contract or agreement created in Stripe when a plan is signed up to. The agreement ID is then associated with the `customer_id` in Kinde. ## Key concepts - **Plan groups** - Plan groups organize multiple plans under a common category, helping segment offerings by use case, customer size, or market. A group is scoped to either organizations (B2B) or individual customers (B2C). You can have multiple plan groups, but each plan must belong to a group. - **Plans** - Plans define the specific features, usage limits, and pricing tiers offered to customers in a SaaS product. - **Features** - Plan features are the specific capabilities or entitlements included in a plan. They can be chargeable (incurring additional fees) or non-chargeable (included at no extra cost). Features can be metered (usage-based) or unmetered (fixed access). - **Fixed charges**- Single chargeable items like the subscription base price and other stand alone recurring charges. - **Pricing models** - Pricing models are the different methods of charging customers, such as flat-rate, usage-based, tiered, per-seat pricing, etc. Your pricing model is determined by your product and customer needs. Consider scalability and longevity when deciding this. - **Payments processor** - A payments processor is a third-party service that securely processes customer payments via credit cards, ACH, or other methods - such as Stripe Billing. - **Pricing table** - A pricing table is a visual representation of your different subscription plans, showcasing features and prices to help users compare options. You can build one in Kinde and then show it to your customers in the auth flow or self-service portal. - **Self-serve account portal** - Kinde provides a self-serve portal. This allows customers to manage their subscriptions—such as upgrading plans, updating payment information, or cancelling. This reduces support overhead and improves user autonomy. In Kinde, you can decide what your customers can self-manage or remove the functionality completely. ## Common billing terms - **Agreement** - the term used in Stripe and the Kinde API to refer to a customer's subscription. Both terms are used throughout docs. - **Base price** – The starting cost of a subscription plan, typically the cost for a core set of features or a minimum level of usage. - **Chargeable / Non-chargeable feature** – - **Chargeable feature**: Incurs an additional fee when used. Might be metered or per unit price. - **Non-chargeable feature**: Add non-chargeable features for any included features which aren't independently chargeable, but need to be gated in your product. - **Feature** – A specific function or capability of your SaaS product that you provision for app users. In context with a plan, these are chargeable or non-chargeable features that are provisioned to customers. - **Fixed charge** – A recurring fee that does not change based on usage, often applied monthly or annually. Use this for a plan’s base price or other flat recurring fees. - **Metered and unmetered feature** – Metered features are provisioned in units, often with pricing per unit, e.g. MAU. An unmetered feature is like a boolean, and is a basic feature with no pricing attached. - **Multi-currency** – The ability to set plan prices in different currencies to support global customers. Kinde supports nearly all currencies, but you can currently only pick one as the default for all plans. - **Plan** – A packaged offering of features, prices, and terms available for subscription, typically tiered across a group (e.g., Basic, Pro, Enterprise). - **Plan group** – A collection of related plans, often grouped by customer type or usage level, allowing easier management and comparison. - **Pricing model** – The structure used to determine how features in a plan are priced. E.g. fixed charge, tiered, per-user, or usage-based pricing. Kinde lets you use multiple pricing models within one plan. - **Subscription** – The ongoing agreement where a customer pays for access to a SaaS product via a recurring plan. This is referred to as an agreement in Stripe. - **Tiered pricing** – This refers to unit pricing that has different unit costs based on the volume of units purchased. E.g. $10 per unit for 1–10 units, $8 per unit for 11–50 units, $5 per unit over 51 units. - **Unit price** – Where a price is set per unit of usage, e.g. a seat or license. Unit prices can also be applied to metered features, e.g. x per unit. Unit prices can also be tiered, e.g. x per unit up to 10 units, then y for 10+ units. - **Usage-based** **price** – A billing method where charges vary based on the metered consumption of resources or services (e.g., API calls, storage). + +# Billing - About billing - Top questions about Kinde billing + +> A collection of the top questions and answers about how to set up and configure Kinde billing for your Kinde business. + +billing, plans, plan selector, entitlements, feature charges, pricing models, MAU, Stripe +billing, plans, plan selector, entitlements, feature charges, pricing models, MAU, Stripe + +Here are short answers to the most common billing questions. Click any question to expand the answer. ## Core billing functionality in Kinde
How do I choose the right Kinde billing pricing model for my SaaS customers? Think about how your customers actually use your product and what they value most. If you're selling a tool where usage varies dramatically - like API calls or storage - go with usage-based pricing so customers only pay for what they consume. For products where value comes from access to features rather than consumption, subscription pricing makes more sense. Kinde lets you mix these models within a single plan, so you could have a $20 base subscription plus $0.10 per extra API call. Start simple with one model and add complexity as you grow - your customers will thank you for not overwhelming them upfront. [Explore pricing models](/billing/pricing/pricing-models/) | [About billing concepts](/billing/about-billing/billing-concepts-terms/)
What's the difference between Kinde's metered and unmetered features in plans? Metered features are the ones you can put a number on - monthly active users, API calls, storage gigabytes, support hours. These can be chargeable (customers pay per unit) or non-chargeable (included in their plan up to a limit). Unmetered features are more like switches - either customers have access to your advanced analytics dashboard or they don't. Think of metered features as "how much" and unmetered as "yes or no." Most SaaS businesses use a mix of both to create clear upgrade paths without making pricing too complicated. [About plans and features](/billing/manage-plans/about-plans/) | [Billing concepts guide](/billing/about-billing/billing-concepts-terms/)
How do Kinde plan groups help me organize billing for different customer types? Plan groups are how you separate B2B and B2C offerings without creating a mess. Each group is tied to either individual users or organizations, never both. So you might have a "Professional" group with individual plans for freelancers and consultants, and a separate "Enterprise" group with team-based pricing for companies. You can create multiple pricing tables from one group, but each table can only show plans from a single group. This keeps your offerings clean and makes it easier for customers to find the right fit. [Plan groups management](/billing/manage-plans/about-plans/) | [Billing concepts](/billing/about-billing/billing-concepts-terms/)
Why should I use Kinde's billing features instead of building my own payment system? Unless you're excited about spending months building subscription management, dunning logic, proration calculations, and tax compliance - spoiler alert: you're probably not - Kinde's billing saves you from that headache. We handle the messy bits like Stripe integration, plan upgrades, usage tracking, and invoice generation, so you can focus on building features your customers actually care about. Plus, you get a self-serve portal out of the box, which means fewer support tickets about billing issues. [About billing plans](/billing/manage-plans/about-plans/) | [Self-serve portal setup](/build/self-service-portal/self-serve-portal-for-orgs/)
How does Kinde handle the technical complexity of subscription billing? We abstract away the most technical parts. Once you connect to Stripe (we create a new account for you automatically), everything syncs seamlessly. Plan changes, usage tracking, proration, invoice generation - it all happens behind the scenes. Your customers get a smooth experience upgrading or downgrading, and you can set up webhook notifications when important billing events happen. The only thing you need to worry about is building great features and deciding how to price them. [Stripe integration guide](/billing/get-started/connect-to-stripe/) | [About billing plans](/billing/manage-plans/about-plans/)
What happens when I publish a plan versus keeping it in draft, in Kinde? Draft plans are your work in progress - you can tweak pricing, add features, change everything without affecting anyone. Once you publish a plan, it syncs to Stripe and becomes available for actual customers to subscribe to. Here's the catch: once someone subscribes to a published plan, you can't change it anymore, only version it (though plan versioning isn't available yet). This protects your existing customers from surprise pricing changes, but it means you need to think things through before hitting publish. [About plans lifecycle](/billing/manage-plans/about-plans/) | [Billing concepts](/billing/about-billing/billing-concepts-terms/)
## Stripe integration
Why does Kinde create a new Stripe account instead of connecting to my existing one? This is actually a Stripe requirement for third-party integrations like ours, not something we chose. They want to ensure security and compliance by controlling how connected accounts are set up. The good news? You can transfer your existing business information during the Stripe onboarding process, so you're not starting from scratch. We're working on a migration strategy to make this smoother, but for now, the new account approach keeps everyone secure and compliant. [Stripe connection setup](/billing/get-started/connect-to-stripe/) | [Manage Stripe connection](/billing/payment-management/manage-stripe-connection/)
What should I tell customers when my Kinde–Stripe connection shows "In progress" status? Don't worry - this just means Stripe needs a bit more information from you to complete the setup. Usually it's business details like contact information, tax info, or identity verification (they might ask for ID upload). The connection won't work for live payments until this is sorted, so customers won't be able to subscribe to paid plans yet. Jump into your Stripe dashboard through the "Update Stripe information" button in Kinde to see what's missing. Once everything's complete, the status should change to "Connected" and you're good to go. [Stripe connection troubleshooting](/billing/payment-management/manage-stripe-connection/) | [Connect to Stripe guide](/billing/get-started/connect-to-stripe/)
How do I test Kinde billing without charging real money? Switch to your non-production environment in Kinde - this automatically creates a test Stripe account that won't process real payments. You can create plans, test the whole customer journey, even simulate failed payments, all without touching real credit cards. This is perfect for making sure your billing flow works before going live. Just remember to switch back to your production environment when you're ready to accept real payments. [Stripe integration setup](/billing/get-started/connect-to-stripe/) | [About billing plans](/billing/manage-plans/about-plans/)
## Plan management
How should I structure Kinde billing plans to make upgrading feel natural for customers? Create a clear progression where each plan builds on the previous one. Start with a generous free plan that gives users real value, then add features and remove limits as they upgrade. Instead of completely different feature sets, use metered features to give everyone a "taste" - maybe 100 API calls on Free, 1,000 on Pro, unlimited on Enterprise. This way upgrades feel like growth, not switching to something completely different. Keep plan names simple and descriptive - "Starter," "Professional," "Enterprise" beats "Bronze," "Silver," "Gold" every time. [About pricing models](/billing/pricing/pricing-models/) | [Plan management guide](/billing/manage-plans/about-plans/)
What's the best way to handle Kinde plan features that some customers need but others don't? This is where unmetered features shine. Instead of cramming every possible feature into every plan, gate advanced capabilities behind higher tiers. Use unmetered features as "gates" - advanced reporting might only be available on Business plans, while API access could be Professional and up. For features with variable usage, use metered features with different limits per plan. This way customers self-select into the right plan based on what they actually need, and you avoid feature bloat in your lower tiers. [Feature planning strategy](/billing/manage-plans/about-plans/) | [Billing concepts](/billing/about-billing/billing-concepts-terms/)
How do I explain Kinde's tiered pricing to customers who are confused about usage charges? Be upfront about how the math works and give concrete examples. If you charge $0.50 for the first 10 API calls, then $0.30 for calls 11-50, show them: "If you make 25 API calls, you pay $5 for the first 10, then $4.50 for the next 15 = $9.50 total." Most customers appreciate transparency over surprises. Consider setting reasonable limits on lower plans instead of unlimited usage-based charging - it makes budgeting easier for them and upgrade paths clearer for you. Mke sure your pricing table is descriptive and clear about metered or package prices. This can be tricky. [Pricing models explained](/billing/pricing/pricing-models/) | [Build a pricing table](/billing/billing-user-experience/plan-selection/)
What should I consider when setting Kinde plan upgrade and downgrade policies? Think about what's fair for both you and your customers. By default, Kinde forgives unpaid usage when customers downgrade and doesn't refund unused subscription days - this is pretty industry standard and avoids messy proration calculations. But you can change these policies if needed. For example, if someone on your $100/month plan cancels mid-month, you might choose not to refund the remaining days but also not charge them for any metered usage that month. Find the balance that feels fair and stick with it consistently. [Plan policies configuration](/billing/manage-plans/upgrade-downgrade-plans/) | [Billing setup guide](/billing/get-started/connect-to-stripe/)
## User experience
How do I create Kinde pricing tables that actually convert visitors into customers? Less is more when it comes to pricing tables. Stick to your 3-4 core plans (Free, Pro, Business works great), highlight which plan is most popular, and focus on benefits rather than features. Use the custom features section to highlight your best selling points for each plan, and don't just copy your technical feature list. Test different approaches, but remember - confused customers don't buy anything. If your product is complex or has a lot of features, you might want to create a custom designed table. [Build effective pricing tables](/billing/billing-user-experience/plan-selection/) | [Pricing table customization](/billing/billing-user-experience/plan-selection/)
Should I show Kinde pricing tables during the signup flow or after users experience my product? Depends on your product and customer type. For simple tools where the value is obvious upfront, showing pricing during signup can work well - especially if you have a generous free tier. For complex products where users need to understand the value first, let them sign up and experience your product before presenting upgrade options. You can control this in Kinde by toggling the "Show pricing table when customers sign up" option. Test both approaches if you're unsure - the data will tell you what works for your audience. [Pricing table display options](/billing/billing-user-experience/pricing-table-display/) | [Billing integration guide](/billing/billing-user-experience/plan-selection/)
How do I handle customers who need custom pricing that doesn't fit Kinde's standard plans? Start by trying to fit them into your existing plans with some creative metered feature limits - you'd be surprised how often this works. If they truly need something custom, you can manually adjust metered usage for specific customers through the Kinde API after they subscribe. For true enterprise deals with annual contracts or bank transfers, those arrangements are available but you'll need to work with Kinde's enterprise team. Most customers who think they need custom pricing actually just need a slightly modified version of your top tier. [API billing management](/billing/manage-plans/about-plans/) | [Enterprise billing options](/manage-your-account/profile-and-plan/change-kinde-plan/)
## Self-serve portal
How does Kinde's self-serve portal reduce my customer support workload? Think of it as your billing support team that never sleeps. Customers can update their payment details, view billing history, upgrade plans, and manage organization settings without creating support tickets. You control exactly what they can self-manage - maybe you want them handling payment updates but prefer to manage plan changes yourself. The portal generates one-time secure links, so you can add "Manage Billing" buttons throughout your app that take users directly to the right section. Less support tickets means more time building features that matter. [Self-serve portal setup](/build/self-service-portal/self-serve-portal-for-orgs/) | [Portal configuration options](/build/self-service-portal/self-serve-portal-for-orgs/)
What permissions should I give organization members via Kinde's self-serve portal feature? It's better to start with more restrictions and expand, than start with too many that you might have to remove. Most organizations want their admins to manage payment details and view billing history, but you might not want every team member changing subscription plans. Kinde provides some pre-defined roles with varying portal access - so that the right people can change the right things. The permissions map directly to Kinde's system permissions like `org:write:billing`, so you can be granular about who can do what. [Portal permissions setup](/build/self-service-portal/self-serve-portal-for-orgs/).
How do I generate Kinde self-serve portal links for use in my app? You've got two options depending on your setup. If you're using Kinde for authentication, use the SDK to generate portal links on the fly - perfect for "Account Settings" buttons in your app. If you're handling auth yourself or need server-side generation, hit the Kinde Management API with an M2M token. You can specify which section of the portal to open (billing, profile, etc.) and where to redirect users when they're done. The links are one-time use for security, so generate them fresh each time. [Portal link generation](/build/self-service-portal/self-serve-portal-for-orgs/) | [Management API integration](/build/self-service-portal/self-serve-portal-for-orgs/)
## Integration and development
How do I sync Kinde billing data with my application's feature access controls? Use the Account API to check what features and usage limits a signed-in user has access to. The API returns billing entitlements along with roles and permissions, so you can gate features based on their current plan. For organization-level billing data (which is more sensitive), use the Management API instead. Set up webhooks for billing events like plan changes or usage updates, so your app stays in sync automatically. Don't try to cache billing data for too long - things change, and you want accurate limits. [Account API for billing](/developer-tools/account-api/about-account-api/) | [Billing webhooks](/integrate/webhooks/about-webhooks/)
How should I handle Kinde billing webhook events in my application? Set up dedicated API endpoints to receive billing webhooks and verify the JWT signatures - this is how you know the requests actually come from Kinde. Handle key events like subscription changes, payment failures, and usage updates to keep your app in sync. Always respond with a 200 status code when you successfully process a webhook, or Kinde will keep retrying with backoff logic. Use the webhook request ID as an idempotency key to avoid processing the same event twice if there are retries. [Webhook implementation](/integrate/webhooks/about-webhooks/) | [Webhook setup guide](/integrate/webhooks/add-manage-webhooks/)
How do I implement Kinde billing URLs and parameters for seamless user experiences? Use URL parameters to direct customers to specific plans or pricing tables when they're ready to upgrade. For example, `?plan=pro_monthly` can take them straight to your Pro plan signup. This is super useful for email campaigns, in-app upgrade prompts, or landing pages. You can also override which pricing table displays using parameters, so different marketing campaigns can show different plan combinations. The SDK handles most of this automatically, but manual URL construction gives you more control. [Billing URL integration](/billing/billing-user-experience/plan-selection/) | [Pricing table configuration](/billing/billing-user-experience/plan-selection/)
## Troubleshooting and support
Why aren't the plan prices I set up in Kinde syncing with Stripe? If you see "price not synced" status, it usually means the plan isn't published yet - only published plans sync to Stripe. Mixed sync status (some features synced, others not) typically happens when some features are already in a published plan while others are new additions. Try publishing or re-publishing the plan to trigger a sync. If it's still not working, check that your Stripe connection status shows "Connected" rather than "In progress" or "Connecting." [Plan publishing process](/billing/manage-plans/about-plans/) | [Stripe connection status](/billing/payment-management/manage-stripe-connection/)
What should I do when customers report billing discrepancies? Start by checking the billing history in their organization's portal - this shows exactly what they were charged and when. Look for things like mid-month plan changes (which can cause proration), metered usage overages, or failed payment retries. Most "billing errors" are actually just confusing timing - customers might see charges for last month's usage appearing on this month's invoice. If you genuinely find an error, Kinde's support team can help resolve it, but having the billing details handy speeds things up. [Billing history access](/manage-your-account/profile-and-plan/view-kinde-plan/) | [Support resources](/build/self-service-portal/self-serve-portal-for-orgs/)
What are some of Kinde's billing limitations and when might these be fixed? Currently, Kinde only supports monthly billing (no annual), doesn't have free trial periods built-in, and plan versioning isn't ready yet. For customers who need annual billing, you could manually create annual plans with different pricing. For free trials, you could start them on a free plan and set up automated emails to encourage upgrades. Give us feedback about your billing experience with Kinde by reporting bugs and making feature suggestions. We genuinely are listening. [Current billing limitations](/billing/manage-plans/about-plans/) | [Alternative approaches](/billing/pricing/pricing-models/)
## Best practices
What's the smartest way to launch Kinde billing for an existing SaaS product with users? Start by setting up your billing plans and pricing tables in a non-production environment to get everything perfect. Create a grandfathering strategy for existing users - maybe they keep their current access levels for a certain period before needing to choose a plan. When you're ready to go live, communicate the changes clearly with plenty of notice. Consider starting with just new signups on the new billing system, then migrating existing users in batches. This gives you time to iron out any issues without affecting your entire user base at once. [Billing setup strategy](/billing/get-started/connect-to-stripe/) | [Plan management](/billing/manage-plans/about-plans/)
How should I price Kinde metered features to encourage growth while staying profitable? Pricing decisions can be really hard. Start with generous free tiers that let customers experience real value, then use usage limits to create natural upgrade triggers. If your app gets more valuable with heavier usage, price metered features aggressively low or even free up to reasonable limits. The goal is to make customers successful enough that upgrading feels like a no-brainer rather than a burden. Watch your unit economics closely - some features cost you more to provide than others, so price accordingly. [Metered pricing strategies](/billing/pricing/pricing-models/) | [Feature management](/billing/manage-plans/about-plans/)
What's the most effective way to use Kinde billing data to reduce customer churn? Set up webhooks for payment failures and usage pattern changes, then create automated workflows to reach out before customers hit walls. If someone's approaching their usage limits, send them upgrade prompts with specific benefits rather than just warnings. Use billing data to identify your best customers (high usage, consistent payments) and make sure they're getting white-glove treatment. Failed payments aren't always churn signals - sometimes cards expire or customers need payment method updates. [Billing webhooks setup](/integrate/webhooks/about-webhooks/) | [Usage tracking](/billing/manage-plans/about-plans/)
How do I structure Kinde plans to minimize customer confusion while maximizing revenue? Keep it simple with clear value differences between tiers. Three to four plans usually hit the sweet spot - more than that and customers get paralyzed by choice. Use the "good, better, best" psychology: make your middle plan the obvious choice by giving it the best value ratio. Include some metered features as "freebies" in higher plans to justify the price jump. And please, test your pricing table with real humans before launching - what seems obvious to you might be confusing to customers who see it fresh. [Pricing table best practices](/billing/billing-user-experience/plan-selection/) | [Plan strategy guide](/billing/pricing/pricing-models/)
+ +# Billing - About billing - The Kinde billing model + +> Detailed explanation of the Kinde billing model including Stripe integration, B2B/B2C support, multi-currency, and billing cycles. + +Kinde billing model, Stripe integration, B2B, B2C, B2B2C, multi-currency, billing cycles, payment processing +billing + +In the Kinde model, we handle everything except the payment processing part of billing. Kinde integrates with a third-party payment processor (Stripe) for secure payment processing. This involves a continuous sync between Kinde and Stripe, to ensure that products, prices, subscription information, invoices and payments, are accurate in both systems. Kinde does not store payment details, such as credit card information. This is exclusively managed by Stripe. ## Billing for B2B, B2C and B2B2C Kinde supports billing models for B2B, B2C and even B2B2C. Depending which you are setting up, you may need to do a few different tasks. Most of the setup is common, but we will call out tasks that are only relevant to one or the other. - B2B - customers are companies, organizations, or groups. - B2C - customers are individual users. - B2B2C - the platform model, where you have a customer who is an organization, and then users who are customers of that organization. ## Kinde and Stripe Kinde integrates a single payment processor (only Stripe Billing for now) to handle the financial and payment management side of things. Stripe uses the plan data and the customer info to create an agreement in Stripe. The customer is invoiced based on this agreement. Stripe securely stores your customer’s payment details and Kinde never sees credit card or other bank information. Here’s what the billing feature looks like as a workflow. ![Plan purchase workflow](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/b9a7bc9a-8f32-4a6d-fe4c-799db02c1600/public) Stripe is currently the only payment provider supported with Kinde. But we plan to expand to other providers in the near future. ## Multi-currency support Kinde has customers everywhere and almost every global currency is supported. ## Transaction data and Stripe region - When you connect your Stripe account to Kinde, you connect to our Stripe US account. We do this because Stripe US more widely supports global functionality. - Regardless of your own Stripe account region, you can still select any currency for your plans in Kinde, and Stripe will do the hard part of exchange rate conversion, tax calculations, etc. - Any fees you incur in Stripe for international transactions are your sole responsibility. ## Billing and invoice cycles By default, Kinde uses the following billing behavior, though some aspects can be customized depending on how you configure cancellations. - Billing cycles are monthly, based on the customer's original sign-up date. - Fixed charges (e.g. monthly subscription fees) are billed in advance, customers pay at the start of their billing period. - Metered (usage-based) charges are billed in arrears, usage is tracked throughout the billing period, and charges appear on the next invoice. You can also [set policies](/billing/get-started/setup-overview/) to control what happens when a customer cancels or changes their plan. + +# Billing - Billing user experience - Update code and URLs for billing + +> Guide to integrating billing into your application using URL parameters, React SDK components, and authentication flows. + +billing integration, URL parameters, React SDK, plan selection, pricing table, org signup, B2B +billing + +This topic explains how to customize billing flows with Kinde, including URL parameters, direct auth URLs, and SDK usage in React. Examples are given in React, but can be adapted for most frameworks. ## Edit the auth URL parameters directly Here’s a standard Kinde auth URL: ``` https://.kinde.com/oauth2/auth ?response_type=code &client_id= &redirect_uri= &scope=openid%20profile%20email &state=abc ``` Add these parameters as needed: | Parameter | Description | | --- | --- | | `plan_interest` | Pre-selects a plan (skips plan selection) | | `pricing_table_key` | Displays a specific pricing table | | `is_create_org` | Triggers org sign-up flow | ### Examples - Pre-select a plan: ``` ...&plan_interest=pro_monthly ``` - Show specific pricing: ``` ...&pricing_table_key=spring_promo ``` - Org sign-up: ``` ...&is_create_org=true ``` ## Integrate billing using the React SDK You can avoid manual URL construction by using our SDK components. Here's how. **User sign-up (default):** ```jsx Sign up ``` **Org sign-up (B2B):** ```jsx Sign up your organization ``` **Pre-select a user plan:** ```jsx Sign up with Pro plan ``` **Show a specific pricing table:** ```jsx Spring Promo Sign up ``` **Combine for B2B + pricing table:** ```jsx Sign up your company ``` + +# Billing - Billing user experience - Customize the plan sign-up experience + +> Guide to customizing the plan sign-up experience including three different approaches and billing screen customization options. + +plan sign-up, billing customization, plan selection, payment flow, billing screens, HTML CSS customization +billing + +There are three ways you can allow customers to sign up to a plan. ## Option 1: Use your own plan selection screen Display a plan selection screen in your own app or website. Once the user selects a plan, redirect them to Kinde to complete the payment flow. To pre-select a plan, pass the `plan_interest` query parameter in the Kinde authentication URL. ## Option 2: Use Kinde’s built-in plan selection Let Kinde handle plan selection as part of the authentication flow. To enable this: - [Create a pricing table](/billing/billing-user-experience/plan-selection/) in Kinde - [Add and publish plans](/billing/manage-plans/create-plans/) - Set the table to **Live** Once this is done, use the relevant pricing table key in the authentcation URL and Kinde will display the plan selection screen during signup. ## Option 3: Assign a plan via the Kinde Management API Use the [Kinde Management API](https://docs.kinde.com/kinde-apis/management/#tag/billing-agreements/get/api/v1/billing/agreements) to assign a customer to a specific plan. The next time the customer signs in, Kinde will automatically prompt them for payment details. This is ideal for: - Migrating customers from another system - Assigning a plan without user input ## Customize billing screens in the authentication flow Depending on how you choose to onboard customers, users will see three different billing screens during the authentication flow. These screens can be customized: 1. **Plan selection** - Displayed when a user signs up for the first time and multiple plans are available. 2. **Payment details** - Shown after a user selects a plan—or if a plan was pre-selected before redirecting to Kinde. 3. **Success** - Shown when sign up and payment are successfully completed. By default, all screens will inherit branding and styling from the global Kinde [Design](/design/brand/global-brand-defaults/) settings. If you want more control, you can [fully customize these screens using your own **HTML, CSS, and JavaScript**](/design/customize-with-code/customize-with-css-html/). + +# Billing - Billing user experience - Build a pricing table + +> Comprehensive guide to building pricing tables in Kinde including plan selection, customization, multi-language support, and integration options. + +pricing table, plan selection, plan groups, multi-language, plan highlighting, plan ordering, live pricing +billing + +You can build pricing tables to enable your customers to select plans and go through a payment flow as part of signing up to your app or site. Kinde's pricing table builder can generate a pricing table from published plans, or you can start with a blank one. You can also add and edit information and content in your preferred languages. You can create as many pricing tables as you want. ![parts of a pricing table](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/c911b0af-5c1d-44f8-970b-47c0084ad500/public) ## Create a pricing table A pricing table can only have 4 plans. 1. Go to **Billing > Pricing tables**. 2. Select **Add pricing table**. 3. Choose an option: 1. **Generate** a pricing table from a [plan group](/billing/manage-plans/add-manage-plan-groups/) - this pre-populates the pricing table with basic details and the plans based on the plan group you select. Up to 4 plans can be included on a pricing table. If your plan group contains more, you may want to create a new pricing table. 2. **Create new** pricing table. Manually build the pricing table and add plans from a plan group. This gives you a blank slate to start in. 4. Select **Next**. 1. **Generated** - select the group and then **Save**. 2. **New** - complete the details in the window and **Save**. ## Edit the pricing table You can edit a pricing table, but they are not versioned. Whatever content you override, it cannot be reverted or recovered. You cannot edit a plan price. This is inherited from the plan itself. ## Change what plans show on a pricing table You can add and remove plans from the pricing table when it is being worked on. 1. Open the pricing table. 2. Scroll to the **Plans** section. 3. To remove a plan: 1. Select the three dots on the plan card and select **Remove from pricing table**. 2. Confirm you want to remove the plan. This removes all custom content you have added, in all languages you have added content in, on the pricing table. The plan is removed. 3. Select **Save**. 4. To add a plan, select **Add plan**. 1. In the window that opens, select an available plan. Only plans from the same plan group are shown. 2. Complete the details in the window for this plan. At minimum, you must enter a **Display name** and the **CTA button** content. This will be displayed in the pricing table. 3. Select **Save**. The plan is added to the pricing table. ## Change the order of plans on a pricing table 1. Open the pricing table. 2. Scroll to the **Plans** section. 3. Select the three dots menu on the plan you want to move. 4. Select **Move up** or **Move down**, depending on the plan position. 5. Select **Save**. This is the order plans will be displayed left to right on the pricing table. ## Add a features list to a plan on the pricing table To promote the top features in a plan, add them manually to the pricing table. These features don't need to correspond exactly to your plan configuration, this is an opportunity to sell the most appealing product features and make plan choices easy for customers. 1. Open the pricing table. 2. Scroll to the **Plans** section. 3. Select the three dots menu on the plan and select **Edit content**. 4. In the top of the window, select the language you want to add features in. 5. Add a **Features list heading**. This sits directly above the list. 6. Add a list of features in the large text **Features list** field. Features will appear in the order they are listed. 7. Select **Save**. ## Highlight a plan on a pricing table It’s common to want to call out or highlight something about a plan on the pricing table, for example, to highlight which plan is most popular. 1. Open the pricing table. 2. Scroll to the **Plans** section. 3. Select the three dots menu on the plan and select **Edit content.** 4. In the top of the window, select the language you want to add highlight content. 5. Add a **Highlight label** and select **Save**. ## Edit and translate pricing table content If you want to display pricing tables in multiple languages, you can change add content translations to the plans on the pricing table. 1. Open the pricing table. 2. Scroll to the **Plans** section. 3. Select the three dots menu on the plan and select **Edit content.** 4. In the top of the window, select the language you want to add or edit content for. ![image.png](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/58587ad1-0077-47d7-faca-ea3dd6345d00/public) 5. Enter or edit all the content you want in the chosen language. 6. Select **Save**. ## Make the pricing table live to customers We recommend only doing this after your plans are finalized and published. 1. Open the pricing table. 2. Select **Make live**. 3. Select **Save**. If a user passes the pricing table code in a URL, they will be able to sign up using it. Here's how to [add the pricing table params to URLs](/billing/billing-user-experience/add-billing-to-url-sdk/). ## Set pricing table to show as default in register flow You can set a pricing table to show by default, even if the code key is not passed in the URL during the normal sign up flow. 1. Open the pricing table. 2. Select **Show by default**. 3. Select **Save**. If a user goes through the registration flow without a pricing table code key in the URL, this is the pricing table they will see. ## Switch the pricing table off for the register flow You can configure Kinde to hide pricing tables in the sign up flow, but still show them in the self-serve portal. You'd do this if you have designed your own pricing pages and you only want to show Kinde's pricing table for the self-serve upgrade or downgrade experience. 1. Go to **Settings > Environment > Billing**. 2. Switch off the **Show the pricing table when customers sign up** option. 3. Select **Save**. ## Add plan selector to registration URL Use your SDK or manually change URL params to incorporate billing. See [Add billing to URl or SDK](/billing/billing-user-experience/add-billing-to-url-sdk/) + +# Billing - Billing user experience - Pricing table display defaults + +> Guide to understanding pricing table display defaults for B2C, B2B, and B2B2C models including when pricing tables are shown. + +pricing table display, B2C, B2B, B2B2C, plan groups, default display, URL parameters +billing + +The pricing table that is displayed in a particular flow depends on the the [default plan groups and pricing table order](/billing/manage-plans/add-manage-plan-groups/). ## B2C (User-based) A pricing table is shown when: - A new user registers - An existing user, marked as a billing customer, signs in but isn’t on a plan yet ## B2B (Org-based) A pricing table is shown when: - A new organization registers (`is_create_org` parameter) - An org member with `org:write:billing` permission signs in and the org is a billing customer but not on a plan yet ## B2B2C (Platforms - uses both) - Organization plan selection = B2B logic - User plan selection = B2C logic ## Here's a video showing the user experience for billing ## Override the default plan display You can override which plan or pricing table is shown using URL parameters. See: [Update code and URLs for billing](/billing/billing-user-experience/add-billing-to-url-sdk/). ## Summary of display for plan groups | Model | Plan group | Pricing table is shown when | | --- | --- | --- | | B2C | User plan group | New user registers / logs in | | B2B | Org plan group | New org registers / billing admin | | B2B2C | Both | Depends on flow context | + +# Billing - Get started - Step 1 Add billing role (B2B) + +> Guide to creating a billing role for B2B organizations including permissions setup and role assignment for billing management. + +billing role, B2B, organization billing, billing admin, permissions, org:write:billing +billing + +Skip this step if you sell your services to individuals (B2C). If you are a B2B business, your customers in Kinde are referred to as organizations. These can be created: * via API * manually in the Kinde admin area * via the auth flow if you have enabled the relevant settings and pass `is_create_org` as a query parameter in the authentication URL. In order to manage billing for the organization, create a default billing role (with relevant permissions) to assign to a user in the organization. 1. Go to **Settings > Roles** and select **Add role**. The **Add role** window opens. ![Roles screen for billing owner](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/96415552-a11b-4be3-e644-d9eaa2af6700/public) 2. Name the role, for example, `Billing Admin` , and enter a description and **Key**. 3. If you allow organizations to self-sign up, select the **Assign to the creator** option. 4. In the **System permissions** section, ensure the **org:write:billing** system permission is selected. 5. Select **Save**. ## Assigning the role If you have configured Kinde to allow organizations to self-sign up, and selected to apply this role to the "Creator", then this role will now be automatically assigned to users who create an organization as part of the authentication flow. Alternatively, you can assign the billing admin role to organization members via API or in the Kinde dashboard. You can add the permissions to any of your custom roles and mix and match the system permissions to work for your needs. **Next:** [Step 2 Connect to Stripe and set policies](/billing/get-started/connect-to-stripe/) + +# Billing - Get started - Step 6 Create pricing table (optional) + +> Guide to creating pricing tables in Kinde for plan selection during registration and self-serve portal plan changes. + +pricing table, plan selection, registration flow, self-serve portal, plan upgrade, plan downgrade +billing + +Kinde lets you create pricing tables based on your plans. The tables can be integrated into the auth flow so that plan selection becomes part of registration. It might look something like this. ![pricing table example](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/8514b968-262d-4aec-24bd-02070669e300/public) Pricing tables are also used in the plan upgrade and downgrade flows available in the self-serve portal. So when a customer changes their plan, the pricing table appears for them to select the new plan option. To create your own, go to [Build a pricing table](/billing/billing-user-experience/plan-selection/). If you have your own screen flows for plan display and selection, you do not have to use Kinde’s pricing tables. **Next:** [Step 7 Set up the self-serve portal (optional)](/billing/get-started/self-serve-portal-setup/) + +# Billing - Get started - Step 4 Build plans + +> Guide to developing a plan strategy and building plans in Kinde including B2B/B2C considerations, feature planning, and pricing models. + +plan strategy, B2B, B2C, B2B2C, plan features, pricing models, plan limits, feature planning +billing + +Whether you currently charge for services or are just starting out, building plans is the more complex part of the billing setup process. We recommend you define a strategy before adding plans in Kinde. - [Learn more about how plans work in Kinde](/billing/manage-plans/about-plans/) - [Skip to creating plans](/billing/manage-plans/create-plans) ## Develop a plan strategy If you have not created plans before, here’s a list of tasks to help you prepare. These will give you a strategy for creating the plans you need in Kinde. 1. Are you creating B2B or B2C or B2B2C plans? B2B plan types are for business customers (organizations), B2C plan types are for individual users, B2B2C is a platform model, where you have a customer who is an organization, and then users who are customers of that organization. 2. Decide how many plans you want and the name of each plan. E.g. `Free, Pro, Plus` or `Solo, Team, Enterprise`. 3. Make a list of each [plan’s features](/billing/manage-plans/create-plans). For each feature, decide on: - the [pricing model](/billing/pricing/pricing-models/) that applies - limits and inclusions for a feature Anything you ‘gate’ access to, or put limits on in your product, should be on this list. Tip: Create a spreadsheet to keep track of everything. ![example spreadsheet for plan planning](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/401ff633-c6c8-45ba-9502-1a29274b4400/public) 4. Identify which features are common across plans. You don’t need to add a new feature every time, you can [re-use features](/billing/manage-plans/about-plans/) across plans and change the details. **See [Create plans](/billing/manage-plans/create-plans)** for step-by-step instructions. + +# Billing - Get started - Step 2 Connect to Stripe and set policies + +> Step-by-step guide to connecting Kinde to Stripe for payment processing and setting up billing policies for cancellations and plan changes. + +Stripe connection, payment processing, billing policies, cancellation policies, plan changes, onboarding +billing + +Kinde’s billing feature comes with a dependency on [Stripe](https://stripe.com), which is a globally known and reliable payments processing platform. A new Stripe account is automatically created for you when you set up billing in Kinde. ## Watch a quick video about how to connect to Stripe ## Connect to Stripe 1. If you are testing billing, switch to your non-production environment. This will automatically trigger the use of a test Stripe account as well. 2. Go to **Settings > Environment > Billing**. 3. Select **Connect Stripe account**. Kinde initiates the connection and adds the connection card. ![Stripe card connection in Kinde](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/f3797997-6681-41c8-a297-4a962d5d0500/public) 4. Select **Update Stripe information**. This kicks off a Stripe onboarding flow. You will see a Stripe-generated screen to enter details. ![Kinde Stripe onboarding flow start screen](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/71b08393-f43d-4f91-3268-7501e08d3f00/public) 5. Enter the email that will be associated with the Stripe account and select **Submit**. Here’s what happens next, depending if you have a Stripe account already associated with your email address. 1. **If you are in the test environment**, you’ll be prompted through a flow. You can continue or select **Return to Kinde**. 2. **If you are in a production environment,** you will be asked if you want to use details from an existing Stripe account or make a new one: 1. If you select existing, account details from the existing account will be used, but no other data will come across. 2. If you select to make a new one, you will be prompted to enter all your business details. This can take a while. 3. Follow the prompts as far as you want. Select **Return to Kinde**. 6. When you complete the Stripe onboarding, or opt out by selecting **Return to Kinde**, the connection card on the Kinde **Billing** page shows the connection status. ![Connection status on Kinde stripe card](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/f4eb395b-069e-42c3-ab4f-d78cc52e8800/public) - `Connecting` means Stripe is still sending information to Kinde about the account status. It should not take long to sync. - `In progress` indicates that Stripe has connected to Kinde, but still requires some additional details from you in order to fully set up the account. Select **Update Stripe information** to complete the Stripe onboarding. You need to do this before plans can be made available to your customers. - `Connected` means Stripe is successfully syncing data with Kinde and you’re ready to publish plans. ## Set billing policies for cancellation and plan changes After you have connected to Stripe, you can set policies to control what happens when a customer cancels or changes their plan. The policies are for deciding if you charge or forgive unpaid usage of metered features, or if you refund or retain unused, paid subscription days. 1. In the **Policies** section, choose the settings. 2. Select **Save**. **Next:** [Step 3 Set default billing currency](/billing/get-started/default-billing-currency/) + +# Billing - Get started - Step 3 Set default billing currency + +> Guide to setting the default billing currency for all Kinde plans including important considerations about currency selection. + +default currency, billing currency, currency selection, multi-currency, Stripe transactions +billing + +You need to set a default billing currency for all your Kinde plans, before you create them. This is the currency that purchase transactions will be processed in Stripe. The currency you select cannot be changed after your first plan is published. For now, the default billing currency will be used in all plans and plan groups you create. 1. Go to **Settings > Environment > Billing**. 2. Select a default currency. 3. Select **Save**. Next: [Step 4 Build plans](/billing/get-started/build-plans/) + +# Billing - Get started - Step 5 Publish plans + +> Guide to publishing plans in Kinde including Stripe synchronization and best practices for testing before publication. + +publish plans, Stripe sync, draft plans, published plans, plan testing +billing + +When you publish a plan, all of the plan features and charges are synced to Stripe where they are transformed into products that users can buy. We recommend testing, reviewing, and making all changes before publishing plans. When you are ready, open the plan and select **Publish plan** in the top right of the plan window. Do this for each plan you want users to subscribe to. Learn more about [draft and published plans](/billing/manage-plans/about-plans/) **Next:** [Step 6 Create pricing tables](/billing/get-started/add-pricing-table/) + +# Billing - Get started - Step 7 Set up self-serve portal (optional) + +> Guide to setting up the self-serve portal for customers to manage their own plans, payment information, and account details. + +self-serve portal, customer management, plan upgrades, plan downgrades, payment management, account management +billing + +If you want your customers (organizations or individual users) to manage their own plans, including upgrades and downgrades, payment information, team members, etc., set up the self-service portal to allow this. Aside from account management, the self-serve portal is for orgs to self-manage teams and business information, and individuals to manage their user profile. - [Self-serve portal for orgs](/build/self-service-portal/self-serve-portal-for-orgs/) - [Self-serve portal for users](/build/self-service-portal/self-serve-portal-for-users/) + +# Billing - Get started - Setup overview + +> Step-by-step overview of the billing setup process including Stripe connection, plan creation, and self-serve portal configuration. + +billing setup, Stripe connection, plan creation, self-serve portal, billing roles, pricing tables +billing + +Billing is big step for a business, so it’s a good idea to review the process before you start. ## Overview of billing setup 1. [Set up billing roles and permissions (B2B)](/billing/get-started/add-billing-role/) 2. [Connect to Stripe and set billing policies](/billing/get-started/connect-to-stripe/) 3 [Set currency](/billing/get-started/default-billing-currency/) - you can’t change this once your first plan is published 4. [Build plans](/billing/manage-plans/create-plans/) 5. [Publish plans](/billing/get-started/publish-plans/) 6. Enable subscription self-serve (optional) 1. [Create a plan selector](/billing/billing-user-experience/plan-selection/) 2. [Enable self-serve portal](/build/self-service-portal/self-serve-portal-for-orgs/) 7. [Update your code and registration URLs](/billing/billing-user-experience/add-billing-to-url-sdk/) 8. Test the setup and get your first subscriber! ## ⚠️ Test in a non-production environment If you are using billing for the first time, make sure you use a Kinde non-production environment to test out the billing features. When you use a non-production environment, Stripe automatically creates a test Stripe environment. This test environment allows you to create customers and billing subscriptions without actually charging customers. You can also use Stripe’s test credit card details. When using a Kinde test environment and a test Stripe account, you will not incur any billing-related fees from Stripe or Kinde. ## Watch a video about creating and publishing plans, and building pricing tables ## Tip: Before setting up billing - Make a list of all your app’s features - with names, descriptions, prices, metered rates, limits, inclusions, etc. You might consider doing this in a spreadsheet to make it easier and faster to add features in the Kinde plan builder. Include plan variations for prices, limits, etc. ![example of a spreadsheet of plans](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/401ff633-c6c8-45ba-9502-1a29274b4400/public) - (B2B) make sure your Kinde business is set up to [create an organization on sign up](https://docs.kinde.com/build/organizations/orgs-for-developers/#new-organization-self-sign-up). Follow the numbered steps in this section to set up billing in your business. + +# Billing - Manage plans - About plans + +> Comprehensive guide to understanding plans in Kinde including plan groups, features, pricing models, and plan lifecycle management. + +plans, plan groups, features, pricing models, fixed charges, metered features, unmetered features, plan versioning +billing + +Plans enable you to structure your app features and charge your customers for using your services. Kinde supports both basic and more advanced plans for SaaS services. Here’s some examples: - A simple subscription plan: $10 per month for x features - A more complex plan: $20 per month for x features, plus x amount per GB storage, plus MAU charges (up to x free per month). We recommend creating your basic or simplest plan first (e.g. your Free plan), then work through to more complex plans. ## Current limitations These are known limitations that we are actively working on to add. - Support for plan models with free trial periods. - Annual subscriptions. Only monthly is available right now. - No alterations to billing cycle or invoice methods. - Add-ons and discounts that can be applied to individual subscriptions. ## About plan groups Plan groups are a collection of related plans, tied to either users or organizations. - You can create as many plan groups as you need. - Each group can only contain plans for users OR plans for orgs. - You can create multiple pricing tables for one plan group (but only one is the default). - Only one plan group can be included in a pricing table. For more information see [add and manage plan groups](/billing/manage-plans/add-manage-plan-groups/) ## Parts of a plan There are a number of concepts and elements involved in building a plan. ### Plan profile This is the name of the plan, description, code key, etc. You need to enter these details and save them before you move on to adding charges and features. The plan name appears on the pricing table that you can generate to share with customers. We recommend keeping it short. Use the description fields to explain differences in plans for internal use. ### Plan feature pricing Depending how you manage plans and feature provisioning in your application, plan pricing might be simple or complex in your business. When you set up a plan, you can include a mixture of any of these options: - **Fixed charges** - a recurring charge that does not change and is invoiced in advance, e.g. a monthly subscription charge. - **Metered features** - usage-based entitlements that define what and how much users’ access, and what they pay to access it. These might be per unit, per tier, or non-chargeable. Such as included and additional MAU. - **Unmetered features** - things included in a plan that users don’t pay for separately. Unmetered features are generally used to gate feature access. E.g. X feature is not available on the Free plan, but is on a higher tier plan. ## Example plan features | Feature | Price | Pricing model | | ------------------- | ---------------------------- | ------------------------- | | Access to x feature | N/A | Unmetered | | Subscription | $ 20 / month for access | Fixed charge | | Interaction | $x per interaction | Metered / tiered | | Storage/Usage | $x per GB | Metered / units or tiered | | MAU | x included | Metered / non-chargeable | | MAU | Additional $x per MAU over n | Metered / tiered | A plan is complete when it includes all the features needed to provide the access and charge the right price. ## How to use and re-use features and charges Kinde structures plans so that they can share a pool of features and charges that you define at a high level. When you add the feature in a plan, you add the price, limits, and other differences uniquely in each plan. This makes building and managing plan features easier, because the feature shares the same key (e.g. `base_price`), making it easier to manage in your code and for gating. For example, you only need to define the item ‘Base price’ once, and then you define the price when you add it to each individual plan. Similarly, features that are inclusions, such as support hours included, just create one metered feature. Then set the limits of the feature differently for each plan level. E.g. Free plan one hour, Pro plan gets 2 hours, etc. ![Model of how you can use the same feature or charge across plans](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/190e7ba8-ba26-4fb6-57b4-a4d6b9fec700/public) ## Draft and published plans, and plan versioning Plans can be in two states: **Draft** - these plans are being developed and are not available for subscribers yet. **Published** - products and prices are synced to Stripe and the plan can be signed up to manually, or via API. - Once a plan has a subscriber, the plan cannot be changed, only versioned. - Published plans must be included in a pricing table for self-sign ups. Plan versioning is being worked on, but is not currently available. ## When a plan feature price syncs to Stripe Feature prices sync to Stripe when you are successfully connected to Strip and you publish the plan containing that feature. When you are creating a plan, you may notice that some features show `price synced` or `price not synced`. - Price synced - The price in Kinde and Stripe are the same. A plan with this feature is published. - Price not synced - The price in Kinde has not yet synced to Stripe. When you publish or re-publish the plan, this will change. If you see a mix of synced and not synced feature prices on a plan, this might be because the synced ones are in a plan that is published. Unmetered (non-chargeable) features do not have a price sync status badge. + +# Billing - Manage plans - Add and manage plan groups + +> Guide to creating and managing plan groups in Kinde including B2B/B2C organization, default groups, and plan ordering. + +plan groups, B2B, B2C, B2B2C, default groups, plan organization, pricing tables +billing + +Plan groups are a way of organizing sets of related plans together. A plan group can be defined as an 'organization' or 'user' type, depending who you are selling to. For (B2B) businesses, use the organization type. For (B2C) individual customers, use the 'user' type. If you are a B2B2C business, create one group of each type. How you set up plans in the group impacts how you present feature bundles on a pricing table. ## Default plan groups When you first add a plan in Kinde, you select the plan type and a plan group will be automatically created for you. You can later change the name of the group, or make a different group the default group. There can only be one default group for organizations and one for users. The default group is what is displayed by default on a pricing table. ## Add a plan group 1. Go to **Billing > Plans**. 2. Select **Add group**. 3. Enter a **Name** and select the type of plan the group contains. 4. Choose a colour. This only applies to how the group appears on the **Plans** page. 5. Select **Save**. 6. Repeat for all the groups you want to add. ## Organize plans within a group The order of plans within a group represents the order they are shown in the Kinde Admin. This does not impact the order they are shown on the pricing table. To move a plan up or down in a group, select the three dots menu and select a moving option: ![Plan card overflow menu](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/787e431f-c73c-44b4-b245-222f9a4cf200/public) ## Delete a plan group 1. Go to **Billing > Plans**. 2. Select the three dots menu near the plan group name. ![Plan group overflow menu](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/1ba1256c-d3cf-4b80-e7b0-8422d3866100/public) 3. Select **Delete**. 4. In the confirmation window that appears, confirm you want to delete. + +# Billing - Manage plans - Cancel a subscription + +> Guide to canceling subscriptions including customer self-service cancellation and API-based cancellation methods. + +cancel subscription, self-serve portal, API cancellation, agreement ID, billing role, cancellation workflow +billing + +While we would rather customers didn't cancel their subscription to your services, they do need to be able to. There's two ways to do this. - The customer can cancel via the self-serve portal - You can cancel on behalf of a customer via API ## How a customer can cancel their own plan Customers can only do this if you have enabled plan management in the [self-serve portal](/build/self-service-portal/self-serve-portal-for-orgs/) and the B2B customer has a [billing role](/billing/get-started/add-billing-role/) that allows them to make changes. 1. In your app or product, they open the self-serve portal for managing their account. Here's an example of where users (B2C) and organizations (B2B) can manage plans. ![Self-serve portal selector for managing plans](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/1f7c8192-418b-412e-1728-54affbfeed00/public) 2. On the **Plan** page, they can scroll to the bottom and select **Cancel plan**. 3. They follow the prompts to cancel. This information is synced to Stripe. Depending on the [billing policies](/billing/manage-plans/upgrade-downgrade-plans/) you have set, they might receive a bill for unpaid usage, or be credited for unused subscription days. ## Cancel a plan via API 1. Get the customer's Agreement ID. This is the unique ID associated with their subscription in Stripe. You can find it in their Kinde record under Billing. 2. Using a DELETE request, hit the delete/api/v1/billing/agreements endpoint and include the `agreement_id` value in the call. ![API cll to delete agreement](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/d136fd54-7474-486f-2768-8fcb1deaaa00/public) ## Receive an alert when a customer cancels their plan You can set up a workflow that enables you to check and approve cancellations. You might want to do this, for example, to be alerted when high value customers cancel. For details, refer to the [Plan cancellation request workflow](/workflows/example-workflows/plan-cancellation-request-workflow/). + +# Billing - Manage plans - Create plans + +> Step-by-step guide to creating plans in Kinde including plan groups, fixed charges, metered features, and tiered pricing configuration. + +create plans, plan groups, fixed charges, metered features, tiered pricing, plan features, subscription fees +billing + +Once you’ve got a plan strategy along with a plan feature list, prices, and details, you’re ready to create plans them in Kinde. All plans must belong to a plan group. When you create your first plan, it will be automatically added to the default group. A plan group can only contain either user plans or organization plans. When you create your first plan, we automatically create a group based on the plan type you select. ## Add a plan 1. Go to **Billing > Plans**. 2. If this is the first plan, select **Add plan** on the empty page. 3. If you already have plans, select **Add plan** in the top right. The **Add plan** window opens. ![Add plans window](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/a8a237d5-c242-45dc-453e-a7ad66e33a00/public) 4. Choose whether the plan is for **Organizations** or **Users**, or select the **Group** the plan belongs to. Only one of these options will appear. You cannot change these selections later. 5. Give the plan a **Name** (e.g. `Free`), a **Description**. This is the name that will also appear in the pricing table (if you use one). 6. Give your plan a **Key** for referencing in your code. This cannot be changed after a plan is published. 7. Select a **Default currency**. This field only appears if one has not been set. You can change this later in **Settings > Billing**, but only before any of your plans are published. 8. Select **Save**. ## Add a subscription fee or fixed charge to a plan A fixed charge is a recurring monthly charge such as base price or subscription fee. 1. Select **Add charge**. 1. If the charge exists, select **Use existing feature** then select it from the list. 2. If this is a new charge, give it a name (e.g., `Base subscription fee`). If you’ll reuse this charge across plans, choose a generic name. This cannot be changed later. 2. Add a **Line item description**. This appears on the customer invoice, so might be more specific than the name, e.g. `Base subscription - Pro plan`. 3. Set the price. (You may be asked to set a default currency if you haven’t already). 4. Select **Save**. 5. Select **Save draft**. 6. Repeat from step 1 for each fixed charge you want to add, or start adding features. ## Add features (entitlements) to a plan Features describe the individual functions or entitlements that users get with their plan. These can be of the type metered (chargeable) or unmetered (included). 1. Select **Add feature**. ![Add feature window](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/ceb95ba9-1c03-4ae7-89f9-275ab3185100/public) 2. To add a new feature, select **New unmetered** or **New metered**, then select **Next**. The **Add feature** window opens. 3. Enter a **Feature name**. Be sure to use something generic if you plan to use this feature again, e.g. `Included seats`. 4. Enter a **Description**. 5. Enter a **Key** for referencing the feature. 6. If you selected a unmetered feature, select **Save**. You’re done. Repeat from step 1 to add more features. 7. If you selected a metered feature, complete the rest of the details: ![Add feature window, select units](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/de016f2c-2477-4abd-9a2d-00e7c3e99300/public) 8. Enter the **Maximum units** allowed on the plan. Leave blank if there is no limit. 9. Enter the **Unit measurement** name, e.g. `license`, `MAU` 10. If the item is separately chargeable, select a **Pricing model**. ![Add feature window, tiered prices](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/80ea9a38-e6ac-479f-9697-f04e237d4d00/public) 11. Add a **Line item description**. This appears on the customer invoice, so might be more specific than the name, e.g. `Additional licenses for Pro (5)`. 12. For a flat unit price, enter the price and select **Save**. You’re finished. 13. For tiered pricing, select **Tiered - Graduated** and define each tier with unit numbers and add the price per unit. 14. Select **Add tier** to add a different price for higher unit tiers. For example, a unit might be $10 each if you use 1-10, but is $9 per unit if you use 11 or more. 15. Select **Save.** 16. In the **Plan** window, select **Save** to commit your changes. 17. Repeat for each feature you want to add to the plan. Then repeat this procedure for each plan. **Next:** [Step 5 Publish plans](/billing/get-started/publish-plans/) + +# Billing - Manage plans - Plan upgrade and downgrade policies + +> Guide to setting billing policies for plan upgrades, downgrades, and cancellations including usage billing and refund policies. + +plan upgrade, plan downgrade, billing policies, usage billing, refund policies, cancellation policies +billing + +If you offer different levels of paid plans, then you will need to facilitate plan upgrade or downgrade. Before you make plan changes, make sure you have set the policies. ## Set billing policies for cancellation and plan changes You can also set policies to control what happens when a customer cancels or changes their plan. The policies are for deciding if you charge or forgive unpaid usage of metered features, and if you refund or retain unused, paid subscription days. By default, unpaid usage is forgiven and you don't refund or credit for unused subscription days. 1. Go to **Settings > Environment > Billing** to set these policy defaults. 2. In the **Policies** section, choose the settings. ![Billing policies settings](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/1a4c3673-d972-4dd6-2c3a-d46b9eb70200/public) 3. Select **Save**. + +# Billing - Manage subscribers - Add metered usage for a customer via API + +> Guide to manually adding metered usage for customers via the Kinde API including agreement ID and feature code requirements. + +metered usage, API, agreement ID, feature code, usage data, billing cycle +billing + +From time to time, you may need to manually add metered usage for an individual customer. You can do this via the Kinde API. Adding usage values requires two key pieces of information: - your customer's agreement ID - the feature code you want to record usage against ## Get the agreement ID - [Via API](https://docs.kinde.com/kinde-apis/management/#tag/billing-agreements/get/api/v1/billing/agreements/). Include the `billing` expand parameter in your request to access the agreement ID. - Via the Kinde UI - Open the user or organization record in Kinde and select **Billing** in the menu. The customer agreement shows as part of the subscription details. ![Example of agreement ID in Kinde](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/6488a69d-a47d-413b-a3b3-47a39398b600/public) ## Get the feature ID 1. Open the plan the feature belongs to. 2. Edit the feature (to view it) in the plan. 3. Take note of the **Key**. ## Submit usage data POST the usage to the [meter usage record API](https://docs.kinde.com/kinde-apis/management/#tag/billing-meter-usage/post/api/v1/billing/meter_usage/) including the feature code and agreement ID to record a usage value. + +# Billing - Manage subscribers - Respond to customer activity using webhooks + +> Comprehensive guide to using Kinde billing webhooks to respond to customer activity including event triggers and automation examples. + +billing webhooks, customer activity, JWT, event triggers, automation, subscription events, payment events +billing + +Kinde's billing webhooks are outbound calls Kinde makes to your specified endpoint when particular billing events occur. You can use them to keep your application synchronized with Kinde's billing events, trigger automated actions to provide a seamless experience for your customers, and reduce the load on your support team. ## How Kinde webhooks work Kinde webhooks use HTTPS REST to send information about events to a verified external URL that you provide. When an event is triggered, Kinde dispatches a JSON Web Token (JWT) containing relevant data to your registered endpoint. It's essential to verify the authenticity of this JWT to confirm the request originated from Kinde and then decode it to access the event data. If your endpoint doesn't return a 200 OK response, Kinde will retry the webhook call using a back-off policy. More about webhooks: Manage [Kinde webhooks](/integrate/webhooks/about-webhooks/) via the Kinde interface, or via the [Kinde Management API](https://docs.kinde.com/kinde-apis/management/#tag/webhooks). ## Billing webhook triggers and examples ### A customer cancels their subscription * **Trigger**:`customer.agreement_cancelled` * **Description**: Triggered when a customer subscription is cancelled, this might be by the customer or by an admin * **Example**: Automatically deactivate premium features for a user in your application, initiate an offboarding sequence, or update their status in your CRM to "cancelled. ### A new agreement is created for a customer - **Trigger:** `customer.agreement_created` - **Description**: Triggered when a customer signs up to a plan or changes plans, and an agreement is created for the customer. - **Example**: Provision new services for the customer, send a welcome email confirming their subscription, or grant access to exclusive content. ### A customer's invoice becomes overdue * **Trigger:** `customer.invoice_overdue` * **Description**: Triggered when a customer's invoice becomes overdue. Usually only triggered in cases where payment is not automated. * **Example**: Send automated reminders to the customer about their outstanding payment, trigger a temporary suspension of services, or notify your accounts receivable team for follow-up. ### Metered usaage is recorded against a plan feature * **Trigger:** `customer.meter_usage_updated` * **Description**: Triggered when a customer's metered usage data is updated. * **Example**: Ideal for displaying real-time usage statistics to the customer within your app, calculating potential overage charges, or sending notifications if their usage approaches a predefined limit. ### A payment from a customer fails * **Trigger:** `customer.payment_failed` * **Description**: Triggered when a customer's payment attempt fails, for example due to insufficient funds or incorrect credit card details. * **Example**: Initiate a dunning process, prompt the customer to update their payment method, or temporarily restrict access to features until payment is resolved. ### A payment from a customer succeeds * **Trigger:** `customer.payment_succeeded` * **Description**: Triggered when a customer's payment is successfully processed. * **Example**: Confirm a payment receipt to the customer, unlock paid features, or record the successful transaction in your accounting system. ### A plan is associated with a customer in Kinde * **Trigger:** `customer.plan_assigned` * **Description**: Triggered when a customer is associated with a plan in Kinde. * **Example**: Activate the features associated with the newly assigned plan in your application, send a plan activation email, or update the customer's profile with their new plan details. ### A customer's plan changes (upgrade or downgrade) * **Trigger:** `customer.plan_changed` * **Description**: Triggered when a customer's billing plan is changed (e.g., upgraded or downgraded). * **Example**: Adjust the customer's feature access based on the new plan, update their billing cycle information, or notify relevant internal teams about the plan changes. + +# Billing - Manage subscribers - Subscription upgrade and downgrade methods + +> Guide to upgrading and downgrading customer subscriptions including self-serve portal, manual changes, and API methods. + +subscription upgrade, subscription downgrade, plan changes, self-serve portal, API, billing policies +billing + +Customers will eventually want to change the plan they are on and you need a way to alter their subscription. ## How to upgrade or downgrade a plan subscription - Set up the self-serve portal and allow customers to manage their own subscriptions. See [self-serve portal for orgs](/build/self-service-portal/self-serve-portal-for-orgs/) and [self-serve portal for users](/build/self-service-portal/self-serve-portal-for-users/). In this scenario, the user will select the new plan from the pricing table. - Manually upgrade or downgrade via the Kinde UI (see below) - Overwrite the current agreement (subscription) by [creating a new one via API](/kinde-apis/management/#tag/billing-agreements/post/api/v1/billing/agreements/) ## Change a plan subscription for an organization (B2B) or user (B2C) 1. Open the organization or user record in Kinde. - Go to **Organizations** and locate the org. - Go to **Users** and locate the user. 2. Select **Billing** in the side menu. Details of the org's or user's plan are shown. 3. Select **Change plan**. 4. In the dialog that appears, select the new plan. 5. Select **Save**. The customer's plan is now updated. Depending on the [billing policies](/billing/manage-plans/upgrade-downgrade-plans/) you have set, this information will be synced to Stripe and an invoice credit or bill will be issued. + +# Billing - Payment management - Manage Stripe connection + +> Guide to managing the Stripe connection in Kinde including connection status monitoring, troubleshooting, and disconnection procedures. + +Stripe connection, connection status, troubleshooting, business information, identity verification, disconnect +billing + +When you connect to Stripe as part of Kinde's billing feature, a new Stripe account is created for you. You cannot connect an existing Stripe account. When you first connect Stripe as part of the setup flow, you need to set up the new Stripe account with all your business and other details to make the connection active. To connect, follow [this process](/billing/get-started/connect-to-stripe/). You can then manage the connection in **Settings > Billing**. ![Stripe connection card in Kinde](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/859d5538-db3c-4244-3dbe-7a2ff2c04b00/public) ## Manage the Stripe connection The Stripe connection status (see below) lets you know if Stripe is connected or if you need to take action. Statuses include: - `Connecting` means Stripe is still sending information to Kinde about the account status. It should not take long to sync. - `In progress` indicates that Stripe has connected to Kinde, but still requires some additional details from you in order to fully set up the account. Select **Update Stripe information** to complete the Stripe onboarding. You need to do this before plans can be made available to your customers. - `Connected` means Stripe is successfully syncing data with Kinde and you’re ready to publish plans. You may also see an error and message, letting you know what action is needed. To add and edit Stripe business information, select **Update Stripe information**. ## Disconnect Stripe This action is not reversible. 1. Go to **Settings > Environment > Billing**. 2. On the Stripe connection card, select the three dots, then select **Disconnect**. 3. In the confirmation window, select **Disconnect billing connection**. ## Troubleshoot Stripe issues Stripe requires that your account is set up properly before connecting successfully. Here's some common reasons why the Stripe connection status remains **In progress**. - Incomplete business information - contact, tax, or other business details - Identity verification - where you need to upload a copy of your ID To add details in Stripe, select the **Update Stripe information** option. + +# Billing - Payment management - Connect payment processor (Stripe) + +> Step-by-step guide to connecting Stripe payment gateway to Kinde including onboarding flow and connection status management. + +payment gateway, Stripe connection, onboarding flow, business information, connection status, test environment +billing + +Kinde’s billing feature comes with a dependency on third party payment processor, specifically [Stripe Billing](https://stripe.com/au/billing). A payment processor holds credit card details, processes payments, applies tax, and generally handles all the financial side of billing. For now, only [Stripe](https://stripe.com), a known and reliable payments processing platform, is supported. A new Stripe account is automatically created for you when you set up billing in Kinde. 1. If you are testing billing, switch to your non-production environment. 2. Go to **Settings > Environment > Billing**. 3. Select **Connect Stripe account**. Kinde initiates the connection and adds the connection card. ![Stripe card connection in Kinde](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/f3797997-6681-41c8-a297-4a962d5d0500/public) 4. Select **Update Stripe information**. This kicks off a Stripe onboarding flow. You will see a Stripe-generated screen to enter details. ![Kinde Stripe onboarding flow start screen](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/71b08393-f43d-4f91-3268-7501e08d3f00/public) 5. Enter the email that will be associated with the Stripe account and select **Submit**. The next step depends if you have a Stripe account already associated with your email address. 1. **If you are in the test environment**, you’ll be prompted through a flow. You can continue or select **Return to Kinde**. 2. **If you are in a production environment,** you will be asked if you want to use details from an existing Stripe account or make a new one: 1. If you select existing, account details from the existing account will be used, but no other data will come across. 2. If you select to make a new one, you will be prompted to enter all your business details. This can take a while. 3. Follow the prompts as far as you want. Select **Return to Kinde**. 6. When you complete the Stripe onboarding, or opt out by selecting **Return to Kinde**, the connection card on the Kinde **Billing** page shows the connection status. ![Connection status on Kinde stripe card](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/f4eb395b-069e-42c3-ab4f-d78cc52e8800/public) - `Connecting` means Stripe is still sending information to Kinde about the account status. It should not take long to sync. - `In progress` indicates that Stripe has connected to Kinde, but still requires some additional details from you in order to fully set up the account. Select **Update Stripe information** to complete the Stripe onboarding. You need to do this before plans can be made available to your customers. - `Connected` means Stripe is successfully syncing data with Kinde and you’re ready to publish plans. + +# Billing - Pricing - Pricing models + +> Comprehensive guide to pricing models in Kinde including flat rate, usage-based, tiered, and per-feature pricing strategies. + +pricing models, flat rate pricing, usage-based pricing, tiered pricing, per-feature pricing, SaaS pricing strategy +billing + +A pricing model refers to the structured approach businesses use to charge customers for products and services, often based on factors like usage, feature access, or licensing. In Kinde, each feature you include in a plan has a pricing model attached. This topic describes some examples of pricing models you can apply in Kinde, when you might want to use them, and how to [set them up in your Kinde plans](/billing/manage-plans/create-plans/). ## Pricing decisions There's a lot of information available about SaaS pricing strategy, and many things to consider. Research the market and map out an approach that works for your business now and as you grow, before setting up plans for the first time. We will also add more flexibility and variation for pricing models in Kinde, as our billing feature develops. ## Flat rate pricing (e.g. subscription pricing) Where you want to charge a periodic (e.g. monthly) flat fee for access to your product or services. Higher plans may include access to more features, or have higher access limits. In Kinde, create a **Fixed charge** and call it something like `Subscription fee`. Re-use this charge in each plan, and change the price and line item description. - Example - Basic plan 5.00, Team plan 20.00, Business plan 75.00. ## Usage-based (metered or tiered) pricing Where you charge customers for what they use. For example, monthly active users, data storage, transactions, etc. For each individual plan you can treat this as fully pay-as-you-go, or charge volume prices so the price goes down the more units are used. You can set limits for usage based pricing or leave as limitless. Limits can make plan upgrade more attractive. ### Usage pricing - per unit In Kinde, add a **New metered feature**, e.g. `Data storage`. Leave **Maximum units** blank for limitless, or set a limit. Select a **per unit** pricing model. Set a price for each unit. E.g. - Example - Basic plan is 00.30 per unit, Team plan is 00.20 per unit, Business plan is 00.10 per unit. ### Usage pricing - volume pricing In Kinde, add a **New metered feature**, e.g. `Token generation`. Leave **Maximum units** blank for limitless (you might do this for the highest plan only), or set a limit per plan. Select the **Tiered graduated** pricing model. Set the price for each unit tier for each plan. E.g. - Basic plan (100 unit limit) 0-10 tokens / 0.50 per token, 11-20 tokens / 0.35 per token, 21-100 tokens / 0.20 per token. - Team plan (250 unit limit) 0-10 tokens / 0.40 per token, 11-20 tokens / 0.30 per token, 21-100 tokens / 0.15 per token. - Business plan (No unit limit) 0-100 tokens / 0.15 per token, 101-250 tokens / 0.10 per token, 251-1,000,000,000 tokens / 0.05 per token. (Note you need to include an upper tier limit even if you offer limitless, just use a really high number.) ## Per feature pricing Where you charge per feature or module in your SaaS model. This approach can make plan pricing transparent and make it easy for customers to choose the right plan. It can also help you group "expensive" or more "enterprise" features for inclusion in higher plans. However, it can also be challenging to decide what features should be in or out of specific plans, and to provision and gate each feature in-product. If you want to charge based on features, we recommend using a subscription model, and then including/excluding features for your plan levels. - Example - Basic plan 10.00 for features A-E. Team plan 20.00 for features A-N. Business plan 75.00 for features A-Z. Another way to approach this is to included limited metered features per plan, so that all customers get a "taste" of features, but to get more of one you need to upgrade. - Example - Basic plan 10.00 for features A-E (plus one each of F & G). Team plan 20.00 for features A-N (Plus two of U & V). Business plan 75.00 for features A-Z. ## Support and feedback Email support@kinde.com if you need a different pricing model than those listed above, or if you need help setting up your plan pricing. + diff --git a/public/_llms-txt/build.txt b/public/_llms-txt/build.txt new file mode 100644 index 000000000..8ef218108 --- /dev/null +++ b/public/_llms-txt/build.txt @@ -0,0 +1,395 @@ +--- +page_id: 1d2e3f4a-5b6c-7d8e-9f0a-1b2c3d4e5f6a +title: Kinde Documentation - Build +description: "Complete documentation for Kinde's build section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section for LLM training" +sidebar: + order: 1 +topics: + - llm + - documentation + - training + - build +sdk: [] +languages: + - markdown + - text +audience: developers +complexity: beginner +keywords: + - llm training + - documentation + - build + - section + - frontmatter + - metadata + - kinde +updated: 2025-09-18 +featured: false +deprecated: false +ai_summary: "Complete documentation for Kinde's build section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section for LLM training" +--- + +# Kinde Documentation - Build + +This is the complete documentation for Kinde's build section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section. + +# Build - Applications - Applications in Kinde + +> Comprehensive overview of Kinde applications including backend, frontend, and machine-to-machine applications with OAuth 2.0 flows and security considerations. + +applications, OAuth 2.0, authorization flows, backend apps, frontend apps, M2M apps, client credentials +applications, oauth, authentication + +Applications in Kinde facilitate the receipt of access tokens in your application’s code. Kinde applications use OAuth 2.0 flows to securely pass tokens. See [Section 4 of the OAuth 2.0 Authorization Framework](https://datatracker.ietf.org/doc/html/rfc6749#section-4) for details on Authorization flows. We support the following applications and flows. ## Back-end / server-side apps Use for server-rendered web applications. Suitable for confidential applications (such as Regular Web Applications) because the application's authentication methods are included in the exchange and must be kept secure. ### Secured with Authorization Code Flow This application uses the Authorization Code Flow to exchange an authorization code for a token. For security, a client secret is required to request an access token. The client secret is known only to the application and the authorization server. So when the application makes a request for an access token, it includes the client secret as a form of authentication. This ensures that the authorization server can verify the identity of the client application. The use of client secrets protects sensitive data from being accessed by unauthorized users and systems. ### SDKs and compatible frameworks Apollo GraphQL, Elixir, ExpressJS, Express GraphQL, Java, .NET, Next.js, NodeJS, Nuxt, PHP, Python, Ruby, TypeScript. [View Kinde SDKs](/developer-tools/about/our-sdks/) ## Front-end / client-side apps Use for client-side web applications, single page web applications, and mobile applications. Authentication methods are different for these apps because they run in unsecured systems, such as web browsers. ### Secured with Authorization Code Flow and PKCE This application uses the Authorization Code Flow with Proof Key for Code Exchange (PKCE). Client-side applications, such as single-page web apps, are typically unable to securely store a client secret due to the inherent exposure of client-side code. That’s why OAuth 2.0 recommends the Implicit Flow or PKCE (Proof Key for Code Exchange) to provide security without relying on a client secret. ### SDKs and compatible frameworks JavaScript, React, TypeScript, Android, iOS, React Native, Expo, Flutter, Node/Apollo GraphQL, Node/Express GraphQL. [View Kinde SDKs](/developer-tools/about/our-sdks/) ## Machine to machine (M2M) apps Use for your backend services that require access to an API. This includes accessing the Kinde management API. Other use cases include CLIs, daemons and IoT devices. You can create as many M2M apps as you require. See [Add a machine to machine application for API access](/developer-tools/kinde-api/connect-to-kinde-api/). ### Secured with Client Credentials M2M applications are secured through an initial exchange of each application’s Client ID and Client Secret. This identifies each application as authorized for token exchange. Each access token request must include the `Client Credentials` grant type. Typically, a request includes scopes, which define the type of information that can be requested in the exchange. ### Access to Kinde's Management API is managed via scopes When you set up an M2M application that you will use with Kinde's Management API, you need to select the scopes that your application will need to access. For example, you'll select `read`, `create`, `update`, and `delete` actions. ### Add properties to M2M tokens If you want, you can [add custom properties to an M2M application](/properties/work-with-properties/manage-properties/) and then [include these properties in M2M tokens](/properties/work-with-properties/properties-in-tokens/). This is helpful if you want to include special information when you pass M2M tokens between systems. + +# Build - Applications - Add and manage applications + +> Step-by-step guide for adding and managing applications in Kinde including configuration tasks, application deletion, and integration setup requirements. + +add applications, manage applications, application configuration, delete applications, application keys, callback URLs +applications, configuration + +Applications are how you make your product or service available to your users, such as through a mobile app, a web app, or a website. If you plan to manage authentication for each of your applications using Kinde, you will need to add and configure each application. [Kinde provides several application types](/build/applications/about-applications/), including a regular web app (for execution on a server), single page web app (for browsers and mobile), and machine to machine applications (for backend services that require access to an API, including the [Kinde management API](/developer-tools/kinde-api/connect-to-kinde-api/)). ## Add an application 1. Go to **Settings > Environment >** **Applications**. 2. Select **Add application**. 3. Enter a name and select the type of application. 4. Select **Save**. A tile appears for the application. 5. Configure the application by selecting **View details** on the application tile. Some of the main tasks are listed below. ## Application configuration tasks - [Get application keys](/get-started/connect/getting-app-keys/) to connect your apps - Set callback URLs using the [relevant SDK](/developer-tools/about/our-sdks/) - [Set up authentication](/authenticate/authentication-methods/set-up-user-authentication/) - [Configure tokens](/build/tokens/configure-tokens/) ## Delete an application You can now delete applications in Kinde. You need to be an owner or an admin to do this. When an application is deleted, all application-related authentication settings, token settings, session information, and API links are also deleted. 1. Go to **Settings > Environment >** **Applications**. 2. Select the three dots next to the application you want to delete and select **Delete application**. A confirmation window appears. 3. Follow the prompts in the window and select **Delete application**. + +# Build - Applications - Authenticating single-page apps (SPAs) with Kinde + +> Comprehensive guide for authenticating single-page applications with Kinde including client-side and server-side authentication approaches with React and Node.js examples. + +SPA authentication, single-page apps, client-side auth, server-side auth, PKCE, JWT validation, API routes +applications, authentication, spa + +A very common architecture is to use a decoupled front-end / back-end with a standalone front-end and separate REST API for the back end. This topic runs through a scenario for authenticating a SPA. In our scenario, you have a React front-end and a NodeJS based API. This is a pretty common set up we see at Kinde, however, the guiding principles are the same regardless of the technologies you use. There are a couple of ways you can use Kinde to authenticate this style of application. ## Option 1: Client side authentication This authentication option takes place in the browser and when you want to call your API, you send the access token you received from Kinde to your API in the **Bearer header**. ### Front end setup 1. In Kinde, go to **Settings > Applications > Add application** and choose **Front-end and mobile** application. 2. Follow the **Quick Start** guide for your chosen technology to get set up. This can be found in the menu when you view details of the application in Kinde. 3. Once you are up and running, call your API with code similar to the below - replacing `` with the API you are trying to call. 4. This sample is from a React application, but it will be very similar for any frontend technology. ```jsx const { getAccessToken } = useKindeAuth(); const fetchData = async () => { try { const accessToken = await getAccessToken(); const res = await fetch(``, { headers: { Authorization: `Bearer ${accessToken}` } }); const {data} = await res.json(); console.log({data}); } catch (err) { console.error(err); } }; ``` ### Back end setup You do not need to set up a back-end application in Kinde. The request sent to your API will include the access token, which gets validated when you receive it on your back end. Validation checks the token has not expired and that the token has originated from Kinde, as well as various other checks. While it is possible to write code to check this yourself, it can be easy to miss something and accidentally introduce serious security vulnerabilities. Here's our recommendations: - Use the Kinde JWT verifier for your chosen technology (if available). Our Node package is available [here](https://www.npmjs.com/package/@kinde/jwt-validator). OR - Use any existing middleware for your web framework OR - Choose a third-party library, for example the OpenID Foundation has [a list of libraries for working with JWT tokens](https://openid.net/developers/jwt/). #### Audience To further protect your project, we recommend you [register your API](/developer-tools/your-apis/register-manage-apis/) in Kinde and make sure it is enabled for your front end application. You will then need to [request the audience](/developer-tools/your-apis/register-manage-apis/#request-an-audience-be-added-to-a-token) from your front end to make sure it is included in the `access_token` when your user authenticates with Kinde. This is an additional check in the JWT validation above, which should be handled by the verifier you are using. ## Option 2 - Server side authentication with API routes In this approach your API deals with the authentication side and shares a session cookie with your front end. It is important to note that in order for this to work securely, both your API and front-end need to be hosted on the same domain. 1. In Kinde, go to **Settings > Applications > Add application** and choose **Back-end web** application. 2. Follow the **Quick start** guide for your respective technology to initiate the Kinde client. This can be found in the menu when you view details of the application in Kinde. 3. Implement `/login` and `/register` and `/callback` routes on your API. For example in Express this might look something like: ```typescript const app = express(); app.get("/login", async (req, res) => { const loginUrl = await kindeClient.login(sessionManager); return res.redirect(loginUrl.toString()); }); app.get("/register", async (req, res) => { const registerUrl = await kindeClient.register(sessionManager); return res.redirect(registerUrl.toString()); }); ``` 4. In your front-end SPA, your login and register buttons will point to the API endpoints you set up above - e.g `[api.myapp.com/login]()` ```jsx Sign in ``` This will handle the redirect to Kinde where your user will authenticate. 5. You will also need an API route to handle the callback - again using Express as an example: ```jsx app.get("/callback", async (req, res) => { const url = new URL(`${req.protocol}://${req.get("host")}${req.url}`); await kindeClient.handleRedirectToApp(sessionManager, url); // Code to creates a stateful session goes here return res.redirect("/"); }); ``` Your API should create a stateful session which is shared with your front end via a `secure`, `same-site`, `httpOnly` cookie. As previously mentioned, for this to be secure it should be on the same domain. In this architecture the user is only authenticated with your API which means your frontend SPA doesn't know their identity. For this reason it is a good idea to create a `/profile` route on your API to fetch the identity of the user after authentication. + +# Build - Applications - Set a default login route for an application + +> Guide for setting default login routes to handle session issues and provide fallback authentication endpoints for applications with expired or problematic sessions. + +default login route, login URI, session management, authentication loop, callback URLs, safety net redirect +applications, authentication, routing + +A default login route provides a kind of ‘safety net’ redirect for users who encounter issues with authenticated sessions in your application. This route provides the login endpoint for the application, so users can navigate back to the sign in screen to restart an authentication session. There are a number of reasons that default login routes are useful. - A bookmarked link to an application tries to access an expired session - A user hits ‘back’ in their browser while authenticating and the session cannot resume - A user has cookies disabled and the redirect URI sends them into an authentication loop - A link in an invitation or verification email fails when a past session has not closed properly ## To set default login routes We recommend setting a default login route for all your front-and back-end applications. 1. In Kinde, go to **Setting > Applications**. 2. Select **Configure** on the relevant application. 3. In the left menu, select **Authentication**. 4. Scroll to the **Callback URLs** section. 5. Add the **Application login URI.** This is the default login route for resolving session issues. Hits the /auth endpoint to redirect back to your application sign in page. E.g. `https://app.yourapp.com/api/auth/login` 6. Select **Save**. 7. Repeat for each relevant application. + +# Build - Applications - Rotate client secret + +> Security guide for rotating client secrets in backend and machine-to-machine applications including step-by-step rotation process and dependency management. + +client secret rotation, security, backend apps, M2M apps, secret management +applications, security + +To ensure your applications remain secure, you can periodically rotate the Client secret stored in the Kinde-side application. You can only do this for back-end and machine-to-machine applications. Note that you can only rotate a client secret by completely deactivating the old one. So you must update any dependent apps, connections, and services with the new secret ASAP. ## Rotate client secret in Kinde 1. In Kinde, go to **Settings > Applications**. 2. Select **View details** on the relevant application. 3. Scroll to the **Admin actions** section. 4. If you have previously retained a Client secret you’ll need to delete the previous secret first: 1. Take a copy of the previous secret if you want to. 2. Select **Delete previous client secret.** 5. Select **Rotate**. A confirmation window opens. 6. If you want, opt in to rotate the client secret and retain the old secret. You may need to [upgrade plans](https://kinde.com/pricing/) to do this. 7. If you don’t want to retain the previous secret, or you don’t want to upgrade, leave the switch off. 8. Select **Rotate client secret**. 9. Update any dependent apps, connections, and services with the new secret. + +# Build - Domains - Add a custom domain for an organization + +> Comprehensive guide for adding custom domains to organizations including DNS configuration, SSL certificate provisioning, verification monitoring, and troubleshooting steps. + +custom domain, organization domain, DNS records, SSL certificate, subdomain, domain verification, social auth callback +domains, organizations, ssl + + When you add a custom domain to an organization, it sets the domain URL for authentication to the custom domain, instead of a Kinde domain address. For example `account.domain.com` instead of `domain.kinde.com`. It's important to include a subdomain for this procedure to work. Common subdomain names include `account` , `id` , or `auth`, e.g. `account.domain.com`. Kinde currently supports a single custom domain per organization. ## Step 1: Add the custom domain to the organization 1. In Kinde, go to **Organizations**. 2. Browse or search for the organization. 3. In the list, select the organization to open the **Details** page. 4. Select **Custom domain** in the menu. 5. Select **Add custom domain** and enter the custom domain you want. Be sure to include the subdomain, e.g. `account.domain.com`. 6. Select **Save**. The DNS details are generated. Use them to add DNS records to your domain provider site. ## Step 2: Add DNS records to your domain provider site Instructions will vary depending on your domain provider. Here’s the general process. 1. Sign in to your domain provider admin portal. 2. Navigate to the page where you can add DNS records. 3. Use the details provided by Kinde to add CNAME DNS records. ## Step 3: Monitor for verification and SSL certificate provisioning 1. Open the individual organization record. 2. Select **Custom domains**. 3. The custom domain panel DNS records shows the current verification status. The verification process can take anywhere from a few minutes to a couple of hours. When it completes, the verification statuses will change. Here are the possible statuses you will see: - Unverified - Verification in progress - Verified - Verification failed (check that DNS records are correct on your domain provider site and try again). - Unprovisioned - Provisioning in progress - Provisioned (SSL certificate issued) - Provisioning failed Once successfully provisioned, your custom domain will then be used for this organization. You will also receive email confirmation. ## Step 4: Update provider social auth apps and codebase If the organization's users will use social authentication to sign in, update the provider apps such as Google or GitHub to include the custom domain callback (e.g. `account.example.com/login/callback`) as an authorized redirect URI. How you do this will be different for each provider you use. Remember to also update your application's codebase to reference the custom domain. ## Troubleshoot custom domain issues If you encounter any errors, such as the verification taking too long, re-check the DNS records you created on your provider site, to ensure the details are correct. ### No subdomain It's important to include a subdomain for the procedure to work, e.g. `account.domain.com`. If you left out the subdomain, delete the custom domain in Kinde, re-add it using the subdomain, and add the newly generated DNS details to your provider records. ### Tips for the DNS set up When you create the DNS records be sure to match the format and details provided in Kinde. For example, if your custom domain is `account.example.com`, then: Host = `account` Record type = `CNAME` Value = `account.example.com` TTL = Leave as default Routing policy = Leave as default ### Using multi-level subdomains If you are using a multi-level subdomain, like `multi.subdomain.example.com`, how you set up DNS records will depend on how your zones are set up. The details provided in the admin console assumes the domain entered is adding a single level to your DNS zone, but if you are adding more than one level you’ll need to create others. So if your business is `multi.subdomain.example.com` and your zone is `example.com`, you need to create a DNS entry for `multi.subdomain`, as well as for `_acme-challenge.multi.subdomain`. ## Remove a custom domain for an organization 1. Open the **Organization** record in Kinde. 2. Select **Custom domain** in the menu. 3. In the custom domain details area, select the three dots menu and then select **Remove custom domain**. Respond to the confirmation message. + +# Build - Domains - Use your own custom domain + +> Complete guide for setting up custom domains in Kinde including DNS configuration, verification process, SSL certificate provisioning, and integration with social authentication providers. + +custom domain, DNS records, CNAME, SSL certificate, subdomain, social auth, domain verification, multi-level subdomains +domains, custom-domain, dns + +By default, Kinde issues a Kinde subdomain when you first register. But for your production environment you can use your own custom domain instead of Kinde’s as your URL. For example, `account.example.com` instead of `mydomain.kinde.com`. There are a few reasons you may wish to do this. - It will give your users the impression they have never left your application to authenticate, creating a seamless user experience. - For Single Page Applications (SPAs) it means we can securely set a first party cookie meaning authentication state persists for full-page refreshes and new tabs. - If you also register the domain in the configuration for any social providers you are using, the social providers auth screen will be customized with your app details. ## Before you begin - Name your custom domain. It needs to include a subdomain for this procedure to work. Common subdomain names include `account` , `id` , or `auth`, e.g. `account.example.com`. - Make sure your application is configured to use the exact custom domain. This includes updating the environment variables and any relevant configuration files. For example, the KINDE_ISSUER_URL needs to be updated to the custom domain. - Ensure that the callback and logout redirect URLs in your Kinde settings are updated with the custom domain. This can be done in the Kinde dashboard under Settings > Applications > [your app] > View details. ## Set up in Kinde Note that the verification process can take anywhere from 5 minutes to a few hours, depending on who your domain provider is. See [tips for the DNS set up](/build/domains/pointing-your-domain/#tips-for-the-dns-set-up) below. 1. Go to **Settings > Environment > Custom domain**. 2. Select **Add custom domain** 3. In the dialog, enter your custom domain. Be sure to include the subdomain, for example `account.example.com`. 4. Select **Save**. DNS details appear. You need to add these to your domain provider site. ## Add CNAME DNS records 1. Go to your domain provider website. 2. Create CNAME DNS records using the DNS details generated above. Apologies that we can’t offer instructions for all situations, as this will be different depending on your provider. But here are the setup steps for [Godaddy](https://au.godaddy.com/help/add-a-cname-record-19236), [Cloudflare](https://community.cloudflare.com/t/adding-dns-records/52718), and [NameCheap](https://www.namecheap.com/support/knowledgebase/article.aspx/9646/2237/how-to-create-a-cname-record-for-your-domain/). ## Check verification status in Kinde Once you have created the DNS entries, Kinde will start the verification process. This can take anywhere from a few minutes to a couple of hours. When it completes, the verification status will change to 'Provisioned' and an SSL certificate will be provisioned. Your domain will then be used instead of Kinde’s. You will also receive an email notification when the process is complete. If you encounter any errors, such as the verification taking too long, re-check the DNS records you created on your provider site, to ensure the details are correct. ## Update your code - Update your code to use the custom domain. ## Add the custom domain to social sign in When you use social connections to authenticate users, you need to add the callback URL to the provider app so that the custom domain shows on the sign in form, instead of kinde.com. If you haven't set this up, follow these instructions for the [relevant social provider](/authenticate/social-sign-in/add-social-sign-in/). If you already have social auth set up, make sure you add the custom domain callback (e.g. `account.example.com/login/callback` as an authorized redirect URI in the provider app. ## Domains and auth end points Auth endpoints are available for both custom domains and your Kinde subdomain. You can get tokens from either end point, but they are not interchangeable. For example, if you get an ID and access token from `account.example.com`, it cannot be used with `mydomain.kinde.com`. ## Local domain Currently, Kinde only supports `*.localhost` for non-https traffic. ## Tips for the DNS set up When you create the DNS records for linking your own domain to Kinde, be sure to match the format you have used above. For example, if your custom domain is `account.example.com`, then: Host = `account` Record type = `CNAME` Value = `account.example.com` TTL = Leave as default Routing policy = Leave as default ## Using multi-level subdomains If you are using a multi-level subdomain, like `multi.subdomain.example.com`, how you set up DNS records will depend on how your zones are set up. The details provided in the admin console assumes the domain entered is adding a single level to your DNS zone, but if you are adding more than one level you’ll need to create others. So if your business is `multi.subdomain.example.com` and your zone is `example.com`, you need to create a DNS entry for `multi.subdomain`, as well as for `_acme-challenge.multi.subdomain`. There are many different ways people manage multi-level domains and zones, and unfortunately we can’t cover all variations in these instructions. + +# Build - Domains - Org handles and dynamic callbacks for subdomains + +> Guide for implementing organization handles and dynamic callbacks to route users to correct subdomains in multi-tenant applications with authentication flow examples. + +organization handles, dynamic callbacks, subdomains, multi-tenant, callback URLs, organization routing +domains, organizations, callbacks + +If you use [organizations in Kinde](/build/organizations/multi-tenancy-using-organizations/), you probably build and maintain multi-tenant software. And if you manage multiple subdomains for those tenants, you'll need to make sure they are redirected to the right subdomain when they authenticate. The most effective way to do this is via ‘organization handles’ supported by a dynamic callback URL. ## How it works For every organization that has its own subdomain, you will add an organization handle. The handle and the subdomain need to match exactly. Here's an example. | Organization | Handle | Subdomain | | --- | --- | --- | | Red | red | red.everycolor.com | | Green | green | green.everycolor.com | | Blue | blue | blue.everycolor.com | Then you add one dynamic callback URL to your application that routes all the users to the correct subdomain via the organization handle: `{organization.handle}.everycolor.com`. The result is that users of the **Red** org will be automatically redirected to `red.everycolor.com` when they authenticate, and so on. ## Example authentication flow ![showing how handles and a dynamic callback route users during authentcation](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/e4e8e1ca-564f-4e25-602f-5f7cc51b1700/public) ## Requirements - This feature works for top level subdomains only - Handles must exactly match subdomain names - Handles must be unique for each organization ## Add the dynamic callback URL to your application 1. In Kinde, go to **Settings > Applications > [your application] > Details.** 2. Scroll to the **Callback URLs** section and in the **Allowed callback URLs** field, add `https://{organization.handle}..com.`, and replace `` with your primary domain. For example, `https://{organization.handle}.everycolor.com` 3. Select **Save**. 4. Repeat from step 1 for each app you want to enable this for. ## Add handles to your organizations You can do this [via API](/kinde-apis/management#tag/organizations/patch/api/v1/organization/{org_code}) using the `handle` parameter, or manually in Kinde (see below). 1. In Kinde, go to **Organizations > [your organization] > Details.** 2. Enter the subdomain name for this organization in the **Handle** field, without the added URL information. For example, enter `blue` for the subdomain `https://blue.everycolor.com`. Ensure the subdomain name and the handle match exactly. The handle must also be unique within your Kinde business. 3. Select **Save**. + +# Build - Env variables - Add and update environment variables + +> Step-by-step guide for adding, updating, and deleting environment variables in Kinde including naming conventions and sensitive variable management. + +add environment variables, update environment variables, delete environment variables, sensitive variables, variable naming, environment configuration +env-variables, configuration + +Environment variables are key-value pairs configured outside your source code so that each value can change depending on the [Environment](/build/environments/environments/). Common use cases are for API keys, and URLs or IDs which change per environment, as they can be more easily updated wherever the key is referenced. You can store as many environment variables in Kinde as you want. ## Recommendations for variables - Choose a key name that helps you easily recognize what the variable is for. - Use descriptive, purpose-indicating names (e.g., `DATABASE_URL`, `API_KEY_STRIPE`). - Use a consistent case, such as CamelCase, snake_case, kebab-case, etc. We recommend using UPPER_SNAKE_CASE for environment variables as this is a widely adopted convention. - Mark a variable as sensitive if the value should be kept secret. For example an API key or password. - Consider adding a prefix for different environments (e.g., `PROD_`, `DEV_`). - Document the purpose and format of each variable for team reference. ## Add an environment variable 1. Go to **Settings > Data management > Env variables**. 2. Select **Add environment variable**. 3. In the dialog that opens, enter the **Key** and the **Value**. 4. Select if the key is **Sensitive**. 5. Select **Save**. ## Update an environment variable value You can only update the value of non-sensitive variables. If you need to update a sensitive variable value, you’ll need to delete and then create a new variable. 1. Go to **Settings > Data management > Env variables**. A list of all your variables is shown. 2. Select **Edit variable** in the … three dots menu next to the relevant non-sensitive variable. The **Edit variable** dialog opens. 3. Change the **Value**. You cannot change the `key`. 4. Select **Save**. ## Delete an environment variable 1. Go to **Settings > Data management > Env variables**. A list of all your variables is shown. 2. Select **Delete variable** in the … three dots menu next to the relevant variable. A confirmation window appears. 3. Confirm the variable deletion. + +# Build - Env variables - Store environment variables in Kinde + +> Guide for storing environment variables in Kinde including sensitive and non-sensitive variable types, environment-specific configuration, and security best practices. + +environment variables, sensitive variables, secret management, key-value pairs, workflow variables +env-variables, security, workflows + +Environment variables are key-value pairs that enable access to applications across different environments and systems. Once you can bring your code into Kinde via workflows, it’s important to be able to reference environment variables using a key, instead of hardcoding these values into your code. Kinde allows you to create and store sensitive (secret) and non-sensitive key-value pairs. ## Store variables for each environment You need to set environment variables separately, in each of your Kinde environments. You can’t share keys across development, testing, staging, and production, etc. ## Sensitive and non-sensitive environment variables The environment variables you store in Kinde can be sensitive or non-sensitive. - **Sensitive environment variables** contain confidential data (e.g., passwords, API keys, credentials) that must be handled with care to avoid security risks and data breaches. When you mark an existing environment variable as sensitive, Kinde converts it to a non-readable format and the value can no longer be read by you or your team. It can only be read by Kinde workflows at runtime. The value will also be redacted in any logs. - **Non-sensitive environment variables** handle non-confidential settings (e.g., language, application name, etc.) that don’t pose a risk if exposed. ## Examples of environment variables | Variable Name | Type | Description | Example Value | | --- | --- | --- | --- | | API_KEY | Sensitive | Authentication key for external services | `********` | | CLIENT_SECRET | Sensitive | OAuth client secret | `********` | | APP_NAME | Non-sensitive | Application identifier | `my-kinde-app` | | LOG_LEVEL | Non-sensitive | Application logging configuration | `debug` | + +# Build - Environments - About environments + +> Overview of Kinde environments including production and non-production environments, environment management, rate limiting considerations, and development workflow best practices. + +environments, production environment, non-production, staging, testing, environment management, rate limiting +environments, development, production + +Kinde allows you to run multiple environments to support your software development cycle. All plans come with one production environment and one non-production environment. Higher plans come with additional non-production environments, so you can add staging, testing, beta, etc. to meet your team’s needs. You can see the environment you are working in at the top left of the home page when signed in. ## Take care using multiple environments Unless you are a developer, we recommend you stay in the production environment for viewing and working with your Kinde account. For developers who want to test new user configurations or make other changes, do this in a non-production (testing or staging) environment first, before replicating in the production environment. ## Rate limiting for live production environments Before you make your production environment live, [follow ](/build/environments/production-to-live/)[this checklist](/build/environments/production-to-live/). It is critical that all [third-party authentication](/authenticate/authentication-methods/set-up-user-authentication/) connections (such as social connections or enterprise connections) are set up with the third-party’s Client ID and Client secret. If you leave these fields blank during setup, Kinde’s credentials will be used as a proxy, and rate limits will apply. Note that you can leave these fields blank in your non-production environments. Non-production environments cannot be made live. ## View and manage environments Select the environment drop-down in the top left of the home screen. From here you can: - Switch to another environment - View all your environments (and create additional ones) - View environment settings ## Add an environment You can only add non-production environments. 1. Select the environment drop-down in the top left of the home screen, and select **All environments**. 2. On the **Environments** page, select **Add environment**. 3. Enter a name and code for the environment, then select **Save**. ## Switch between environments Select the environment drop-down in the top left of the home screen, and select the environment you want to switch to. ## Change the name of an environment 1. Switch to the environment you want. 2. Select the environment drop-down in the top left of the home screen and choose **Environment settings**. 3. Change the environment name and select **Save**. ## Delete a non-production environment You cannot delete the production environment. 1. Select the environment drop-down in the top left of the home screen, and select **All environments**. 2. On the environment you want to delete select the three dots, then select **Delete environment**. 3. Confirm you want to delete the environment. This action is irreversible. ## Move data between environments There is currently no way to shift data or configuration settings between environments. For now, you need to replicate settings manually, and export/import data or use the [Kinde Management API](https://docs.kinde.com/kinde-apis/management/). It's on our roadmap to make this easier someday. + +# Build - Environments - Prepare your production environment to go live + +> Comprehensive checklist for preparing production environment to go live including authentication setup, domain configuration, security measures, and analytics integration. + +production environment, go live, live checklist, third-party authentication, custom domain, multi-factor authentication, Google analytics +environments, production, go-live + +As you build your business on Kinde and configure connections and features, you will eventually want to set your production environment to be ‘live’. This indicates the status of the environment to anyone making changes. Follow the checklist below before you switch your environment to show as 'Live'. ## Go-live checklist Before you go live, make sure you’ve done the following: - (Required) Enter a `Client ID` and `Client secret` in all your [third-party authentication](/authenticate/authentication-methods/set-up-user-authentication/) connections (such as social connections or enterprise connections). If you left these fields blank at setup, Kinde’s credentials are used and rate limits will apply. - (Required) Add Twilio details if you have [phone or SMS authentication](/authenticate/authentication-methods/phone-authentication/) switched on. - Add a [development environment](/build/environments/environments/) to continue building your product on Kinde without affecting the live production instance. - Add [policies and terms](/manage-your-account/business-information/policies-terms/) so that users can access and agree to these on sign up. - Configure [custom email details](/get-started/connect/customize-email-sender/) so that authentication emails sent to your users come from your business, and not Kinde. - Connect [your own domain](/build/domains/pointing-your-domain/) and customize the [sign in screens](/design/brand/global-brand-defaults/) to provide a seamless and branded experience for users. - Set up [multi-factor authentication](/authenticate/multi-factor-auth/enable-multi-factor-authentication/) to add extra layers of security for user sign in. - Connect [Google analytics](/manage-users/view-activity/track-user-sign-in-with-google-analytics/) to track sign ups through Kinde. - Set up [default roles](/manage-users/roles-and-permissions/default-user-roles/) for assigning to new users when they sign up. ## Switch an environment to appear live When you are ready, turn the 'Live' indicator switch on. 1. Open your production environment. 2. Go to **Settings > Environment > Details.** 3. Scroll to the **Environment status** section and toggle the switch to **Live**. 4. Select **Save**. If there are any issues, an error message will appear. Where there are no errors, your Kinde environment should now show as 'Live. ![Status of production environment in Kinde](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/ac1aa617-bcb6-4a7f-02d3-b51aa7bcc600/public) + +# Build - Organizations - Add and manage organizations + +> Step-by-step guide for adding and managing organizations in Kinde, including creating new organizations, modifying the default organization, and understanding organization codes. + +add organizations, manage organizations, default organization, organization code, external organization ID +organizations, multi-tenancy + +All Kinde businesses come with one default organization. Some businesses will create more organizations to support a multi-tenancy business model. [Learn more about organizations](/build/organizations/multi-tenancy-using-organizations/). - To add organizations manually, follow the procedure below. - To add multiple organizations, we recommend importing them. See [Import organizations](/build/organizations/import-organizations/). ## Add an organization 1. In the main menu, select **Organizations.** The **Organizations** page opens. 2. Select **Add organization**. 3. Enter the name of the organization. 4. If you want, add an **External organization ID**. This is the ID you use to identify the organization, and enables you to import users and assign them to organizations by matching to this ID. 5. Select **Save**. The organization now appears on the **Organization** page, and is assigned a unique code. Developers need this code for using the Kinde API and SDKs. 6. To view the details or get the code again, select the three dots and then select **View details**. ## Change the name of the default organization When you first sign up to Kinde, you have one organization already created for you. This is the default organization that all users will be added to, until you create other organizations. You can change the name of this organization, but not the unique code. 1. In the main menu, select **Organizations.** The **Organizations** page opens. 2. Select the three dots next to the default organization, and select **View details**. 3. Edit the organization name and select **Save**. + +# Build - Organizations - Allow organization creation on sign up + +> Guide for controlling organization creation during user signup, including how to disable automatic organization creation for new registrations. + +organization creation, signup, self-signup, is_create_org +organizations, signup + +By default, Kinde allows organizations to be created when a user signs up if the `is_create_org` param is passed. This is helpful if your customers are organizations and you want them to be able to self-sign up. If you want to, you can disable organization creation for new sign ups. ## Switch off organization creation on sign up You can switch this option off at any time. 1. Go to **Settings > Environment > Policies**. 2. Switch off the **Allow organization creation on sign up** option. 3. Select **Save**. + +# Build - Organizations - Manage user sign up to organizations + +> Comprehensive guide for managing user signup to organizations, including allowing specific organization registrations, default organization settings, and disabling self-signup with security considerations. + +user signup, organization registration, default organization, user policies, registration management +organizations, user-management, signup + +Kinde lets you easily manage which organizations users can sign up to. For example, you can: - allow or disable users from signing up to specific organizations (if you manage multiple organizations) - allow or disable automatic sign up to the default organization (all Kinde businesses have a default) - disable signups completely, and add users manually, via API, or by import. - disable organizations from being created when a user signs up - this is usually only needed by businesses who’s customers are also businesses (B2B). Follow the relevant procedure below to set up your preferences. ## Allow users to register to a specific organization Each organization you set up in Kinde will have a unique `org_code`. If you want users to sign up to a specific organization, the `org_code` must be passed with their registration request. You need to switch this functionality on per organization. 1. Go to **Organizations** and select the organization. 2. On the **Policies** page, switch on the option to **Allow registrations**. 3. Select **Save**. Anyone can now register onto this organization if the `org_code` is passed with the registration request. ## Sign users up to the default organization If the organization being signed up to is not known when a user signs up, the default organization is used. This applies to users created via API and by import as well. If you want, you can switch this off to prevent sign-ups to the default org. 1. Go to **Organizations** and open the default organization. 2. Go to **Policies**, then switch off the **Sign users up to the default organization if one can’t be detected** option. 3. Select **Save**. ## Disable user self-sign up You can disable user self-sign up altogether. You might do this if you want to add and manage users manually, by API, or by import only. 1. Go to **Settings > Environment > Policies**. 2. Switch off the **Allow users to sign up** option. 3. Select **Save**. This setting applies to all apps in your business. ## Sign in experience for users in multiple organizations If a user belongs to multiple organizations, they will be prompted to select an organization when they sign in unless they pass a specific `org_code`. If you use enterprise authentication, users will be recognized by their email domain and will be forwarded to the correct identity provider. + +# Build - Organizations - Delete an organization + +> Guide for safely deleting organizations including data cleanup considerations, user reassignment, and irreversible deletion process with safety precautions. + +delete organization, organization removal, data cleanup, user reassignment +organizations, data-management + +You can delete organizations in Kinde, but doing so removes all users from the organization, and deletes organization settings, feature flags, and data. Users who belong to other organizations remain assigned to those organizations. Users who only belong to the organization you are deleting will be removed, but not deleted from Kinde. ## Caution: Before you delete Deleting an organization cannot be reversed, so we recommend you: - [Reassign users to other organizations](/manage-users/about/manage-users-across-organizations/) (if you need to) - Review [feature flags](/releases/feature-flags/manage-feature-flags/) that might only apply to this organization - [Export any data](/manage-your-account/your-data/exporting-data/) that you want ## Deleting an organization 1. In Kinde, go to **Organizations**. 2. In the list, find the organization you want to delete. 3. Select the three dots menu at the far right and then select **Delete organization**. 4. In the confirmation window that appears, select **Yes, I definitely want to delete**, and then select **Delete organization**. + +# Build - Organizations - Customize email sender for an organization + +> Guide for customizing email sender settings for organizations including sender name and email address configuration with SMTP requirements. + +email sender, organization branding, custom email, SMTP, email customization +organizations, email, branding + + If you want, you can set a unique email address and sender name for each organization you have. Users in the organization will receive emails from the email address and sender name you set, for example one-time passcode emails. You can change the customer sender name any time, but you must have a [custom email sender](/get-started/connect/customize-email-sender/) set up to change the email sender address. ## Change the email sender name for an organization 1. In Kinde, go to **Organizations**, then view an organization. 2. Select **Email**. 3. Add or change the **Sender name**. 4. Select **Save**. 5. To change the sender email, see below. ## Change the email sender address for an organization You must have a [custom SMTP email provider](/get-started/connect/customize-email-sender/) set up in Kinde, and your provider details configured with the address you are sending from. 1. In Kinde, go to **Organizations**, then view an organization. 2. Select **Email**. 3. Add or change the **Sender email**. 4. Select **Save**. 5. If you want, select **Send test email**. This lets you check the changes you made. ## Send a test email 1. In Kinde, go to **Organizations**, then view an organization. 2. Select **Email**. 3. Select **Send test email**. This lets you check the email details that your customer sees. + +# Build - Organizations - Import organizations + +> Guide for importing multiple organizations via CSV including file format requirements, import process, and integration with user bulk import workflows. + +import organizations, bulk import, CSV import, external organization ID, B2B setup +organizations, bulk-import, csv + +All Kinde businesses come with one default organization. For B2B business models, multiple organizations are usually required. [Learn more about organizations](/build/organizations/multi-tenancy-using-organizations/). Use this procedure to import multiple organizations into Kinde via CSV, before you [import users](/manage-users/add-and-edit/import-users-in-bulk/) into those organizations. You can also [add and manage organizations](/build/organizations/add-and-manage-organizations/) manually. ## Set up your CSV file Before importing, you need to set up the CSV file with the organization details: - Organization name - External organization ID The CSV should be set up like this: ```text name, id alpha, a001 beta, b002 charlie, c003 ``` ## Import organizations You can use this procedure to add new organizations or update the details of your existing organizations. 1. In Kinde, go to **Organizations** and then select **Import organizations**. 2. In the window that opens, select **Choose file** and select the CSV file. 3. Select **Import**. The **Organizations** window now shows the imported organizations or changes. Next: [Import users in bulk](/manage-users/add-and-edit/import-users-in-bulk/) and include the **external organization id** to assign users to the imported organizations. + +# Build - Organizations - About organizations + +> Overview of multi-tenancy using Kinde organizations including business models, tenant isolation, and user management across multiple organizational structures. + +multi-tenancy, organizations, B2B, B2B2B, B2B2C, tenant isolation, business structure +organizations, multi-tenancy, business-models + +Kinde is designed to support most business models and structures, from single entities to large enterprises. You can [run multiple businesses](/build/set-up-options/run-multiple-businesses/) on the Kinde platform, and you can also use organizations to separately manage sub-entities and user groups - known as multi-tenanting. ## What is multi-tenancy? Multi-tenancy is where a single instance of software (e.g. a business on Kinde), and its supporting infrastructure, can serve multiple customers. There are a number of ways that multi-tenancy can be done: - A single database with a tenant ID per tenant - A single database with a schema per tenant (how Kinde does it) - A database per tenant At Kinde we use a single database with a schema per tenant, which means each customer shares the application and a single database, but each tenant’s data is isolated and remains invisible to other tenants. ## Who needs to use organizations? If your business services businesses, who in turn service businesses or customers in a B2B2B or B2B2C model, you’ll need to set up organizations. For example, you might be: - a parent company running multiple stores, branches or membership groups. - a service or SaaS company managing access to a platform for different businesses and their customers. - a consultancy managing projects for different clients. ## Sample organization structure The diagram below shows an example of an organization structure. An organizational structure outlines how certain activities are managed, including [user roles and permissions](/manage-users/roles-and-permissions/apply-roles-and-permissions-to-users/). ## User management in organizations Organizations function to separate user groups or members, so you can separately control and manage access for them. Users can also belong to multiple organizations. For example, you may want freelancers or contractors to access all organizations. User management at the organization level, lets you: - Control who can access the organization - Set roles and permissions for each user in the organization + +# Build - Organizations - Set access policies for an organization + +> Advanced guide for setting organization-specific access policies including domain restrictions, auto-addition rules, and default role assignments for new members. + +organization policies, access control, domain restrictions, default roles, organization security +organizations, access-policies, security + + You can set policies for an organization to control access to the organization. When you set policies for an organization, this overrides any [policies set at the environment level](/build/set-up-options/access-policies/). This topic provides instructions for the following tasks: - Allow anyone to join the organization - Only allow users from specific domains to sign in to the organization (i.e. apply domain restrictions for an organization) - When users from specific domains sign up, add them as members to this organization - Assign specific roles to new members of an organization You may need to activate some features as you go. ## Go to the Policies section in your organization 1. In Kinde, go to **Organizations**. 2. Browse or search for the organization. 3. In the list, select the organization to open the details page. 4. Select **Policies** in the menu. 5. Configure policies using the following procedures. ### Configure access 1. If you want users to be able to join this organization if they pass the correct `org_code`, select **Allow org members to be auto-added**. 2. (Only in the default organization) Choose if you want to **Add users to this organization if no organization is specified** on sign up. ### Configure domain restrictions 1. Select **Allow org members to be auto-added** (if not already selected). 2. Select **Auto-add users from allowed domains**. 3. Enter the domains in the **Allowed domains** list. Use the format `domain.com` and not `https://www.domain.com`. This restricts users from joining the organization unless they belong to an allowed domain. If you leave this empty, users from any domain can sign up. 4. Select **Save**. ### Configure default roles for new members 1. In the **Default roles** section, select which roles will be assigned to new members when they sign up. ![Select default roles](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/6fc3e960-8bfe-427e-1e34-051b515aa600/public) 2. Select **Save**. ## Policy setting quick reference Note that your selections for each organization override the [global policy settings](/build/set-up-options/access-policies/). | To… | Do this… | | --------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | Allow anyone to join this organization. | Select **Allow org members to be auto-added**. | | Sign up users who are not already associated with an organization, to the default organization. | Select **Add users to this organization if no organization is specified**. | | Allow only people from `specificdomain.com` to sign up to this organization. | Select **Allow self sign-up** and enter the `specificdomain.com` into the **Allowed domains** list. | | Allow only people from `specificdomain.com` to sign up to this organization and auto-add them seamlessly. | Select **Allow self sign-up** and enter the `specificdomain.com` into the **Allowed domains** list and select Auto-add users from allowed domains. | | Assign new members specific roles when they sign up | Select the **Default roles** you want assigned + +# Build - Organizations - Give API access to an organization using M2M + +> Guide for creating organization-scoped machine-to-machine applications to provide secure API access for automated systems and backend services within specific organizations. + +organization m2m, api access, machine to machine, organization scoped, backend services +organizations, m2m, api-access + +If you want to give automated systems, AI agents, or backend services access to data in a specific organization, you can do this securely using an **organization-scoped machine-to-machine (M2M) application**. This type of app is tied to a single organization and can only be used to access resources for that org. To create an org-scoped M2M app: 1. In Kinde, go to **Organizations**, then select the organization. 2. Select **Machine-to-machine apps**. 3. Follow the steps to create the app and assign the appropriate scopes. For full details, see [M2M access scoped to organizations](/machine-to-machine-applications/organization-scoped-m2m-apps/m2m-applications-for-organizations/). + +# Build - Organizations - Kinde organizations for developers + +> Comprehensive developer guide for working with Kinde organizations including creation, user assignment, self-signup flows, and organization management with code examples. + +organizations, multi-tenancy, organization creation, user assignment, organization management, org_code +organizations, multi-tenancy, user-management + +Organizations allow you to group your users into buckets. An organization in Kinde could represent a club, a company, a practice, a department - however you model your business. We’ll refer to them collectively as **organizations** in this topic. ## Important things to know about Kinde organizations - A user can belong to [multiple organizations](/manage-users/about/manage-users-across-organizations/) - The same user can have different [roles and permissions](/manage-users/roles-and-permissions/apply-roles-and-permissions-to-users/) in different organizations - By default they inherit global styles - but you can [brand them individually](/design/brand/apply-branding-for-an-organization/) - There is a **default organization** where new users are placed if we don’t know which organization they belong to. Auto assigning to this organization can be [turned off](/build/organizations/allow-user-signup-org/#sign-users-up-to-the-default-organization). - You can also [turn off](/build/organizations/allow-user-signup-org/#allow-users-to-register-to-a-specific-organization) the ability for users to sign up to specific organizations. ## Creating an organization There are three ways of creating an organization. 1. [Add](/build/organizations/add-and-manage-organizations/) or [import](/build/organizations/import-organizations/) through the Kinde application. 2. Add through the [Kinde management API](/kinde-apis/management#tag/organizations/post/api/v1/organization). 3. Allow organizations to sign themselves up (see below). ## New organization self-sign up By default Kinde allows organizations to self-sign up to your project. You can [turn this off](/build/organizations/allow-org-create-on-signup/) in Kinde if you prefer to handle registration another way. ### Basic implementation To initiate the organization self-sign up flow pass the `is_create_org` parameter in the auth url when redirecting to Kinde. This will prompt the user to register an account and upon successful registration create an organization in the background on Kinde. Our SDKs contain helpers to achieve this. The below example is from the Kinde React SDK, which ships with a `createOrg` method. ```jsx import {useKindeAuth} from "@kinde-oss/kinde-auth-react"; export const RegisterOrgButton = () => { const {createOrg} = useKindeAuth(); return ( ); }; ``` See the [relevant SDK doc](/developer-tools/about/our-sdks/) for your stack, for examples on how to do this. ### Providing an organization name If you want to pass an organization name to Kinde, you can pass it in the auth url with the `org_name` parameter. A common pattern is to provide an input field in your project for the user to type their preferred name. Here’s another example using React. ```jsx import {useKindeAuth} from "@kinde-oss/kinde-auth-react"; import {useState} from "react"; const RegisterOrgForm = () => { const {createOrg} = useKindeAuth(); const [orgName, setOrgName] = useState(""); const handleSubmit = (e) => { e.preventDefault(); // 1. store whatever you need to in your project // 2. redirect to Kinde createOrg({org_name: orgName}); }; return (
setOrgName(e.target.value)} type="text" />
); }; ``` See the [relevant SDK doc](/developer-tools/about/our-sdks/) for your stack, for examples on how to do this. ## Assigning a user to an existing organization There are a few ways of doing this. 1. Go into Kinde and [add](/manage-users/add-and-edit/add-and-edit-users/) or [import](/manage-users/add-and-edit/import-users-in-bulk/) users manually. 2. Add users via the [Kinde management API](/kinde-apis/management#tag/organizations/post/api/v1/organizations/{org_code}/users). 3. Provide a sign up link from your product (see below). ### Signing up new users into an existing organization As noted earlier, Kinde has the notion of a **default organization** where new users are placed if we don’t know which organization they belong to. This can be [switched off](/build/organizations/allow-user-signup-org/#sign-users-up-to-the-default-organization), or you can pass an `org_code` parameter in the auth URL to specify which organization you would like users to sign up to. Our SDKs provide specific helper methods for passing the `org_code` parameter. For example, in React, this can be achieved as follows: ```jsx import {useKindeAuth} from "@kinde-oss/kinde-auth-react"; export const RegisterOrgButton = (orgCode) => { const {register} = useKindeAuth(); return ( ); }; ``` See the [relevant SDK doc](/developer-tools/about/our-sdks/) for your stack, for examples on how to do this. ### Signing users into an existing organization The flows are slightly different depending on whether you supply an organization code to us in the auth url as `org_code` parameter. **No org code provided** If Kinde is not provided with an `org_code`, there are three possible outcomes: 1. If a user only belongs to a single organization they will be automatically signed into this organization. 2. If the user belongs to multiple organizations, after they have authenticated we present them with an organization selector that shows all the organizations they have access to. They can then choose one to continue. 3. If the user belongs to no organizations, they will be signed in without an organization, meaning the `org_code` claim will be omitted from the access token. Code wise there is nothing different to do from a standard sign in. Again, a React example: ```jsx import {useKindeAuth} from "@kinde-oss/kinde-auth-react"; export const LoginButton = () => { const {login} = useKindeAuth(); return ( ); }; ``` See the [relevant SDK doc](/developer-tools/about/our-sdks/) for your stack, for examples on how to do this. **Org code provided** If Kinde receives the `org_code` parameter in the auth url it means two things: 1. If you have set up [branding for the organization](/design/brand/apply-branding-for-an-organization/) we display this to the end user providing a much more customized experience 2. If the user is a member of multiple organizations we can skip the organization switcher step mentioned above and sign them straight into the requested organization. Our SDKs describe how to provide the `org code` in the auth url. Here’s an example from React. ```jsx import {useKindeAuth} from "@kinde-oss/kinde-auth-react"; export const LoginOrgButton = (orgCode) => { const {login} = useKindeAuth(); return ( ); }; ``` See the [relevant SDK doc](/developer-tools/about/our-sdks/) for your stack, for examples on how to do this. ## Getting the organization ID We refer to the organization’s ID as an `org_code` which is unique for each organization. Once a user has authenticated and is returned to your project we expose the `org_code` in their access token. Each SDK has a way of accessing this. For example in React: ```jsx const {getOrganization} = useKindeAuth(); console.log(getOrganization()); //returns {orgCode: "org_xxxxxxxxxx"} ``` See the [relevant SDK doc](/developer-tools/about/our-sdks/) for your stack, for examples on how to do this. ## Getting the list of all organization IDs a user belongs to If a user belongs to multiple organizations, you might find it useful to get a list of them. You could do this in a couple of ways: 1. Via the [Kinde management API](/kinde-apis/management#tag/organizations) 2. Reading the `id_token` (see below). ### Using the id_token to get a list of organization IDs We provide an array of organization codes in the `org_codes` claim of the `id_token`. You can either use a JWT parser to extract these, or use our SDKs provide helper methods. In React you can use the following helper: ```jsx const {getUserOrganizations} = useKindeAuth(); console.log(getUserOrganizations()); //returns {orgCodes: ["org_1234", "org_5678"]} ``` ## Roles and Permissions A user can have different roles and permissions per organization. This means they can have an `admin` role in Organization ABC but a `member` role in Organization XYZ. You can manage these roles and permissions: 1. In the [Kinde admin area](/manage-users/roles-and-permissions/user-permissions/) 2. Via the [Kinde Management API](/kinde-apis/management#tag/permissions) 3. Read them from the `access_token` (see below). Note that only permissions specific to the organization the user is signed into will be returned. ### Using the access_token to get a list of permissions We provide an array of permissions in the `permissions` claim of the `access_token`. You can either use a JWT parser to extract these, or using our SDK helper methods. In React you can use the following helper: ```jsx const {getUserOrganizations} = useKindeAuth(); console.log(getUserOrganizations()); //returns {orgCodes: ["org_1234", "org_5678"]} ``` ### Using an SDK for permission-based access control Our SDKs also ship with helpers for handling permission checks. For example in React you could use: ```jsx const {getPermission} = useKindeAuth(); getPermission("create:todos"); // {orgCode: "org_1234", isGranted: true} ``` Then you could gate the feature as follows: ```jsx { getPermission("create:todos").isGranted ? : null; } ``` See the [relevant SDK doc](/developer-tools/about/our-sdks/) for your stack, for examples on how to do this. ## Release management You can use feature flags to provide different features to different organizations. This is especially helpful if you want to beta test a new feature for your project and only release it to selected organizations. You can manage these feature flags: 1. In the [Kinde admin area](/releases/feature-flags/add-feature-flag/) 2. Via the [Kinde Management API](/kinde-apis/management#tag/feature-flags) 3. Read them from the `access_token` (see below). ### Using the access_token to get a list of feature flags We provide an array of flags in the `feature_flags` claim of the `access_token`. You can use a JWT parser extract these, or use an [appropriate SDK](/developer-tools/about/our-sdks/) for handler examples. Here’s an example from the React SDK. ```jsx feature_flags: { theme: { "t": "s", "v": "pink" }, is_dark_mode: { "t": "b", "v": true }, competitions_limit: { "t": "i", "v": 5 } } ``` + +# Build - Organizations - Customize the self-serve portal for an organization + +> Use advanced organizations to override the self-serve portal setting for individual organizations. For example, make a function available in one organization that is not suitable for another org. + +self-serve, plan, bill, payment method, SSO +self-serve portal, manage organizations, self-manage, SSO, plan management, payment details + + If an organization requires a unique setup for the self-service portal, you can do this using an advanced organization function. If you set this up, the authorized members of the organization will be able to perform the selected functions. 1. In Kinde, open the organization you want to customize. 2. In the side menu, select **Self-serve portal**. 3. If you don't have Advanced organizations switched on, enable this now. 4. Switch on the **Override environment settings** option. ![Switch to override](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/9461ff2f-0c8e-4f2a-0dbb-f6db420bb400/public) 5. Select the options you want to be available in the self-serve portal for this org. 6. Select any additional changes you want to make for members of the org (users) to access. Note that individual access is still controlled via system roles. 7. Select **Save**. Learn more about [setting up the self-serve portal for an organization](/build/self-service-portal/self-serve-portal-for-orgs/). + +# Build - Set up options - Customer self-serve portal + +> Intro to concept of self-serve portals in Kinde, including what functions they include, how to use them, and when to set them up. + +organization portal, self-serve portal, user portal, billing portal, portal permissions +self-serve-portal, organizations, users, billing + +Customer support is one of the higher overheads for a SaaS business. For paying customers, the expectation is that they get help when needed, for example, to manage their account or get assistance with your app. Kinde lets you configure a self-serve portal so authorized customers can self-manage functions provided by Kinde. A self-serve portal means your customers can make account changes without contacting you for support, saving everyone time and money. There's two types of portal: one for end users (B2C), and one for organizations (B2B). ## Watch Dave's portal demo in 90 seconds ## Self-serve portal for organizations In the organization portal, you can allow org members to manage: - Account details - Payment details (if you have billing set up) - API Keys (Paid plans) - Members and roles (Coming soon - Paid plans only) - SSO enterprise connections (Coming soon - Kinde Scale plan only) You can enable all functions or limit them to what you offer. [Set up a self-serve portal for an org](/build/self-service-portal/self-serve-portal-for-orgs/) ## Self-serve portal for users In the user portal, you can allow users to manage: - Account details - Payment details (if you have billing set up) - Multi-factor auth settings (coming soon) - API Keys [Set up a self-serve portal for users](/build/self-service-portal/self-serve-portal-for-users/) ## Self-serve portal settings These are the self-serve portal settings you can enable. ![Self-serve portal settings in Kinde](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/1fd3505c-883b-4b01-8dff-e028e25b6300/public) ## Current limitations Currently, we don't support any customer design for the portal appearance. However, you can build your own portal and use the [Kinde API](https://docs.kinde.com/kinde-apis/management/) endpoints to provide the functions. + +# Build - Set up options - Set global access policies + +> Guide for setting global access policies including self-signup controls, domain restrictions, organization creation, and social profile synchronization settings. + +access policies, domain restrictions, self signup, organization creation, social profile sync, global policies +access-policies, security, user-management + +This topic is about setting user access policies at the environment level. If you want to apply user access policies per organization, see [Set access policies for an organization](/build/organizations/organization-access-policies/) This topic covers the following tasks: - Allow anyone to sign-up for an account - Create an organization when someone signs up (for B2B businesses usually) - Allow only users from specific domains to sign up (i.e. restrict sign up based on email domain) - Enable profiles from social providers to sync with Kinde profiles (recommended if you allow social sign in) ## Set policies for all organizations 1. In Kinde, go to **Settings > Environment > Policies**. 2. If you want users to be able to sign up or register to your application, select **Allow self sign-up**. 3. If you want to restrict which domains can sign up to your applications, enter domains in the **Allowed domains** list. Use the format `domain.com` and not `https://www.domain.com`. If you leave this empty, users from any domain can sign up. 4. Choose if you want to **Allow organization creation on sign up**. This is common for B2B businesses. 5. Select **Sync user profiles on sign in** if you want to keep basic user profile data provided by third-party sources (like Google, GitHub, etc.) in sync with Kinde profiles. You only need to select this if you allow sign-up and sign-in using social providers. 6. Select **Save**. ## Policy setting quick reference Note that global access policies can be overriden at the individual organization level if you are on a [Kinde Scale plan](https://kinde.com/pricing/) and activate the Advanced organization feature. | To… | Do this… | | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | Allow anyone to sign up to your applications. | Select **Allow self sign-up**. | | Allow only people from `specificdomain.com` to sign up to your applications. | Select **Allow self sign-up** and enter the specificdomain.com into the **Allowed domains** list. | | Allow anyone to sign up to your applications and create an organization if they are a business. | Select **Allow self sign-up** and **Allow organization creation on sign up**. | + +# Build - Set up options - Configure attack protection + +> Guide for configuring attack protection including brute force protection settings, credential enumeration protection, and security best practices for account lockouts. + +attack protection, brute force protection, credential enumeration, account lockout, security settings, failed sign-in attempts +security, attack-protection, brute-force + +Attack protection is always on, and Kinde ships with sensible defaults to keep your product protected without you lifting a finger. There are some things you can configure. ## Set brute force protection 1. In Kinde, go to **Settings > Attack protection**. 2. Select **Brute force protection**. 3. Set how many sign-in attempts users get before being locked out of their account. You can choose the Kinde default of 5 or set a custom amount. 4. Set how long the account lockout lasts before users can sign in again. You can accept the Kinde default of 5 minutes or set a custom time, up to 60 minutes. 5. Select **Save**. ### What counts as a failed sign-in attempt - incorrect password entered - incorrect OTP code entered - incorrect recovery code entered - incorrect MFA response entered ## Enable credential enumeration protection Enumeration attacks are where an attacker tries to verify if an account exists using your credentials. One of the ways an attacker knows you have an account or not, is if they enter credenitals (e.g. email or phone number) and the screen either progresses to a password/code entry screen, or shows a message that the account does not exist. Once an attacker knows an account exists, they can go about breaking in. To prevent them ever knowing, you can ensure that the sign in experience does not give the answer away. 1. In Kinde, go to **Settings > Attack protection**. 2. Select **Enumeration protection**. 3. Switch on the toggle for **Credential enumeration protection**. 4. Select **Save**. For general information about Kinde security, practices, and policies, see the [Trust Center](/trust-center/security/security-at-kinde/). + +# Build - Set up options - Kinde for different business models + +> Comprehensive guide to different business models supported by Kinde including B2C, B2B, B2B2C, marketplace, agency, and membership organizations with configuration recommendations. + +business models, B2C, B2B, B2B2C, marketplace, agency, membership, multi-tenancy +business-models, multi-tenancy, organizations + +Kinde is built to support many types of SaaS models, for apps, sites, and projects. From straightforward models where you provide services directly to individuals, to multi-tenant setups for managing other business’s auth and user needs. This topic explains how to use organizations in Kinde to support your business model. ## You provide services directly to customers (B2C) Users sign up directly to your business and you manage them in one large user group. For this business setup, configure everything at the Business and Environment level in Kinde, including: - [Authentication](/authenticate/about-auth/about-authentication/) (including signing up and in with third party providers like Google) - [Global brand and page design](/design/brand/global-brand-defaults/) - [Defining roles and permissions](/manage-users/roles-and-permissions/user-roles/) Kinde comes with a default organization, so if you only have one user group, they all belong to that default organization. ## You provide services to companies (B2B) Each company your business services has their own organization in Kinde. Each organization can also have it’s own group of users. If you want, you can [allow organizations to be created when a new business signs up](/build/organizations/allow-org-create-on-signup/) to your service. Configure these settings at the Business and Environment level for organizations to inherit: - [Authentication](/authenticate/about-auth/about-authentication/) (including enterprise auth such as [Entra ID](/authenticate/enterprise-connections/azure/) or [SAML](/authenticate/enterprise-connections/custom-saml/)) - [Global brand and page design](/design/brand/global-brand-defaults/) - [Define roles and permissions](/manage-users/roles-and-permissions/user-roles/) Then you’ll set up organizations for each business you service, and in each organization: - [Manage how users sign up to organizations](/build/organizations/allow-user-signup-org/) - (optional) Set up individual [organization brand, including the sign up and sign in experience](/design/brand/apply-branding-for-an-organization/) - Define what [roles and permissions](/manage-users/roles-and-permissions/apply-roles-and-permissions-to-users/) apply for users of each organization - Enable special [feature access](/releases/about/about-feature-flags/#overriding-feature-flags) for individual organizations ## You provide services to companies, and their customers (B2B2C) Each company your business services has their own organization in Kinde. And for each organization, there is a group of users who are managed separate to each other. In tech-speak, this is multi-tenanting. You will want to carefully manage [how users sign up to organizations](/build/organizations/allow-user-signup-org/) for this business model. You will configure most settings at the Business and Environment level, and then you can decide if you customize some settings per organization. You might set up the following for your business and in your applications: - Supported [Authentication](/authenticate/about-auth/about-authentication/) types, including custom auth for [SAML](/authenticate/enterprise-connections/custom-saml/), and [social sign in](/authenticate/social-sign-in/add-social-sign-in/) - [Global brand and page design](/design/brand/global-brand-defaults/) - Define the [roles and permissions](/manage-users/roles-and-permissions/user-roles/) that can be applied to users in each organization For each organization, you will want to: - Assign [user roles and permissions](/manage-users/roles-and-permissions/apply-roles-and-permissions-to-users/), including [default roles](/manage-users/roles-and-permissions/default-user-roles/) that apply when a user signs up - Enable special [feature access](/releases/about/about-feature-flags/#overriding-feature-flags) for individual organizations - (optional) Set up individual [organization brand, including the sign up and sign in experience](/design/brand/apply-branding-for-an-organization/) In this set up, you will likely need to [manage users across organizations](/manage-users/about/manage-users-across-organizations/) as well. ## You’re a membership-type organization You’re a central organization, and you service related businesses, branches, locations, or clubs, who have members. This works a bit like a B2B2C, but the structure is usually more simple. Membership organizations are typically branded at the org level, and authentication is kept fairly simple. You will configure most settings at the Business and Environment level, such as: - [Authentication](/authenticate/about-auth/about-authentication/) (including [passwordless](/authenticate/authentication-methods/passwordless-authentication/) and [social sign up](/authenticate/social-sign-in/add-social-sign-in/) to make things easy) - A base [global brand and page design](/design/brand/global-brand-defaults/) - [Defining simple sets of roles and permissions](/manage-users/roles-and-permissions/user-roles/) For each organization, you will want to: - Spend time setting up [brand and design](/design/brand/apply-branding-for-an-organization/) - Align [roles](/manage-users/roles-and-permissions/user-roles/) and [feature access](/releases/feature-flags/edit-feature-flag/#override-feature-flag-value-for-an-organization) within each organization to ensure different users see the right part of your application - Decide [how user’s are able to sign up to an org](/build/organizations/allow-user-signup-org/) ## You’re a marketplace A marketplace usually combines a bit of B2C and B2B. This kind of business connects buyers with sellers, creators and audiences, businesses and consumers - you get the idea. A marketplace usually separates the different market participants, which can be done through organizations. This enables independent control of the parts of your app each organization can access, and how. Configure most settings at the Business and Environment level, such as: - A base [global brand and page design](/design/brand/global-brand-defaults/) - [Defining simple sets of roles and permissions](/manage-users/roles-and-permissions/user-roles/) For each organization, you will want to: - Set up [Authentication](/authenticate/about-auth/about-authentication/) per organization to enable different sign up and sign in methods, depending on user segment. For example, set password authentication with [multi-factor authentication](/authenticate/multi-factor-auth/enable-multi-factor-authentication/) for your supplier side users, and [easy social sign up](/authenticate/social-sign-in/add-social-sign-in/) for your consumer side users. - Align [roles](/manage-users/roles-and-permissions/user-roles/) and [feature access](/releases/feature-flags/edit-feature-flag/#override-feature-flag-value-for-an-organization) within each organization to ensure different users see the right part of your application - Decide [how user’s are able to sign up to an org](/build/organizations/allow-user-signup-org/) - (optional) Set up individual [organization brand, including the sign up and sign in experience](/design/brand/apply-branding-for-an-organization/) ## You’re an agency This model is for enterprise-sized customers who really love Kinde. For example, an agency who sets up and runs multiple businesses and applications, on behalf of clients, using the Kinde platform. You’ll set up each of your client’s businesses according to what type of business model they are. See above for business structure recommendations. Tip: You could adapt this model if you’re a large multi-location, multi-department, or multi-service enterprise. + +# Build - Set up options - Set up and manage user access requests + +> Guide for setting up and managing user access requests including page configuration, contact conversion to users, and access request lifecycle management. + +access requests, user conversion, request access page, contact management, user onboarding +access-requests, user-management, onboarding + +In Kinde, you can collect user information before you give people access to your application. This is managed through the **Access requests** user list. You might use this function if you’re not ready to give people product access, but you want them to register their interest. You can also use this if you want to select and control who or how many people can access your application. It’s a good idea to maintain a separate contact list for general communication to customers, and you can do this by [building your subscriber list](/manage-users/add-and-edit/manage-subscribers/). ## Set up the request access page Kinde allows you to design the page where customers can go to register their interest. See [set up your request access page](/design/pages/set-up-the-request-access-page/). ## View access requests list 1. In Kinde, go to **Users > Access requests**. A list of customer contacts is shown. 2. To see when a contact requested access, find them in the list, select the three dots menu and select **View details**. A panel slides out showing added information. ## Convert an access requests contact to a user When you’re ready to give application access to someone on your access requests list, you can convert them to a user and (if applicable) allocate them to an organization. 1. Go to **Users > Access Requests** and find the contact you want to convert to a user. 2. Select the three dots menu and select **Convert to user**. A window appears, prompting you to select the organization the user will belong to. You can only select one. 3. Select **Convert**. The contact will now appear on the **All users** list, but will also remain an **Access requests** contact. See [Manage users across organizations](/manage-users/about/manage-users-across-organizations/) if you want to assign the user to other organizations. ## Delete access request contact 1. Go to **Users > Access Requests** and find the contact you want to delete. 2. Select the three dots menu and select **Delete** **access request**. A confirmation message appears. 3. Select **Delete**. The contact is permanently removed from this list. + +# Build - Set up options - Run multiple businesses + +> Guide for managing multiple businesses on Kinde including adding new businesses, switching between them, and safely deleting businesses with data export considerations. + +multiple businesses, business management, switch business, delete business, data export +business-management, multi-tenancy + +You can run multiple businesses on Kinde. This is helpful if you want to create different businesses with different user groups. For instance if you are a founder working on multiple applications, or you also run a business in a different region. Organizations, users, branding, and activity are all managed separately. ## **Add a new business** 1. Select your business profile in the bottom left of the Kinde home screen. 2. From the menu, select **Switch business**. A screen showing all your businesses opens. 3. Select **Add business**. 4. Complete the form, including your preferred Kinde domain and data storage region. These details cannot be changed later. 5. Select **Save**. 6. To complete the setup, select the business to switch to it. Follow the quickstart prompts. ## **Switch between businesses** 1. Select your business profile in the bottom left of the Kinde home screen. 2. From the menu, select **Switch business*. A screen showing all your businesses opens. 3. Select the one you want to work in. The business loads. ## Delete a business You can only [delete a business](/manage-your-account/your-data/delete-business/) that is on the Kinde free plan. If you have a paid subscription, you need to email [support@kinde.com](mailto:support@kinde.com) to downgrade from a paid account before deleting. Include the Kinde domain and business name in the email, and send it from the owner account email. Deleting a business is a nuclear and irreversible action, so make sure you [export](/manage-your-account/your-data/exporting-data/) all your important data before doing this. + +# Build - Set up options - Enable self-serve portal for orgs + +> Guide for enabling self-serve portals for organizations including business details management, billing access, permission controls, and portal link generation methods. + +organization portal, self-serve portal, org management, billing portal, portal permissions, organization alias +self-serve-portal, organizations, billing + +You can configure a self-serve portal to enable authorized organization members to be able to self-manage functions provided by Kinde. Authorized org members can update: - [Business details](/manage-your-account/business-information/update-your-details/) - [Payment details](/manage-your-account/profile-and-plan/update-kinde-payment/) (if you have billing set up) - [API Keys](/manage-your-apis/add-manage-api-keys/self-serve-api-keys/) - [Members and roles](/get-started/team-and-account/add-team-members/) - Multi-factor auth settings (coming soon) - SSO enterprise connections (almost here) A self-serve portal means your customers can make account changes without contacting you for support. This can save you both time. If you are on the Kinde Scale plan, you can configure the [portal per organization](/build/organizations/self-serve-portal-per-org/). E.g. allow some functions for some customers and not others. ## Configure the organization self-serve portal 1. Go to **Settings > Environment > Self-serve portal**. ![Settings for self-serve portal for orgs](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/81169031-611b-402a-20f7-47c84f53b600/public) 2. Enter the **Return URL** that you want users to land on when they exit the portal, e.g. your app dashboard. 3. Add an **Organization alias** to represent how your customers are referred to in your business, e.g. Account, Partner, Workspace, etc. This will be visible in the interface in the portal. 4. In the **Organization profile** section, select the functions you want organization admins to be able to manage. ![Options for showing hiding settings for org members](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/13cf1ec6-bbe1-4059-4c78-b97d94b2b200/public) 5. Select **Save**. ## Portal access control with system permissions Each core function within the self-serve portal is governed by a corresponding system permission. For example, the `org:write:billing` permission allows users to update billing details. These permissions can be included in your custom roles and assigned to organization members. We recommend creating custom roles with varying levels of portal access, which you can then assign as needed. For instance, you might create a role that allows members to view billing details but not update them. You can select these permissions within your existing roles, or when you create them. ![Roles with system permissions for self-serve portal](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/1e90e72e-00d5-4063-8d34-79d1a9b8f000/public) When [configuring org roles](/billing/get-started/add-billing-role/), you can specify whether it should be: - Automatically assigned to all new organization members. - Automatically assigned to the organization creator. ## Generate the self-serve portal link Access to the portal is granted via a one-time link. You then use the link on an 'account' or 'profile' button in your app to open the Kinde portal screens. There are two main ways to generate this link: - **Using the user's access token** (recommended) - **Using the Kinde Management API** ### Include the self-serve portal link in the user's access token This method is ideal when you want to generate the portal link on the fly—for example, when a user clicks an "Account" button in your app. ### Generate a self-serve portal link with a Kinde SDK If you're using the Kinde React SDK, you can use the `` component, which both generates the link and redirects the user: ```jsx import {PortalLink} from "@kinde-oss/kinde-auth-react"; Account; ``` ### Generate a self-serve portal link without a Kinde SDK If you're not using a Kinde SDK, you can manually call the Account API: ```js const response = await fetch("/account_api/v1/portal_link", { headers: { Authorization: `Bearer ${userAccessToken}` } }); const data = await response.json(); window.location = data.url; ``` Optional parameters: - `return_url` – where to redirect the user after exiting the portal. - `sub_nav` – specify the portal section to open (e.g., `organization_billing`, `profile`). ### Manage the self-serve portal link using the Kinde Management API This option is useful for server-side applications or if you're using Kinde billing features without Kinde Authentication. Make a request to the `POST /api/v1/portal/generate_url` endpoint using an M2M token. **Request body** ```js { "user_id": "kp_1234567890", // The ID of the user for whom you want to generate the portal link "organization_code": "org_123456789", // Optional: the organization code for which the portal link is generated "return_url": "https://yourapp.com/dashboard", // Optional: where to redirect the user after exiting the portal "sub_nav": "profile" // Optional: specify the portal section to open (e.g., `organization_billing`, `profile`) } ``` This will return a one-time portal link for the specified user. ## How the self-serve portal looks When the user clicks the link you've added to your app, the portal opens. The default design is shown below, and we are working on allowing you to style this yourself. The options a member sees depends on their role and what you have chosen to display. ![Self-serve portal in Kinde](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/fb38548b-e530-4dfa-68b3-29ef2f287700/public) + +# Build - Set up options - Enable self-serve portal for users + +> Guide for enabling and configuring self-serve portals for users including profile management, billing access, and multiple methods for generating portal links with SDK and API examples. + +self-serve portal, user portal, account management, billing portal, portal link, account API +self-serve-portal, user-management, billing + +You can configure a self-serve portal to enable users to be able to self-manage functions provided by Kinde. For example, you can allow users to update their profile, as well as their billing subscription and payment details (if you have billing set up). If you have a B2C business, you might want to set this up. A self-serve portal means your customers can make basic account changes without contacting you for support. This can save time and money. ## Configure the user self-serve portal 1. Go to **Settings > Environment > Self-serve portal**. ![Settings for self-serve portal set up in Kinde](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/81169031-611b-402a-20f7-47c84f53b600/public) 2. Enter the **Return URL** that you want users to land on when they exit the portal, e.g. your app dashboard. This can also be used as a fallback URL if you decide to use the SDK method of dynamically generting the URL (see below). 3. In the **User profile** section, select the functions you want the user to be able to manage. If you select **Billing**, they can manage their plan as well as payment methods. ![Self-serve portal settings for users](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/f821e9c5-497d-41f0-b373-2755320d1c00/public) 4. Select **Save**. ## Generate the self-serve portal link Access to the portal is granted via a one-time link. There are two main ways to generate this link: - **Using the user's access token** (recommended) - **Using the Kinde Management API** Both methods are able to generate the portal link on the fly. For example, when a user clicks an "Account" button in your app. ### Generate a self-serve portal link with a Kinde SDK If you're using the Kinde React SDK, you can use the `` component, which both generates the link and redirects the user: ```jsx import {PortalLink} from "@kinde-oss/kinde-auth-react"; Account; ``` ### Generate a self-serve portal link without a Kinde SDK If you're not using a Kinde SDK, you can manually call the Account API: ```js const response = await fetch("/account_api/v1/portal_link", { headers: { Authorization: `Bearer ${userAccessToken}` } }); const data = await response.json(); window.location = data.url; ``` Optional parameters: - `return_url` – where to redirect the user after exiting the portal. - `sub_nav` – specify the portal section to open (e.g., `organization_billing`, `profile`). ### Manage the self-serve portal link using the Kinde Management API This option is useful for server-side applications or if you're using Kinde billing features without Kinde Authentication. Make a request to the `POST /api/v1/portal/generate_url` endpoint using an M2M token. **Request body** ```js { "user_id": "kp_1234567890", // The ID of the user for whom you want to generate the portal link "organization_code": "org_123456789", // Optional: the organization code for which the portal link is generated "return_url": "https://yourapp.com/dashboard", // Optional: where to redirect the user after exiting the portal "sub_nav": "profile" // Optional: specify the portal section to open (e.g., `organization_billing`, `profile`) } ``` This will return a one-time portal link for the specified user. ## How the self-serve portal looks When the user clicks the link you've added to your app, the portal opens. The default design is shown below, and we are working on allowing you to style this yourself. The options a member sees depends on their role and what you have chosen to display. ![Self-serve portal in Kinde](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/4b3574c5-a499-4da5-e8d0-467d56255e00/public) You can also watch this short video showing how the portal works when a customer signs up for a plan using Kinde billing. + +# Build - Set up options - Manage your code in Kinde + +> Guide for managing git code in Kinde including repository connection, branch selection, code preview functionality, and workflow deployment management. + +git sync, GitHub, code preview, workflow code, BYO code, repository management +git, workflows, code-management + +To use workflows and other BYO code features, you need to sync your git-stored code to Kinde. Currently, Kinde only syncs with Github, but other providers will be added as the feature progresses. ## Change the git repo If you are connecting your repo to Kinde for the first time, see [Connect your workflows repo and branch](/workflows/getting-started/connect-repo-for-workflows/) 1. Go to **Settings > Git repo**. 2. Select **Change repo** 3. Follow the steps to add your repo, select the branch, etc. 4. If you are on an eligible plan, switch on the code preview option in **Advanced settings**. This lets you preview newly deployed code before making it live. 5. Select **Save**. ## Preview workflow code If you are on an eligible plan, we recommend enabling code preview for your workflow. This lets you [test deployed code](/workflows/testing/preview-workflows/) before you make it live for customers. 1. Go to **Settings > Git repo**. 2. Select the **Enable preview mode** option. 5. Select **Save**. + +# Build - Tokens - Access tokens + +> Comprehensive guide to Kinde access tokens including standard JWT claims, Kinde-specific claims like organization codes and feature flags, and token behavior during refresh operations. + +access tokens, JWT, OAuth 2.0, token claims, feature flags, permissions, organization claims +tokens, authentication, oauth + +Access tokens are a secure way of authenticating users, and passing information about a user to to a system. ## Access token standard claims - **Token Type** - indicates the type of access token being used. For example, `Bearer` is a common token type used in OAuth 2.0. - **Expiration Time** - `exp` **-** Access tokens come with an expiration time (also known as expiry or lifetime) after which it is no longer valid. The timestamp is usually represented in **seconds** and can be calculated using the [Epoch](https://www.epochconverter.com/) timestamp (UNIX) or other methods. More about [setting token expiry in Kinde](/build/tokens/configure-tokens/). - **Scopes** - `scp` - information about the scopes granted to the token holder. These scopes define what actions or resources the token can access. There can be multiple scope values, so the type of this claim is an `array`. - **Issuer -** the entity that issued the access token. This is often represented as the token's `iss` claim in JWT. Typically your kinde domain e.g. `https://.kinde.com` - **Subject** - subject of the token, i.e., the user or entity for which the token was issued. Represented as the token's `sub` claim in JWT. If this is an access token for a Kinde user this will be their ID e.g. `kp_xxxx` - **Audience** - intended recipient of the access token. Represented as the token's `aud` claim in JWT. There can be multiple audience values, so the type of this claim is an `array`. - **Issued At** - timestamp of when the access token was issued. Represented as the token's `iat` claim in JWT. The timestamp is usually represented in **seconds** and can be calculated using the [Epoch](https://www.epochconverter.com/) timestamp (UNIX) or other methods. - **Token ID** - `jti` - identifier for the access token, useful for tracking and validation purposes. See [this definition](https://www.rfc-editor.org/rfc/rfc7519#section-4.1.7). - **Custom Claims** - Available using the [Kinde Properties feature](/properties/work-with-properties/properties-in-tokens/). ## Kinde additional claims - **Organization** - `org_code` claim for the organization they are accessing. Format is `org_xxxx`. - **Feature flags** - `feature_flags` claim. Access controls for what features the user can see and access. Format is: ```json "feature_flags": { "analytics": { "t": "b", "v": true }, "theme": { "t": "s", "v": "pink" } } ``` We use short codes for the various keys in the feature flags claim such as `t` and `v` to keep the token size down. `t` = `type` `v` = `value` `b` = `boolean` `i`= `integer` `s` = `strong` - **Permissions** - `permissions` claim controls for what the user can do in an app. This is an array. For example: ```json "permissions": [ "create:competitions", "delete:competitions", "view:stats", "invite:users", "view:profile ] ``` - **External provider ID** - The ID you use to identify the organization the user is authorized against - (MS Entra ID authentication only) Claims starting with `ext_` indicate that user details have come from a third party enterprise auth provider like Microsoft. For example: ```jsx "ext_groups": [ "group1", "group2 ], "ext_attributes": { "jobTitle": "engineer", "mail": "engineer@kinde.com", "preferredLanguage": "en", } ``` ## Example access token ```jsx { "aud": [ "myapp:prod-api ], "azp": "dee7f3c57b3c47e8b96edde2c7ecab7d", "exp": 1693371599, "feature_flags": { "analytics": { "t": "b", "v": true }, "theme": { "t": "s", "v": "pink" } }, "iat": 1693285199, "iss": "https://.kinde.com", "jti": "fbb6bc62-x64e-4256-8ea4-8fb9a645b123", "org_code": "org_xxxxxxxxx", "permissions": [ "create:competitions", "delete:competitions", "view:stats", "invite:users", "view:profile ], "scp": [ "openid", "profile", "email", "offline ], "sub": "kp:_xxxxxxxxx" // your user id } ``` ## Behaviour of Access Tokens on refresh When you use the `refresh_token` grant to refresh an access token, Kinde will return an existing access token if that existing access token is not expired. You will get a completely new access token if one (or more) of the following conditions are met: - You revoke your existing access token - Your user has signed out of their session, and your application has called the logout function in Kinde - Your existing access token has expired. + +# Build - Tokens - ID tokens + +> Complete guide to Kinde ID tokens including standard OpenID Connect claims, Kinde-specific claims, and troubleshooting missing claims with scope configuration. + +ID tokens, OpenID Connect, user identity, token claims, authentication, user profile +tokens, authentication, oidc + +During authentication, ID tokens carry information about authenticated users securely to your application. ## ID token standard claims - **At hash** - `at_hash` ensures the integrity of the claim made in the access token. - **Audience** - intended recipient of the token. Represented as the token's `aud` claim. This could be your kinde domain or app URI, e.g. `https://.kinde.com` - **Authentication time** - `auth_time` indicates the time when the user was authenticated. It's useful for scenarios where certain actions are allowed only if the user has recently authenticated. - **Authorized party** - an `azp` claim specifies the client ID of the party to which the ID Token was originally issued. - **Email** - the `email` associated with the user’s profile - **Expiration Time** - The `exp` claim specifies the timestamp when the ID token expires and should no longer be considered valid. It helps prevent the token from being used indefinitely. More about [setting token expiry in Kinde](/build/tokens/configure-tokens/). - **Issued At** - The `iat` claim indicates the timestamp when the ID token was issued. It can be used to determine the token's age and to mitigate replay attacks. - **Issuer** - The `iss` claim specifies the issuer of the ID token, usually the URL of the authorization server or identity provider. It's used to verify the token's authenticity. - **Picture URL** - the `picture` claim contains the location reference of the avatar picture of the user, if there is one. - **Subject -** The `sub` claim is a unique identifier for the authenticated user within the context of the issuing authentication server. In Kinde, this is the user’s ID. - **Token ID** - the `jti` claim is the unique identifier of the ID token - **Updated at** - the `updated_at` claim specifies the issuer of the ID token, usually the URL of the authorization server or identity provider. It's used to verify the token's authenticity. - **User last name** - the `family_name` claim contains the user’s last name - **User first name** - the `given_name` claim contains the user’s first name - **User full name** - `name` contains the first name and last name of the user ## Kinde additional claims - **Social identity** - Details from the user’s third-party profile, such as handle, username, and ID. - **Organizations** - The `org_codes` claim contains an array of IDs for the Kinde organizations that the user belongs to. ## Example ID token ```jsx { "at_hash": "VZ6cU0Ay0RKB5EosbWuTCQ", "aud": [ "https://.kinde.com ], "auth_time": 1692361334, "azp": "dee7f3c57b3c47e8b96edde2c7ecab7d", "email": "jane.smith@gmail.com", "exp": 1693288799, "family_name": "Smith", "given_name": "Jane", "iat": 1693285199, "iss": "https://.kinde.com", "jti": "fcxf6xd3-8c75-402x-a4cb-1659fb8c555d", "name": "Jane Smith", "org_codes": [ "org_xxxxxxxxxxx ], "picture": "https://lh3.googleusercontent.com/a/google-url", "provided_id": "", "sub": "kp_xxxxxxxxxxxxxxxxxxxx", "updated_at": 1692009540 } ``` ## Can't find a claim in the token? Missing token claims are usually caused by missing scope requests in your app. If you are not using an SDK, you need to manually add scopes (such as `profile`, `email`, `openid`) so that the token you receive from Kinde includes the right claims. Review this document if you are [not using an SDK](/developer-tools/about/using-kinde-without-an-sdk/). + +# Build - Tokens - Configure token and session expiry + +> Comprehensive guide for configuring token and session expiry times including security best practices, token lifetime management, and risk mitigation strategies for different token types. + +token expiry, session timeout, token lifetime, security, refresh tokens, access tokens, ID tokens +tokens, security, configuration + +Tokens are an essential part of keeping your application secure. They enable the continued verification of users and applications (including APIs), and are a mechanism for detecting unauthorized intruders. Tokens need to be updated and refreshed to remain secure, which is why you need to set how long a token lasts, for each token type. ## Defining token lifetimes You can define the lifetime (expiry time) of ID tokens, access tokens, refresh tokens, and SSO session expiry tokens. Expiry and timeouts are usually defined in seconds - where 3,600 seconds is one hour and 86,400 seconds is one day. Tokens and sessions need to be configured per application. - **ID Tokens**: Contain identity information about a user. These do not need to last long as identity info is only needed at the moment of authentication, and is unrelated to session lifetimes. - **Access tokens**: Contain access permissions for a user during authentication. These are the most vulnerable token for attacks, and we do not recommend extending the access token lifetime beyond 1 day. - **Refresh tokens**: Are issued at the same time as an access token, and extend a user's session without them having to reauthenticate. If you want a user to stay authenticated without having to sign in daily or more frequently - set a high lifetime for refresh tokens. - **Session inactivity timeout**: A user can be requested to re-authenticate if they do not sustain activity in the current session. We recommend setting a fairly short limit for inactivity - e.g. up to one day. If you extend the session inactivity timeout, a user's data may become vulnerable, for example if they sign in on a public device and forget to sign out. Token and session expiry should be approached with priority for system and user security. The aim is to reduce risks such as: - Token theft through man-in-the-middle attacks - Unauthorized access through compromised refresh tokens - Session hijacking on shared or public devices - Data exposure through prolonged inactive sessions ## **Set token lifetimes** 1. Go to **Settings** **> Environment > Applications.** 2. Select **View details** on the application tile. 3. Select **Tokens** in the side menu. 4. For each token type, set the expiry time in seconds. 3,600 seconds is one hour; 86,400 seconds is one day. 5. Select **Save**. ## Token security Tokens can be vulnerable to security breaches. Access tokens in particular contain sensitive information, and these tokens can be used to access systems. Refresh tokens can be used to reduce some of this risk as they can be used to get new access tokens. However, refresh tokens are also a security risk for the same reason they are useful. To mitigate risk, we recommend using Automatic Reuse Detection and Refresh Token Rotation. You can revoke access tokens and refresh tokens via the Kinde Management API. [Search the Kinde API docs](/kinde-apis/management/). + +# Build - Tokens - Using OAuth scopes + +> Guide to using OAuth 2.0 scopes in Kinde including supported scopes, authorization flows, and implementation guidance for different application types. + +OAuth scopes, authorization, openid, email, profile, offline, PKCE +tokens, oauth, scopes + +In Kinde, OAuth 2.0 scopes are used to request access to the protected information we store on behalf of your users. The OAuth protocol helps ensure only authorized access to this information. ## Kinde-supported OAuth scopes The following scopes can be requested from Kinde. `openid` - requests an ID token which contains information about the user `email` - requests a user's email `profile` - requests profile details as part of ID token, e.g. name, family name, given name, picture (avatar) `offline` - request to act on behalf of the user if they're offline ## OAuth flows How you request scopes depends on your tech framework and the OAuth 2.0 flow you’re using for your application type. You can use the following flows to request scopes in Kinde. ### Authorization Code flow `authorization_code` Recommended for regular web applications rendered on the server. ### Authorization Code flow with Proof Key for Code Exchange (PKCE) `authorization_code_flow_pkce` Kinde supports the PKCE extension, in which case the `code_challenge` and `code_challenge_method` parameters are also required. This is recommended for mobile apps and single page applications (SPAs). ### Implicit flow (not supported) Before PKCE (see above) this was the method used by applications that were unable to store secrets securely. This flow has security implications and Kinde does not support it for this reason. ## Guidance on requesting scopes Our SDK documents contain guidance on how to connect and make requests in your chosen framework or language. See [all our SDKs](/developer-tools/about/our-sdks/). You can also access our [starter kits on GitHub](https://github.com/kinde-starter-kits) and our [Kinde Management API library](/kinde-apis/management/). + +# Build - Tokens - Refresh tokens + +> Understand how refresh tokens work, including token rotation, offline scope implementation, security best practices, and SDK integration for maintaining user sessions. + +refresh tokens, token rotation, offline scope, session management, token security, auto-update +tokens, authentication, oauth + +Refresh tokens are used to request new access tokens. Access tokens are issued when a user makes an authentication request or a call is made to an API. An access token gives permission to enter and interact with a system. ## How refresh tokens work Access tokens usually have an intentionally short lifetime. However, rather than having a user need to re-authenticate frequently, a refresh token can be used to request a new access token. Refresh tokens operate without user intervention, extending session access without the same security risk as requesting a new access token. Refresh tokens can be used a finite amount of times before re-authentication is required. ## How to get a refresh token To get a refresh token, you need to include the `offline` scope when you initiate an authentication request through the `https://.kinde.com/oauth2/auth` endpoint. You also need to initiate Offline Access in your API. Details on how to do this is provided in [our SDKs](/developer-tools/about/our-sdks/), but here’s how to do it yourself. Below is an example using the Authorization Code grant, with the `offline` scope being one of the scopes passed to the authentication request. ```jsx curl -X POST -H "Content-Type: application/x-www-form-urlencoded" \ -d "response_type=code&client_id=your_client_id&redirect_uri=your_redirect_uri&scope=offline%20email%20openid%20profile&grant_type=authorization_code" \ https://.kinde.com/oauth2/auth ``` Refresh tokens are stored in sessions. When a session needs to be refreshed (for example, a pre-defined time has passed), the app uses the refresh token on the backend to obtain a new access token, using the `https://.kinde.com/oauth2/token` endpoint with `grantType=refresh_token`. **Example of a refresh token response** ```jsx { "access_token": "hju76F...P8rTh63Ute", "refresh_token": "VOe264go...oLp2dC6", "token_type": "Bearer" } ``` ## Refresh token rotation Kinde always rotates refresh tokens. When you use an existing refresh token to request a new access token, a new refresh token is also generated and provided with your new access token. The old refresh token becomes immediately invalid. ## Auto-update of refresh tokens Kinde allows a small overlap period when both a previous and new refresh token is valid. This is to account for retries and bad network connections. You can [set the lifetime of a refresh token](/build/tokens/configure-tokens/) in Kinde. It needs to be longer than the life of an access token. ## Refresh tokens when you are not using an SDK You should store the refresh token you get with your initial `/token` request. Otherwise, your user will need to go through the sign in process again, to get a new access token. ## Refresh tokens when you are using a front-end SDK If you’re using a front-end SDK like [JavaScript](/developer-tools/sdks/frontend/javascript-sdk/) or [React](/developer-tools/sdks/frontend/react-sdk/), the `getToken` function stores an in-memory cache of the access token, which it returns by default. If the token is about to expire it will use a refresh token to get a new access token from Kinde silently in the background so additional network requests to Kinde are only made when absolutely necessary. ## Token security recommendations Token security can be approached in a number of ways. We recommend at least covering the basics of: - keeping the number of refresh tokens within a manageable limit to keep credentials safe and secure. - storing refresh tokens securely in the back-end of your application because they essentially allow a user to remain authenticated forever. - employing refresh token rotation and automatic reuse detection for added security. + +# Build - Tokens - Token customization + +> Learn how to customize Kinde tokens by adding custom claims, properties, and third-party integrations like Hasura for enhanced token functionality. + +token customization, custom claims, properties, additional claims, third-party integration, Hasura +tokens, customization, properties + +If you want to include additional information in tokens, you can customize access tokens, M2M tokens, and ID tokens using preset custom claims and [properties](/properties/about-properties/). If you need Kinde token formats to be third-party friendly, you can also enable mapping for those services, e.g. Hasura. Token customization is a step toward enabling custom claims, but it is not the same thing. ## Add claims to a token 1. In Kinde, go to **Settings > Applications** and select **Details** on your application. 2. Select **Tokens**, then scroll to the **Token customization** section. 3. On the relevant token type card, select **Customize**. A window appears where you can select scopes and properties. ![Customize access token window with selection of scopes and properties](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/8b20408b-5494-4da9-c59c-01be32accf00/public) 4. Select the available **Additional claims** and **Properties** you want to include in the token. 5. Select **Save**. ## Additional claims for tokens Apart from your own [custom properties](/properties/work-with-properties/properties-in-tokens/), you can add some out of the box additional claims to tokens. ### Add claims to access tokens You can: - add an organization name to an access token (`org_name`) - add roles to an access token (`roles`) - add an email to an access token (`email`) - add an external organization ID to an access token (`external_organization_id`) ### Add claims to ID tokens You can: - Add a user's social identity to an ID token - Add a user's organizations to an ID token ### Add claims to M2M tokens You can [add feature flags to an M2M token](/machine-to-machine-applications/m2m-application-setup/add-feature-flags-to-m2m-applications/). ## Add properties to tokens To further customize tokens you can add information using [properties](/properties/about-properties/). Properties are custom fields and information that you can attach to your users, organizations, and applications in order to collect the data you want. For example, if you ask your customers to complete a form, you can map the answers to their user record. Another example could be you want to collect a delivery address for an organization, or include unique identifiers for M2M apps. To make a property available in a token, you need to [make the property public](/properties/work-with-properties/manage-properties/), and then customize the token following the procedure above, to add a property. The value will appear in the token under a `application_properties` claim: ```json { "application_properties": { "region": { "v": "eu" }, "tier": { "v": "pro" } } } ``` The `v` is a shortcode for the value of the property. Only the properties you explicitly toggle on will be included. ## Token integration for third parties Currently, we only support formatting for Hasura. 1. In Kinde, go to **Settings > Applications** and select **Details** on your application. 2. Select **Tokens.** 3. Scroll to the **Token integrations** section and switch the toggle on for the platform you use. 4. Select **Save**. + +# Build - Tokens - OAuth 2.0 access token validation and error codes + +> Reference guide for OAuth 2.0 access token validation including successful response formats and common error codes with troubleshooting information. + +OAuth 2.0, token validation, error codes, invalid_request, invalid_client, invalid_grant, unauthorized_client +tokens, oauth, error-handling + +OAuth 2.0 authentication involves a request for an access token, and a response to the request. Here’s some typical successful and unsuccessful (error) responses. ## Successful responses - `access_token` (required) – The access token string as issued by the authorization server. - `token_type` (required) – The type of token this is, typically just the string “Bearer”. - `expires_in` (recommended) – If the access token expires, the server should reply with the duration of time the access token is granted for. - `refresh_token` (optional) – If the access token will expire, then it is useful to return a refresh token which applications can use to obtain another access token. - `scope` (optional) – If the scope the user granted is identical to the scope the app requested, this parameter is optional. If the granted scope is different from the requested scope, such as if the user modified the scope, then this parameter is required. ## Unsuccessful responses - `invalid_request` – The request is missing a parameter so the server can’t proceed with the request. This may also be returned if the request includes an unsupported parameter or repeats a parameter. - `invalid_client` – Client authentication failed, such as if the request contains an invalid client ID or secret. Send an HTTP 401 response in this case. - `invalid_grant` – The authorization code (or user’s password for the password grant type) is invalid or expired. This is also the error you would return if the redirect URL given in the authorization grant does not match the URL provided in this access token request. - `invalid_scope` – For access token requests that include a scope (password or client_credentials grants), this error indicates an invalid scope value in the request. - `unauthorized_client` – The client is not authorized to use the requested grant type. For example, if you restrict which applications can use the Implicit grant, you would return this error for the other apps. - `unsupported_grant_type` – If a grant type is requested that the authorization server doesn’t recognize, use this code. Note that unknown grant types also use this specific error code rather than using the `invalid_request` above. + +# Build - Tokens - Verifying JSON Web Tokens + +> Learn how to verify JSON Web Tokens (JWTs) for secure authentication, including signing algorithms, validation methods, and security best practices for protecting your backend APIs. + +JWT verification, token validation, RSA signing, JSON Web Key, issuer claims, audience claims, state verification +tokens, security, jwt + +Kinde uses JSON Web Tokens (JWT) for secure data transmission, authentication, and authorization. JWT verification ensures that only authorized users and apps can access your regular web, native, or single-page applications, by checking that tokens are valid, and have not been tampered with, misused, or are expired. The validation process checks the structure, claims, and signature of the JWT. If you are [setting up with Kinde without an SDK](/developer-tools/about/using-kinde-without-an-sdk/), or if you are using a mobile or front-end SDK and want to protect your back-end APIs, this topic is relevant for you. ## **How the JWTs work** ### **Signing algorithm** The JWT signature is generated using a ’signing algorithm’. Kinde supports: - RSA with 2048-bit key - SHA-256 hashing algorithm - RSA signature with SHA-256 ### **Hash values** When validating a JWT, generally, the current hash value and the original hash value are parsed, or decoded, then compared to verify the token signature is authentic. This is part of token encryption. ## **Methods to verify JWTs** If you are not using one of our SDKs, you can parse and validate a JWT by: - Using any existing middleware for your web framework. - Choosing a third-party library, for example the OpenID Foundation has [a list of libraries for working with JWT tokens](https://openid.net/developers/jwt/) See also [Kinde’s supported languages and frameworks](/developer-tools/about/our-sdks/). ## **Asymmetric signing algorithm (RSA)** Verify that the token is signed with `RS256` algorithm (see the `alg` header in the token response). Kinde only supports signing tokens with the asymmetric signing algorithm (RSA). We don’t support `HMAC` signing by design. ## **JSON Web Key** It’s likely you will be using a library to validate your JWTs and they will require the url for your public JSON Web Key (also known as a `jwks` file). The file can be found here: `https://.kinde.com/.well-known/jwks` ## **Included in the Kinde access token** ### **Issuer (iss) claim** Verify the `iss` claim, that the token was issued by your Kinde environment. Each environment has a unique `iss` claim. ### **Audience (aud) claims** If you are authenticating an API, verify `aud` claims in the token. We support multiple `aud` claims which are passed in the token as a JSON array. ### **State versus stateless** For increased security in a back-end application, verify the `state` that you provided in the callback. Deny all requests with a `state` that your application does not recognize. You can use `state` for front-end applications, but it does not increase security. ## The getToken function The `getToken` function stores an in-memory cache of the access token, which it returns by default. If the token is about to expire it will use a refresh token to get a new access token from Kinde silently in the background so additional network requests to Kinde are only made when absolutely necessary. To keep tokens secure, they should only be stored in the back end of your application. Tokens become unsecured if stored in a browser’s local storage, indexed database, or session storage. + diff --git a/public/_llms-txt/contribute.txt b/public/_llms-txt/contribute.txt new file mode 100644 index 000000000..d917c6479 --- /dev/null +++ b/public/_llms-txt/contribute.txt @@ -0,0 +1,44 @@ +--- +page_id: 2e3f4a5b-6c7d-8e9f-0a1b-2c3d4e5f6a7b +title: Kinde Documentation - Contribute +description: "Complete documentation for Kinde's contribute section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section for LLM training" +sidebar: + order: 1 +topics: + - llm + - documentation + - training + - contribute +sdk: [] +languages: + - markdown + - text +audience: developers +complexity: beginner +keywords: + - llm training + - documentation + - contribute + - section + - frontmatter + - metadata + - kinde +updated: 2025-09-18 +featured: false +deprecated: false +ai_summary: "Complete documentation for Kinde's contribute section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section for LLM training" +--- + +# Kinde Documentation - Contribute + +This is the complete documentation for Kinde's contribute section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section. + +# Contribute - Index.mdx - Contribution guide + +> Comprehensive contribution guide for Kinde documentation including writing guidelines, MDX syntax, component usage, GitHub workflow, and community contribution standards. + +contribution guide, documentation, GitHub, pull request, frontmatter, MDX syntax, code samples, components +contribute, documentation, community + +We love that you want to help us with our docs in GitHub, so here’s our guidelines to help make this easier for you. The first thing to know is that Kinde has editorial discretion over all docs and we will review and edit community contributions to keep content in line with our styles and standards. Don’t let this stop you from raising issues or making suggestions - we need your expertise. We just don’t expect writing perfection, so we’ve got you covered. ## What to contribute Our docs describe what Kinde does, how our platform works, the core functions, configurations, features, settings, etc. We’re not trying to cover every use case, just the most common. Please raise an issue or suggestion if: - Something is incorrect and needs to be fixed - Something is under-explained and needs improvement - You find a gap in the docs or missing information What we are not looking for: - Product suggestions or feature requests - please log these [here](https://kinde-21631392.hs-sites.com/en-au/feature-request/) - Workarounds or solutions from third-parties - Non-specific feedback such as ‘bad doc, please improve’. ## Ways to contribute ### Raise an issue Let us know if a document is wrong or needs fixing. Be as specific as you can so we can address it quickly. An example is where a code snippet is incorrect, or a procedure is no longer working. For issues, provide: - Clear descriptive titles - Links to relevant pages/files - Explanations as to why (or *for whom*) this is a problem - Optional: proposed solutions ### Suggest a single page edit Suggest an improvement or change to a document by selecting **Edit this page** in your browser on the document. This will take you to GitHub where you can edit the content of the file and then create a pull request. As part of creating the pull request, make sure you explain why the changes are needed, who they help, and how. ### Raise a PR for bigger contributions We prefer to write the big stuff ourselves, so we encourage people to raise issues about gaps in our content and provide suggestions that way. However, if you want to create a new topic or edit multiple files, go to GitHub to create a branch or fork and raise a PR. There’s no guarantee your pages will be approved and merged, but we will review and get in touch to discuss and definitely consider new content for inclusion. ## Contributing to SDK documentation Our SDK docs are always evolving and we welcome suggestions and contributions to make them better. SDK docs are stored with our other docs (see the file structure below). The SDKs themselves are stored in separate [Kinde repos](https://github.com/kinde-oss/). ## General document structure Most Kinde docs follow a similar structure: - What is the topic about and who is it for (1-2 sentences) - Conceptual explanations with appropriate headings - Before you begin section for prerequisites - Procedure with steps - How to do x. - Supplementary or adjacent information - Related topics ## How we write Our documents are used by developers of varying experience, people from different language backgrounds, and users who are in a hurry to get the answer they need. Our guiding principle is to always use clear, simple language. Our docs are not translated currently, but they will be soon. Plain English makes translation easier. ### Writing principles - Use direct, clear sentences and short paragraphs - Use simple, plain vocabulary and phrases - Minimize jargon, idioms, and internet shorthand - Don’t make assumptions about what readers already know - Explain abbreviations and acronyms in full ### Content principles - Use short, descriptive headings that include keywords, so people can scan to find what they need. E.g. ‘Update redirect URLs’, instead of ‘Edit the .env file’. - Provide clear, step-by-step instructions that any level of user could follow easily. - Include conceptual explanations and use cases for complex topics. - Create tidy code snippets or examples that will help users get it right. ### Tone and voice - Take a friendly but casual tone, like you are explaining things to a peer or colleague. - Don’t waffle on too much with preamble, get to the point. - Speak with clarity and confidence. You know what you’re talking about. ## How to contribute to the Kinde docs ### Edit an existing article 1. Navigate to the doc in your browser and select **Edit page** at the bottom. GitHub opens. 2. Make the required changes and then **Commit**. 3. Provide clear and direct notes about your changes. 4. Submit a PR. [See below](/contribute/#raise-a-pr). ### Create a new document 1. Navigate to the folder of the section and subsection the topic will go. 2. Select **New file**. 3. Type the name of the file in the blank field and add .mdx. 4. Add the required frontmatter of the topic (`title` and `page_id`). See the [Docs syntax](/contribute/#docs-syntax) topic below. 5. Add content and commit. Explain the reason for the topic as part of the PR. ### File structure in GitHub Our documentation articles are written in `mdx` and are structured as follows: - src - content - docs - topic group - subtopic group - article-1.mdx - article-2.mdx ### Raise a PR When you're ready to raise a PR, use the following naming conventions: `feat:[description]` for new topics or substantial changes `fix:[description]` for corrections and minor changes This helps us recognize and prioritize requests. ## Docs syntax This section describes some of our styles, elements, and conventions for docs content. ### Frontmatter The header/metadata part of the content helps the article appearing correctly in docs. It is also important for external AI tools and search optimization. Copy the whole example below into the top of any new topic. And complete the required sections. Complete optional sections if you want. ```md title="src/content/docs/developer-tools/about/our-sdks.mdx --- page_id: title: description: "description" sidebar: order: relatedArticles: - - app_context: - m: s: topics: - - - sdk: [] languages: [] audience: complexity: keywords: - - - - - updated: yyyy-mm-dd featured: deprecated: ai_summary: --- ``` #### Required Fields **`title`** (string) - You must provide a title for every page. This will be displayed at the top of the page, in browser tabs, and in page metadata. **`page_id`** (uuid) - This is the internal unique `id` for the article. This will be used when referencing other articles within the `relatedArticles` frontmatter. You can use our [online UUID generator tool](https://kinde.com/tools/online-uuid-generator/) to use as the `page_id`. **`description`** (string) - A brief description of the article content, used for SEO and metadata. **`keywords`** (array) - Array of keywords for search optimization. #### Optional Fields **`order`** (number) - Control the order of this article when sorting an autogenerated group of links under a specific topic or subtopic. Lower numbers are displayed higher up in the link group. Providing the `order` frontmatter is completely optional and will be treated as a hint for us to where to place the file. We may update the article's `order` upon further review. **`topics`** (array) - Array of topic tags that help categorize the content. **`sdk`** (array) - Array of SDKs that are relevant to this article. Use `[]` for no SDKs or `null` for not applicable. **`languages`** (array) - Array of programming languages covered in the article. **`ai-summary`** (string) - A summary of the article content for AI processing and search. Can be same as description. **`relatedArticles`** (array) - Array of page IDs for related articles that should be displayed at the bottom of the page. ### Code samples The code snippets in our docs are powered by [astro-expressive-code](https://github.com/expressive-code/). Here are some examples in how you can use them: #### Regular syntax highlighting For code highlighting, you will need a language identifier. (See full list of [supported languages](https://github.com/shikijs/textmate-grammars-themes/blob/main/packages/tm-grammars/README.md) on GitHub) e.g. `js` for JavaScript: ````md title="example.mdx" ins=/^([^a-z]{3}.*)/ ```js console.log("This code is syntax highlighted!"); ``` ```` Will render: ```js console.log("This code is syntax highlighted!"); ``` #### Frames If you use a language identifier that is typically used for terminal sessions or shell scripts, a terminal frame will be added to the rendered output. ```` ```bash nano script.sh ``` ```` Will render: ```bash nano script.sh ``` If you add a value for `title`, then you get a title bar: ```` ```powershell title="PowerShell terminal example Write-Output "This one has a title! ``` ```` Result: ```powershell title="PowerShell terminal example Write-Output "This one has a title! ``` If the language identifier is not a terminal session or shell script one, providing the `title` attribute will render the frame with the file name, for example. ```` ```tsx title="src/app/page.tsx import { RegisterLink, LoginLink } from "@kinde-oss/kinde-auth-nextjs/components"; ``` ```` Output: ```tsx title="src/app/page.tsx import {RegisterLink, LoginLink} from "@kinde-oss/kinde-auth-nextjs/components"; ``` This can also been achieved by adding a comment with the file name at the top of your file. ````text frame="none" ```tsx // src/app/page.tsx import { RegisterLink, LoginLink } from "@kinde-oss/kinde-auth-nextjs/components ``` ```` Output: ```tsx // src/app/page.tsx import {RegisterLink, LoginLink} from "@kinde-oss/kinde-auth-nextjs/components"; ``` ### Images Use images sparingly, to support complex or detailed procedures. For accessibility, do not use images instead of text. Always include alt-text. If you need an image or screen shot in your article, you’ll have to: - Create a folder within `src/assets/images` with the same slug as your article (the article’s `.mdx` file name) - The image must be at least `1440px` wide - Include `alt text` in the markdown. Images are optimized before publishing, and have styles and zoom functionality added. For example, this article lives under `src/docs/contribute/index.mdx` - In this case, we would create a `contribute` folder under `src/assets/images` and save the image there. - src - assets - images - contribute - penguin.jpg To add an image to an article, just simply use the `markdown` syntax like so: ```md title="src/docs/contribute/index.mdx ![An image of a penguin](@assets/images/contribute/penguin.jpg) ``` The image will be rendered with some padding and will have the **click to zoom** functionality added to it. ![An image of a penguin](@assets/images/contribute/penguin.jpg) ## Components ### `PackageManagers` This component combines multiple useful commands from different package managers in the `node` ecosystem. It generates commands for `npm`, `pnpm` and `yarn`. #### `pkg` (required) `string` — The package to be installed. For example: `@kinde-oss/kinde-auth-nextjs` #### `type` (optional) `add` `create` `exec` `run` `remove` default: `add` #### Example ```mdx ``` #### Result ### `Aside` This component is useful for displaying secondary information alongside a page’s main content. #### `type` (optional) `info` `warning` `danger` `upgrade` default: `info` #### `title` (optional) `string` default: `null` #### Example with title ```mdx ``` #### Result #### Example without a title and a type (defaults to the `info` variant) ```mdx ``` #### Result ### `FileTree` Use the `` component to display the structure of a directory with file icons and collapsible sub-directories. #### Example ```mdx - .env.local - src - app - page.tsx ``` #### Result - src - app - layout.tsx - page.tsx - dashboard - page.tsx - next.config.ts - .env.local ### `YoutubeVideo` This will embed a YouTube video using [`lite-youtube`](https://github.com/justinribeiro/lite-youtube) behind the scenes. #### `videoId` (required) The YouTube video `id`. `string` #### `videoTitle` (optional) The video title. `string` default: `"Video"` #### Example ```mdx ``` #### Result ### `Tabs` To create a tabbed interface use the `` and `` components. Tabs are useful for grouping equivalent information where a user only needs to see one of several options. #### `: syncKey` (optional) A key used to keep multiple tab groups synchronized across multiple pages. `string` #### `: label` (required) A tab item must include a label attribute set to the text that will be displayed in the tab. `string` #### Example ```text frame="none" Sirius, Vega, Betelgeuse Io, Europa, Ganymede ``` #### Result Sirius, Vega, Betelgeuse Io, Europa, Ganymede #### Example with code ````text frame="none" ```text console.log("hello world!"); ``` ```php echo "hello world"; ``` ```` #### Result ```js console.log("hello world!"); ``` ```php echo "hello world"; ``` + diff --git a/public/_llms-txt/design.txt b/public/_llms-txt/design.txt new file mode 100644 index 000000000..4eb0c5adf --- /dev/null +++ b/public/_llms-txt/design.txt @@ -0,0 +1,296 @@ +--- +page_id: 3f4a5b6c-7d8e-9f0a-1b2c-3d4e5f6a7b8c +title: Kinde Documentation - Design +description: "Complete documentation for Kinde's design section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section for LLM training" +sidebar: + order: 1 +topics: + - llm + - documentation + - training + - design +sdk: [] +languages: + - markdown + - text +audience: developers +complexity: beginner +keywords: + - llm training + - documentation + - design + - section + - frontmatter + - metadata + - kinde +updated: 2025-09-18 +featured: false +deprecated: false +ai_summary: "Complete documentation for Kinde's design section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section for LLM training" +--- + +# Kinde Documentation - Design + +This is the complete documentation for Kinde's design section containing titles, descriptions, keywords, topics, and full content from all documentation files in this section. + +# Design - Brand - Apply unique branding for an organization + +> Comprehensive guide for applying unique branding to organizations including logo, favicon, theme, and color customization with API integration and reset functionality. + +organization branding, multi-tenancy, logo, favicon, brand colors, theme, API, reset branding +design, brand, organizations + +If your business model supports multi-tenancy or multiple user groups and you use [organizations](/build/organizations/multi-tenancy-using-organizations/) in Kinde, you can apply brand overrides to modify the pages in each organization. This means that when a user signs up or signs in to an organization, they have the brand experience associated with that organization, through page logo and colours. You can change the background, button, and text colours, as well as the favicon and logo for: - Sign up and sign in pages - Request access and subscription pages - Emails Custom sign in screens in Kinde ## To add or change a logo for an organization Logos must be under 1MB, and they are resized to have a maximum width or height of 120 pixels based on the aspect ratio. SVG works best as it displays well on any screen, but PNG and other formats are accepted. 1. In Kinde, go to **Organizations**. 2. In the list, select the organization you want to view. The organization **Details** page opens. 3. Select **Brand** in the left menu. The **Brand** page for the organization opens. 4. Scroll to the **Logo** section: 1. To remove an existing logo, select the trashcan icon. 2. To add a new or replace the logo, select **Upload image**. 5. Select **Preview** to see what your changes look like. 6. Select **Back** to exit the preview. 7. Select **Save** to apply the changes. 8. Test the change in your test or production environments. ## To add a logo via the Kinde Management API Use this endpoint `POST {{domain}}/api/v1/organizations/{org_code}/logos/light` For different logo variations, adjust the type path parameter (e.g., `light`, `dark`). In the Header, set a boundary value, e.g. `content-type: multipart/form-data; boundary="value"` Use `form-data` in the body to upload a valid PNG, JPEG, GIF, SVG, AVIF or WEBP image smaller than 1MB. You can also delete logos via the API. [See the API docs](https://docs.kinde.com/kinde-apis/management/#tag/organizations/post/api/v1/organizations/{org_code}/logos/{type}). ## To add or change a favicon for an organization Favicons are the tiny image shown on the tab of a browser. Image files must be a multiple of 48px square (e.g. 48x48, 96x96). 1. In Kinde, go to **Organizations**. 2. In the list, select the organization you want to view. The organization **Details** page opens. 3. Select **Brand** in the left menu. The **Brand** page for the organization opens. 4. In the **Favicon** section, select **Upload image** to add or replace a favicon. 1. Upload an **SVG** that will work in most browsers. 2. Add a **Fallback** image in PNG for other browsers. 5. To preview a favicon, you’ll need to save it and check in your test or live environment. 6. To remove a favicon, select the trashcan icon near the image. 7. Select **Save** to apply the changes. ## Add an avatar for an organization If your organizations manage their own profile or payment details via a [Kinde self-serve portal](/build/self-service-portal/self-serve-portal-for-orgs/), you can upload an avatar to personalize the experience for organization members. An avatar is usually a simple logo. Avatars must be in SVG format, and be smaller than 5kb. They appears as a 36px square in the interface. 1. In Kinde, open the organization details and go to **Brand** in the menu. 2. In the **Avatar** section, select **Upload image**. 3. Select **Save**. ## Set a light or dark theme 1. In Kinde, go to **Organizations**. 2. In the list, select the organization you want to view. The organization **Details** page opens. 3. Select **Brand** in the left menu. 4. Set the **Theme**: **Light**, **Dark**, or **User preference**. If you select user preference, make sure you choose a brand color scheme for both experiences. See below. 5. Select **Save**. ## Set brand colors for an organization 1. In Kinde, go to **Organizations**. 2. In the list, select the organization you want to view. The organization **Details** page opens. 3. Select **Brand** in the left menu. The **Brand** page for the organization opens. 4. Change the following elements to appear how you want: background, buttons, text color, link color, and button border radius. 5. Select **Preview** to see what your changes look like. 6. Select **Save** to apply the changes. ## Reset organization brand to match global styles If you want to revert to global styles for an organization, it is easy to reset. 1. In Kinde, go to **Organizations**. 2. In the list, select the organization you want to view. The organization **Details** page opens. 3. Select **Brand** in the left menu. The **Brand** page for the organization opens. 4. In the bottom section called **Admin actions**, select **Reset to default**. 5. Select **Save**. This removes logo, color schemes, etc. + +# Design - Brand - Set global brand defaults + +> Guide for setting global brand defaults including logo upload, favicon configuration, theme selection, and brand color customization for authentication pages. + +global brand, logo, favicon, theme, brand colors, light theme, dark theme, user preference +design, brand, customization + +When users sign up or sign in to your product, they land on pages generated by Kinde. You can update the look of these pages to match your brand. You also have the option to bring your own page design to the authentication experience. See - [Custom design with code](/design/customize-with-code/customize-with-css-html/) - [Custom sign-up and sign-in pages](/authenticate/custom-configurations/custom-authentication-pages/). ## Setting global brand elements You can choose to set a global theme for all pages, or else use global settings as a fallback for custom page designs. Use the following procedures to make design changes to suit your brand. ## Add your company logo Logos must be under 1MB, and they are resized to have a maximum width or height of 120 pixels based on the aspect ratio. SVG works best as it displays well on any screen, but PNG and other formats are accepted. 1. In Kinde, go to **Design > Global > Brand**. 2. In the **Logo** section, upload your company logo. Make sure images are less than 1MB, are PNG, JPEG, or GIF. 3. Scroll down to the bottom of the page and select the global logo fallback behavior. - Enable to use the global logo as a fallback default for organizations where the logo is not available. This means the end customer will see the organization logo, if not the global level logo, and failing that, the name of the organization. - Disable if you want the default behavior to be show the organization logo, then the organization name, and as a last option show the global logo. 4. Select **Save**. ## Add favicons for web browsers Favicons are small icons that appear on browser tabs. To add them to Kinde, they must measure 48x48px (or multiples of, such as 96x96). ![image of browser favicons](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/f4cc6e0f-3f87-46af-f99d-7c4910602600/public) 1. In Kinde, go to **Design > Global > Brand**. 2. In the **Favicon** section: 1. Add one as SVG format (so it works in most browsers). 2. Add one as a **Fallback** PNG for other browsers, such as Safari. 3. Select **Save**. To change the favicon of an organization, see [Apply unique branding for an organization](/design/brand/apply-branding-for-an-organization/). ## Add an avatar for your business To personalize you Kinde experience, add an avatar for your business to display your logo or preferred image in the Kinde user interface. For example, an avatar appears on the home page in the bottom left where you can access business and profile controls. Avatars must be in SVG format, and be smaller than 5kb. They appears as a 36px square in the Kinde interface. 1. In Kinde, go to **Design > Global > Brand**. 2. In the **Avatar** section, select **Upload image**. 3. Select **Save**. ## Set a light or dark theme 1. In Kinde, go to **Design > Global > Brand**. 2. Set the **Theme**: **Light**, **Dark**, or **User preference**. If you select user preference, make sure you choose a brand color scheme for both experiences. See below. 3. Select **Save**. You can [change the light and dark theme settings for your organizations](/design/brand/apply-branding-for-an-organization/) as well. ## Set brand colors for page elements Your selections will be inherited across all pages and for all organizations, unless you set overrides. 1. In Kinde, go to **Design > Global > Brand**. 2. Select settings and colors for **Pages (backgrounds)**, **Cards**, **Buttons,** **Input fields**, and **Links**. Be sure to set a light and dark version of each if you want your brand colours to appear in both modes. 3. Select **Save**. 4. To preview pages, open the page using the side menu and select **Preview** in the top right. To set the brand color scheme of an organization, see [Apply unique branding for an organization](/design/brand/apply-branding-for-an-organization/). + +# Design - Brand - Add homepage URL to the sign-in page + +> Guide for adding homepage URL to sign-in pages so business logos link to application homepages and provide error recovery navigation. + +homepage URL, sign-in page, application homepage, logo link, callback URLs, error handling +design, brand, applications + +To link to your application’s homepage from your sign in page, you need to add a homepage URL to each of your applications. Once you do this: - Your business logo on the sign-in page will link to your application homepage - If a browser or other error occurs, we can provide a link to your user, to get them back to your application homepage ## Set the homepage URL for your applications 1. In Kinde, go to **Setting > Applications**. 2. Select **Configure** on the relevant application. 3. In the left menu, select **Authentication**. 4. Scroll to the **Callback URLs** section. 5. Add the **Application homepage URI**, e.g. `https://app.yourapp.com` 6. Select **Save**. 7. Repeat for each relevant application. + +# Design - Brand - Remove Kinde branding from sign in pages + +> Simple guide for removing Kinde branding from sign-in pages for paid plan users through business settings configuration. + +remove branding, Kinde branding, sign in pages, paid plans, business details +design, brand, customization + + If you have a paid Kinde account, you can remove the Kinde branding from sign in pages. 1. In Kinde, go to **Settings > Business > Details.** 2. Switch off the **Show Kinde branding** switch. 3. Select **Save**. + +# Design - Content customization - Customize email content + +> Guide for customizing email content including sender details, logo configuration, OTP email customization, and multi-language support for authentication emails. + +email customization, email sender, email logo, OTP email, passwordless auth, SMTP, business name +design, email, content-customization + +If emails are part of your authentication processes for users - for example, users receive sign-in codes via email in a passwordless process - you can customize email details, with some limitations. ## **Change the email sender** **name** You can add your business or brand name so it appears as the sender of emails. 1. Go to **Settings > Email**. 2. Enter your business or brand name in the **Sender** name field. 3. Select **Save**. ## Change the email sender address If you want to change the email sender address, you add your own email provider’s SMTP details. See [Customize email sender](/get-started/connect/customize-email-sender/). ## **Change email logo** Emails inherit the logo you set as part of your [global brand](/design/brand/global-brand-defaults/). But you can also set a unique logo [for each organization](/design/brand/apply-branding-for-an-organization/) in your business. ## Change who verification emails are sent from _Only applies if you choose not to send emails from your own provider_ When Kinde sends an email on your behalf, it is sent from the ‘Business name’ listed in your Kinde business by default. For example: If you want emails to come from your app name instead (if it is different), then you can edit the business name in **Settings > Business > Details**, without it affecting your Kinde domain or other environment settings. ## Change the content of the one-time passcode (OTP) email (passwordless auth) You can change the content of the OTP email if you use a [custom email sender](/get-started/connect/customize-email-sender/) for sending OTP emails. Once this is set up, you can make content changes as follows. 1. In Kinde, go to **Design > Emails > Email content.** 2. Select the language you want to edit. Only [languages you have selected](/design/content-customization/set-language-for-pages/) in your business are available. 3. You can edit the subject line, body content, and disclaimer footer. Use the placeholders to personalize and define where the code appears. 4. When you have made your changes, select **Save**. The new email content will now be sent. ## Add sign-in code to the email subject line (passwordless auth) You can include the sign-in code in the subject line of OTP emails to make it visible for users in notifications. Note that it is less secure to do this, as the code can be seen by anyone when notifications are displayed openly on devices. 1. In Kinde, go to **Design > Emails > Email content.** 2. Select the language you want to edit. Only [languages you have selected](/design/content-customization/set-language-for-pages/) in your business are available. 3. In the subject line field, include the `${code}` placeholder. This is where the code will appear. E.g. Enter `${code}` for access. 4. Select **Save**. + +# Design - Content customization - How content is managed in Kinde + +> Overview of content management in Kinde including editable page elements, multi-language support, and available authentication pages for customization. + +content management, page content, multi-language, authentication pages, sign up, sign in, error messages +design, content-customization, multi-language + +You can change the content for the main pages that your users see as part of authentication. You’re also able to manage the content in [all the languages you have selected](/design/content-customization/set-language-for-pages/) in Kinde. Currently, you can edit content for the following pages: - Sign up - Sign-up confirmation - Sign in - Sign-in confirmation - Request access form - Verify password Additional screens will be added, including error screens, in the coming months. ## What can be edited? You can edit the following page content: - Sign-up page: General page elements, consent, disclaimer, privacy, T&C acceptance, some error messages - Sign-in page: General page elements plus 'Account not found' error message - Verify password page: General page elements, error messages, helper text For the confirmation and request access form pages, you can edit the general page elements. Go to Design > Page content. + +# Design - Content customization - Manage languages on user facing pages + +> Comprehensive guide for managing languages on user-facing pages including language selection, default language configuration, language detection, and widget translation support. + +language management, multi-language, internationalization, RTL languages, language detection, default language, Kinde widget +design, content-customization, multi-language + +By default, all Kinde user-facing screens (for example the sign up and sign in screens) are in US English. However, you can make your end-user experience more international by selecting multiple languages for these screens as well. ## What gets translated? Only the user facing pages are translated. This includes, sign up, sign in, verification code, confirmations, one-time code emails. It is not yet possible to select a different language for the whole Kinde platform. To change the language displayed on sign up and request access pages, you need to [customize the relevant page](/design/brand/global-brand-defaults/). ## Supported languages Kinde’s language support offering is growing all the time. Here’s just a sample of what we have so far: English (en / en-US / en-AU / en-GB), Dutch, German, Polish, Hebrew, Italian, French, Malay, Spanish, Russian, Portuguese (Brazilian), Norwegian, Swedish. We aim to eventually support [all these languages](https://github.com/kinde-oss/kinde-translations#language-codes). Feel free to submit a pull request via [GitHub](https://github.com/kinde-oss/kinde-translations) to request or contribute a specific language translation. ## Choose languages Kinde will display the relevant language on authentication screens, when the user’s regional settings are detected. 1. Go to **Settings > Languages**. 2. In the **Supported languages** section, select the checkboxes of all the languages you want to support. Includes support for right to left (RTL) languages. ## Change the default language The default language is the fallback language if a user’s region is not detected, or if the detected language is not selected as supported in Kinde. 1. Go to **Settings > Languages**. 2. In the **Default language** dropdown, choose the language you would like to display as standard. ## How Kinde displays languages For user-facing authentication screens, Kinde gives display priority using language detection, as follows: 1. The language supplied in the auth url ^ 2. The preferred language selected in the user’s browser ^ 3. The default language you have selected in Kinde 4. US English as a last resort, if a translation is not available ^ If you have chosen not to support a language, we will try the next available option. Through language matching, Kinde automatically works out the closest base language to the requested language and will use this if supported by your app. ## Translation of content in the Kinde widget Translations inside of the Kinde widget are taken care of by Kinde. We will grab the copy from the relevant route and language from your [page content settings](/design/content-customization/update-auth-page-content/) and apply them to the widget. ## Customize text on authentication pages You can customize the text on various pages in the auth flow. See [Update page content for the auth flow](/design/content-customization/update-auth-page-content/) for more information. Kinde provides relevant localized content within the `context` object that is passed into the Page default function as mentioned above. Localizations and placeholder replacements are handled for you at run time. For example: ```jsx const {content} = event.context.widget; } alt={content.logoAlt} /> {content.pageTitle}

{content.heading}

{content.description}

``` + +# Design - Content customization - Update page content + +> Guide for updating authentication page content including multi-language support, text variables, and escape route URL configuration for error handling. + +page content, content customization, text variables, multi-language, auth pages, escape route URL, preview +design, content-customization, multi-language + +For maximum extensibility, page content has been decoupled from the page itself. This lets you update the copy on most screens, which you can do via the **Page content** section of the admin area (see below) or via API (coming soon). ### Update page content If your application is built for [multiple languages](https://docs.kinde.com/design/pages/set-language-for-pages/), select these first in Kinde. 1. In Kinde, go to **Design > Page content**. 2. Select the language you want (only applicable if multiple languages are configured). 3. Select the page you want to edit. The list of content shown corresponds with page elements such as headings, field labels, helper text, error messages, etc. 4. Make the changes to the content. If you want, you can use text variables, explained below. 5. When you’ve finished, select **Save**. The save only applies to the current language and page selected. You need to select **Save** again if you edit in different languages. 6. Check changes by selecting **Preview**. You'll only see an accurate preview if the environment is fully connected, otherwise you may see errors. 7. Repeat from step 2 for each language and page you want to edit. ### Text variables for page content Variables are used to stand in for actual values that you want to appear on pages. They are a way of automating content. For example, if you use the `${email_address}` variable, the user’s email address will be shown. Variables can be used on pages as follows. **Sign in confirm code page** `${email_address}` - shows the full email address of the user `${email_address_obfuscated}` - shows only a part of the user's email **Sign up confirm code page** `${email_address}` ### Include ‘escape route’ URL in auth errors When auth errors appear, you want to give users a way to navigate out of them. To provide an ‘escape route’ URL in these situations: 1. In Kinde, go to **Settings > Applications** and select **View details** on your application. 2. Enter your website URL into the **Application homepage URI** and **Application login URI** fields. 3. Select **Save**. + +# Design - Customize with code - Connect your repo for custom pages + +> Guide for connecting GitHub repositories for custom page design including directory structure setup, code preview options, and status monitoring. + +connect repo, custom pages, GitHub, custom domain, code preview, directory structure, code status +design, customize-with-code, git + +To enable your custom code to override Kinde page design, you need to set up and connect a git repo for the design files. You must also be using a [custom domain](/build/domains/pointing-your-domain/) to run your custom code with Kinde. ## Connect your repo 1. Go to **Design > Custom code**. 2. Select the option to **Connect repo**. This will take you to the **Settings > Git Repo** page where you can manage your repo connection for design and workflows. 3. If you don’t already have a repo set up for workflows, select **Connect GitHub**. 4. Follow the prompts to connect a repo and branch. ## Option to enable code preview If you are on the Kinde Plus or Scale plan, you can enable a code preview before you deploy new code to be live. This is helpful for checking the design before making it public in your production environment. If you have a free or Pro plan, we recommend you preview designs in a non-production environment before syncing in production. ## Set up the Git directory structure Your directory structure should follow the following structure. ```jsx myApp/ ├── kindeSrc/ │ └── environment/ │ └── pages/ │ └── (kinde)/ │ └── / │ └── page.tsx ├── package.json └── kinde.json ``` In the above example, `` is used to map your code to a rendered page in Kinde. For example `kindeSrc/environment/pages/(kinde)/(register)/page.tsx` will map to the register / sign up page in the authentication flow. ## Code status alerts The home page of your Kinde dashboard shows a code alert status. You can see immediately if there are any concerns with your code. Select **View code status** to see if the issue is: - a code sync problem - a workflow code problem - a design custom code issue + +# Design - Customize with code - Review custom code logs + +> Guide for reviewing custom code logs including sync, build, and runtime logs for debugging deployment issues and troubleshooting code problems. + +custom code logs, sync log, build log, runtime log, debugging, deployment errors, troubleshooting +design, customize-with-code, logs, debugging + +There are several logs that can be checked when something goes wrong. ## Sync log Check to see if your code is syncing to Kinde and is able to be deployed. Issues with sync logs are most commonly associated with missing files or other directory issues. Go to **Settings > Git repo > Sync log**. ## Build log A build log is generated for each deployment. It provides details on the deployment checks, showing a success or fail message. 1. Go to **Design > Custom code**. 2. Select **Deployments** in the menu. 3. Select the specific deployment you want to view. 4. Scroll to the **Build log** section. For each page included in the deployment, open the dropdown to view the build details. We recommend fixing all the errors detected during this process and syncing your code again. This generates a new deployment and new code check. ## Runtime log Runtime logs record events that occur when your code is running. When something goes wrong, you can check runtime logs to see what happened. 1. Go to **Design > Custom code**. 2. Select **Runtime logs** in the menu. 3. Select the runtime ID to open a details page. 4. Scan the logs for errors. + +# Design - Customize with code - Apply custom styling per application + +> How to apply custom styling per application using the Client ID attribute and conditional rendering. + +custom CSS, custom HTML, conditional rendering, custom domain +design, customize-with-code, css, styling + +You can apply unique HTML and CSS styling to each Kinde application within the same business account. Although you can only connect one Git repository for your custom pages, you can use conditional rendering to serve different designs based on which application is being accessed. This guide will walk you through how to use the application's **Client ID** to render unique styles and layouts. This doc is based on the tests and implementation we ran and provides example code, folder layout, and implemention checklist. The **clientID** is a unique identifier assigned to each application in Kinde. This value distinguishes one app from another, allowing your template code to detect which application is active and render the appropriate HTML and CSS for each app accordingly. ## Solution: Conditional rendering The key to this solution is the `clientId`, a unique identifier assigned to every application you create in Kinde. This ID is passed in the `request` object to your custom pages. By checking the value of the `clientId`, your code can determine which application is active and render the corresponding HTML and CSS. This process happens server-side, so there's no performance loss for your users. ## Before you begin - Set up a [custom domain](/build/domains/pointing-your-domain/) for your Kinde business. - Connect a [Git repository](/design/customize-with-code/connect-repo/) to manage your custom pages. - Make sure your custom design files are already working. Follow [this guide](/design/customize-with-code/customize-with-css-html/) for more details. ## Step 1: Set up file structure Your repository needs to follow a specific structure for Kinde to recognize the files. For this example, we are using the simplest structure with the `(default)` folder to act as a fallback and a `page.tsx` file within it. This file will contain your conditional logic. ``` myApp/ ├── kindeSrc/ │ └── environment/ │ └── pages/ │ └── (kinde)/ │ └── (default)/ │ └── page.tsx │ └── layout.tsx ├── package.json └── kinde.json ``` For this specific example, we focus on the default design, but you can use this for your sign up and sign pages as well. ## Step 2: Find the Client ID In your `page.tsx` file, you can access the `clientId` from the `request` object that is passed to your page component. ```js const DefaultPage: React.FC = async ({ context, request }) => { let clientId = request.authUrlParams?.clientId || null; // ... rest of your code };` ``` ## Step 3: Implement the conditional logic Now you can use the `clientId` variable to build your conditional logic. For example, you can use an `if/else` statement, a `switch` statement, or a ternary operator to render different JSX for each application. The following example shows how to render different content for three separate applications (Next.js, Python, and Nuxt.js), with a default fallback. ### `kindeSrc/environment/pages/(kinde)/(default)/page.tsx` ```js 'use server'; import { getKindeWidget, fetch, type KindePageEvent, } from '@kinde/infrastructure'; import React from 'react'; import { renderToString } from 'react-dom/server.browser'; import Layout from '../../layout'; const DefaultPage: React.FC = async ({ context, request }) => { // 1. Access the client ID from the request object let clientId = request.authUrlParams?.clientId || null; // Environment variables const BUILDER_API_KEY = process.env.BUILDER_API_KEY; const CLIENT_ID_NEXT_APP = process.env.CLIENT_ID_NEXT_APP; const CLIENT_ID_PYTHON_APP = process.env.CLIENT_ID_PYTHON_APP; // Example: Fetching dynamic content (optional) const res = await fetch( `https://cdn.builder.io/api/v3/content/login-page-data?apiKey=${BUILDER_API_KEY}&sort.createdDate=-1`, { headers: {}, method: 'GET', } ); const { loginPageImage, signInFormTextTop, signupFormTextTop, signInFormTextBottom, signupFormTextBottom, } = res?.data?.results?.[0]?.data || {}; const isUserOnLoginOrRegisterPage = request?.route?.flow; return ( {/* 2. Use conditional rendering based on the client ID */} {clientId == CLIENT_ID_NEXT_APP ? (
{/* Content for the Next.js App */}

Styling for the First App - Next.js

Client ID: {clientId}

{getKindeWidget()}
) : clientId == CLIENT_ID_PYTHON_APP? (
{/* Content for the Python App */}

Styling for the Second App - Python

Client ID: {clientId}

Company Contact Country
Alfreds Futterkiste Maria Anders Germany
{getKindeWidget()}
) : (
{/* Fallback content for any other app (e.g., Nuxt app) */}

Default Kinde Authentication Page

Client ID: {clientId || 'Not available'}

{getKindeWidget()}
)}
); }; // Page Component export default async function Page(event: KindePageEvent): Promise { const page = await DefaultPage(event); return renderToString(page); } ``` The custom CSS for classes like `.container` and `.container-2` would typically be defined in your `layout.tsx` file or in a separate CSS file. ## Expected output for custom designs per application When a user authenticates through each of your applications, they will see a different page design based on your conditional logic. The examples below are not over-designed, but you could make them as distinct as you want. - **Next.js App (`clientId`: `ca3c184xxxxxxd842777bc***xxxx`)** - The user will see the content inside the first block, with the heading "Styling for the First App - Next.js". ![An image of how the page for the Next.js app looks after the conditional rendering is applied](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/b78f5a38-8c84-4b2c-5759-9df24aa61700/public) - **Python App (`clientId`: `c41376xxxxxx244b3122dd***xxxx`)** - The user will see the second block, with the heading "Styling for the Second App - Python" and a custom HTML table. ![An image of how the page for the Python app looks after the conditional rendering is applied](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/b161fbec-4144-4975-8561-a4fb6b1d8500/public) - **Nuxt.js App or any other app (`clientId`: `730c34be0xxxxxxe206ec07***xxxx`)** - Since this ID doesn't match the first two conditions, the user will see the final fallback block with the heading "Default Kinde Authentication Page". ![An image of how the page for any other app (default) would look after the conditional rendering is applied](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/9aacda1b-2583-4226-48c7-3dcd09981100/public) + +# Design - Customize with code - Custom UI examples + +> Collection of custom UI examples and starter templates including SplitScape, Evolve.ai, Orbit, and Bark & Bite for different design themes and use cases. + +custom UI examples, starter templates, React Server Components, SplitScape, Evolve.ai, Orbit, Bark & Bite +design, customize-with-code, examples + +View examples to help you get started with Kinde custom UI. ## Example repos Fully customizable UI starter templates built with React Server Components: - [SplitScape](https://github.com/kinde-starter-kits/custom-ui-splitscape) - Professional and friendly, with room to grow. **Theme:** Clean, flexible, balanced **Description**: A well-balanced, two-column layout that suits a broad range of industries—from SaaS to marketplaces. Social login options are prominent, and the welcome message is clear and reassuring. Great default for teams who want flexibility without committing to a niche tone. - [Evolve.ai](https://github.com/kinde-starter-kits/custom-ui-evolve-ai) - Simple, focused, and designed to convert. **Theme:** Futuristic, minimalist, product-led **Description:** A no-frills, gradient-backed sign-in screen with clear CTA flow. Designed for AI products, productivity tools, or platforms that want a polished, tech-forward look while keeping the user’s focus on getting started fast. - [Orbit](https://github.com/kinde-starter-kits/custom-ui-orbit) - Built for launch-ready teams with a bold aesthetic. **Theme:** Dark mode, sci-fi, and startup energy **Description:** A sleek, dark-themed template with interstellar vibes. Perfect for tech startups, crypto products, and developer tools that want to signal modernity and momentum. - [Bark & Bite](https://github.com/kinde-starter-kits/custom-ui-barknbite) - Warm, approachable, and built to delight. **Theme:** Friendly, natural, lifestyle **Description:** Soft colors and charming personality make this template ideal for lifestyle brands, pet-related businesses, or companies targeting families and individuals. + +# Design - Customize with code - Customize designs with code + +> Overview of customizing Kinde designs with HTML, CSS, and JavaScript including widget customization, page design, and content management layers. + +custom design, CSS, HTML, JavaScript, custom domain, Kinde widget, page customization, code management +design, customize-with-code, css, html + +Kinde gives you the ability to bring your own HTML / CSS and JavaScript to our hosted pages. For security, your custom code will only be run on a custom domain. These are free to use in Kinde - [set up a custom domain](/build/domains/pointing-your-domain/). There are three layers which make up design customization in Kinde: - **The Kinde widget** - This is the ‘form’ that shows on each screen where end users interact, such as where they input and confirm their auth credentials, enter OTPs, etc. You can change the layout and design of widget elements. - **The page** - the page on which the widget appears, includes background colour, images, footer, location of the widget on the page, etc. - **Copy / translations** - the content that appears in and around Kinde widgets, including field labels, headings, button text, etc. You can update content for all the languages you have selected in Kinde. ![Image of sign in page as an example of page parts](https://imagedelivery.net/skPPZTHzSlcslvHjesZQcQ/361adeeb-53f5-46d4-1223-b66eabf96e00/public) It's important to understand how to work with each of these elements, before getting too far along the custom code path. Learn more about: - [The widget](/design/customize-with-code/kinde-widget/) - [Working with pages](/design/customize-with-code/understand-page-design/) - [Content control](/design/content-customization/how-content-is-managed/) ### Code management Your code for your pages will live in a GitHub repository (other git providers to be supported later). For details see [Connect your repo](/design/customize-with-code/connect-repo/). + +# Design - Customize with code - Design inspection with DevTools + +> Guide for inspecting Kinde widget components using browser DevTools including style hooks, CSS settings, and debugging techniques across different browsers. + +DevTools, design inspection, style hooks, CSS settings, browser debugging, element inspection, Safari, Chrome, Firefox +design, customize-with-code, devtools, debugging + +It's helpful to be able to inspect the Kinde widget components and layouts, using DevTools. This lets you: - view [settings](/design/customize-with-code/styling-with-css/) applied to a component or layout, especially when they aren’t defined under `:root`. - get the [style hook](/design/customize-with-code/style-with-style-hooks/) of an element. You can learn more about DevTools in browser documentation. Here's a few common examples: - [Apple Safari](https://developer.apple.com/documentation/safari-developer-tools) - [Google Chrome](https://developer.chrome.com/docs/devtools?hl=en) - [Microsoft Edge](https://learn.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/landing/) - [Mozilla Firefox](https://firefox-source-docs.mozilla.org/devtools-user/) ## Step 1: Open DevTools Most browsers follow a similar approach for opening DevTools. Here’s a quick guide. **Right-click method:** 1. Right-click anywhere on the page. 2. From the context menu, select **"Inspect"** or **"Inspect Element"**. **Keyboard shortcut:** - `Ctrl + Shift + I` (Windows/Linux). - `Cmd + Option + I` (macOS). **Menu navigation:** 1. Open your browser’s menu (three dots or lines in the top-right corner). 2. Select **More tools** **>** **Developer Tools/Web Developer Tools**. In Safari, go to the top menu bar and select **Develop > Show Web Inspector**. If you don’t see the **Develop** menu item, you’ll need to enable it: 1. In the top menu bar, go to **Safari > Settings**. 2. Open the **Advanced** tab. 3. Check **Show features for web developers**. ## Step 2: Locate in HTML Once DevTools is open: 1. On the page, right-click the element you want to inspect. 2. From the context menu, select **Inspect** or **Inspect Element**. 3. The element will be highlighted and focused to in the **Elements** (or **Inspector**) tab. 4. All widget components and layouts have style hooks on them: `data-kinde-[…]`. 5. Click the arrow (▸) icon next to the element to expand its child elements. ## Step 3: View settings Once a component or layout is located in the HTML: 1. On the page, right-click the element you want to inspect. 2. From the context menu, select **Inspect** or **Inspect Element**. 3. In the **Styles** (or **Rules**) panel, the element’s CSS rules will be displayed, revealing the settings applied to it. 4. Look for `--kinde-[…]` instances to identify the settings specific to the component or layout. If a `--kinde-[…]` setting is explicitly defined, clicking on it will navigate to its definition at the document root, where its value is set. Most browsers also display the setting’s value in a tooltip when hovered. If the setting is not defined and relies on a fallback, it will appear inactive and cannot be clicked. 5. To view state-specific settings: 1. In the **Elements** (or **Inspector**) tab, right-click the element (some browsers may include a menu button next to the element for this action). 2. From the context menu, select **"Force state"** (or **“Change Pseudo-class”** or **“Forced Pseudo-Classes,”** depending on the browser). 3. Choose the desired state from the list. + +# Design - Customize with code - Working with the Kinde widget + +> Guide for working with the Kinde widget including customization options, authentication flow settings, MFA configuration, and error handling for form components. + +Kinde widget, form components, CSS customization, authentication flow, MFA, error handling, branding +design, customize-with-code, widget + +The Kinde widget is a core element in Kinde page design. The components that make up the widget have been specifically designed to be easily overridden by your own CSS so you can give it the look and feel of your brand whilst keeping best in class security. The widget refers to a specific form component that lives on the page, that consists of fields, labels, cards, buttons, text strings with URLs, and the 'Built with Kinde' logo. Most styles can be switched out using our suite of [CSS custom properties](/design/customize-with-code/styling-with-css/) but for more complex customizations, we have provided [style hooks](/design/customize-with-code/style-with-style-hooks/) that you can use to completely replace everything. Before designing the elements of the widget and page, fully set up authentication and user access flow, as these impact what is shown in the widget. ## Change what appears in the widget ### Settings for all widgets - [Remove Kinde branding](/design/brand/remove-kinde-branding/) - available only on paid plans ### Settings for the sign in flow - [Auth options](/authenticate/authentication-methods/set-up-user-authentication/) (org or application level configuration) - Create account link - hidden if registrations are disabled ### Settings for the register flow - [Auth options](/authenticate/authentication-methods/set-up-user-authentication/) (org or application level configuration) - [Ask first name / last name](/authenticate/custom-configurations/authentication-experience/) - [Show marketing widget](/authenticate/custom-configurations/authentication-experience/) - [Show “already have account” link](/authenticate/custom-configurations/authentication-experience/) - [Privacy / terms of use links](/manage-users/access-control/accept-policies-signup/) ### Settings for the MFA method - [MFA options](/authenticate/multi-factor-auth/enable-multi-factor-authentication/) (org or application level configuration) ### Settings for errors Follow [this procedure](/design/brand/link-to-homepage/) to include ‘escape hatch’ URLs for errors during the auth flow. + +# Design - Customize with code - Manage custom code deployments + +> Guide for managing custom code deployments including code preview, syncing, making deployments live, and rollback functionality for Plus and Scale plan users. + +custom code deployment, code preview, sync code, rollback, Plus plan, Scale plan, GitHub integration +design, customize-with-code, deployment + +Each time your code is synced to Kinde, a new deployment is created. A deployment is a unique point-in-time process that checks the code, which can then be made live. ## Enable code preview Kinde Plus and Scale plan customers are able to preview the design before setting the code live in the production environment. In **Settings > Git repo**, switch on the **Enable preview mode** option. If this setting is not available to you as a Free or Pro plan user, we suggest you use non-production environments to check your designs before deploying to production. ## Sync code Every time you change your code in GitHub, you must sync those changes back to Kinde so you can make them live. 1. Go to **Design > Custom code**. 2. Select **Sync code**. A new deployment is generated on click. If the deployment is successful, you will be able to make it live. ## Make a deployment live 1. Go to **Design > Custom code**. The **Summary** page shows which deployment is live and which is ready to go. 2. If you want, select **Sync code** to get the latest deployment. 3. Select **Deployments** in the menu. A list of current and previous deployments is shown. 4. Find the deployment you want to make live and select **Make live** in the three dots menu. ## Roll back a deployment To roll back a deployment, you just need to make a previous deployment live. 1. Go to **Design > Custom code**. The **Summary** page shows which deployment is live and which is ready to go. 2. Select **Deployments** in the menu. A list of current and previous deployments is shown. 3. Find the previous deployment you want to roll back to and select **Make live** in the three dots menu. This will override the current live deployment. + +# Design - Customize with code - Manage assets + +> Guide for managing design assets including Kinde-hosted favicons and logos, external assets, and Content Security Policy compliance for custom domains. + +design assets, favicons, logos, external assets, CSP, Content Security Policy, organization logos +design, customize-with-code, assets + +It is likely that your logos and favicons are managed in Kinde, but you may also manage externally hosted assets like stylesheets, fonts, and images. ## Kinde hosted assets Within your custom code you can reference assets which have been uploaded within the Kinde admin area. The Kinde infrastructure package ships with helper methods for accessing these: ### Favicons ```jsx import {getFallbackFaviconUrl, getSVGFaviconUrl} from "@kinde/infrastructure"; ``` #### Usage ```jsx ``` ### Logos ```jsx import {getLogoUrl, getDarkModeLogoUrl} from "@kinde/infrastructure"; ``` #### Usage ```jsx // Always use light logo {event.context.widget.content.logoAlt} // Always use dark logo {event.context.widget.content.logoAlt} // User preference

{heading}

{description}

{getKindeWidget()} // our footer won't change so exclude from re-rendering
// some content here
``` This means that only critical page items are being re-rendered. + +# Design - Customize with code - Pages and the Kinde Management API + +> Guide for integrating Kinde Management API with custom pages including M2M setup, environment variables, and common API calls for B2B applications. + +Kinde Management API, M2M application, API calls, server rendering, environment variables, organization API, bindings +design, customize-with-code, api + +Pages are rendered on the server which means it is possible to make API calls before the page is delivered to the browser. The most common use case for this is calling the Kinde Management API to get additional information for the page. ## Before using the Kinde Mangement API for pages 1. [Create an M2M application](/developer-tools/kinde-api/connect-to-kinde-api/) within Kinde and grant it access to the Kinde Management API with the desired scopes. 2. Setup environment variables in Kinde to provide the client ID and secret. By default the `createKindeAPI` method initially looks up the following environment variables setup in Kinde settings to determine the application to use. - `KINDE_WF_M2M_CLIENT_ID` - `KINDE_WF_M2M_CLIENT_SECRET` - Ensure this is setup with sensitive flag enabled to prevent accidental sharing `createKindeAPI` can also accept an additional parameter which can contain `clientID/clientSecret` or `clientIDKey/clientSecretKey` which can define the environment variables to look up. ## Calling the Kinde Management API for pages The example below calls the `environment` API and adds the logo to the page. **Required bindings** ```js export const pageSettings = { bindings: { "kinde.env": {}, "kinde.fetch": {}, url: {} } }; ``` Example usage calling Organization API: ```jsx export default async Page(event: onPageRequestEvent) { const orgCode = event.request.authUrlParams.orgCode; const kindeAPI = await createKindeAPI(event); const { data: res } = await kindeAPI.get({ endpoint: `organization?code=${orgCode}`, }); const {org} = res; return ` Hello world

{org.name}

`; } ``` ## Common API calls for custom page design - `GET /environment` - includes brand settings for the environment including logos / background images. Required M2M scope: `read:environments` - `GET /organizations?org_code=${request.authUrlParams.orgCode}` brand settings for the requested org including logo. Required M2M scope: `read:organizations` - `GET /business` - business details like the business name. Required M2M scope: `read:businesses` - `GET /applications/${request.authUrlParams.clientId}`. Required M2M scope: `read:applications` + +# Design - Customize with code - Libraries and packages for pages + +> Guide for using npm packages and libraries in Kinde page designs including supported packages, React templates, and development dependencies. + +npm packages, libraries, React, Liquid, dev dependencies, runtime environment +design, customize-with-code, packages + +As part of bringing your own code to page designs, you'll likely need to work with some `npm` libraries in addition to the `@kinde/infrastructure` package. Kinde supports a handful of carefully selected libraries from `npm`. These include: `@kinde/infrastructure` This is Kinde’s package that supplies helpers and methods to give you the best possible authoring experience of Kinde pages and workflows. For server side React templates: `react` and `react-dom/server.browser` For Liquid templates: `liquidjs` Attempting to import unsupported packages into your runtime code will result in your deployment failing. Dev dependencies (e.g packages used for linting, tests and build steps) can be used, as they do not affect the Kinde runtime environment. Any code dependent on these packages should be prebuilt before deploying to Kinde. + +# Design - Customize with code - Preview custom code + +> Guide for previewing custom code designs using preview credentials and auth flow testing for Plus and Scale plan users. + +preview custom code, pages_mode, preview password, Plus plan, Scale plan, auth flow +design, customize-with-code, preview + + Unlike changes you make in the Kinde UI that impact page layouts and content, your custom designs can’t be viewed in a Kinde-generated preview. Instead, you can test designs using your real auth flow, using preview credentials. ## Preview custom code 1. In your application code, pass the additional auth url parameter `pages_mode=preview`. When the auth flow is initiated a password screen will appear which is required to view the preview. 2. Enter your preview password. Go to **Design > Custom code > Preview**. 3. Copy the **Password** and use it in the authentication request. The preview will show the latest code deployment version. + +# Design - Customize with code - Quick start guide + +> Quickly set up and run your first Kinde workflow in minutes. + +quick start, custom UI, GitHub template, React Server Components, custom domain, workflow setup +design, customize-with-code, quick-start + +The quickest way to see an end-to-end example of custom HTML/CSS and JS running on Kinde hosted pages is to follow this guide. ## What you need - A Kinde account with an application set up on a [custom domain](/build/domains/pointing-your-domain/). - A GitHub account to host your code. ## Step 1: Clone a Kinde example template 1. Sign in to your GitHub account and go to [Kinde example Splitscape Custom UI template](https://github.com/kinde-starter-kits/custom-ui-splitscape). 2. Select the green **Use this template button**. 3. Select **Create a new repository**. This will create a new repository in your GitHub account with a copy of the example code. It contains a a fully customizable UI starter template built with React Server Components. ## Step 2: Connect your GitHub repository to Kinde 1. Sign in to your Kinde account and go to **Settings > Git repo**. 2. Select **Connect GitHub** and follow the instructions to connect your GitHub account to Kinde. When you select the repository you just created, Kinde will automatically sync the code for you. ## You're done! Assuming you have an application set up, you can see your custom UI by navigating to your sign in screen. You can now modify the custom UI code to look however you like. ## Next steps - Explore the [Kinde custom UI documentation](/design/customize-with-code/customize-with-css-html/) to learn more about how custom UI works. - Take a look at some other example templates + +# Design - Customize with code - Style with style hooks + +> Comprehensive guide for styling Kinde widgets using style hooks including CSS selectors, theme support, dark mode, and HTML data attributes for custom styling. + +style hooks, CSS styling, data attributes, widget styling, dark mode, theme styles, HTML selectors +design, customize-with-code, styling + +Style hooks are [HTML data attributes](https://developer.mozilla.org/en-US/docs/Learn_web_development/Howto/Solve_HTML_problems/Use_data_attributes) that can be targeted using the [CSS attribute selector](https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors), allowing you to apply styles directly to the Kinde widget in your custom CSS. They give you full control over styling widget components and layouts. Unlike CSS classes, which are used internally, style hooks are dedicated to external (custom) styling. This separation ensures your custom styles remain stable, even if internal styles change. Style hooks are useful when a setting doesn’t exist for a specific style, such as adding a shadow effect to the **Button** component. For example: ```css [data-kinde-button] { box-shadow: 0 1px 3px rgba(12, 12, 12, 0.09); } ``` ## Define style hooks in your CSS Style hooks allow you to apply styles directly in your custom CSS. For example, add a shadow effect to the **Button** component when hovered: ```css [data-kinde-button]:hover { box-shadow: 0 1px 3px rgba(12, 12, 12, 0.09); } ``` ## Available style hooks Nearly all elements in the widget have a style hook applied, allowing you to style it as needed. The best way to see which hooks are available is by using [DevTools](/design/customize-with-code/inspect-design-devtools/). Here’s an example of a form field with its style hooks: ```html
Email
``` And here’s the HTML showing only the style hooks: ```html
``` ## When style hooks aren’t available In rare cases, an element may not have a style hook. This doesn’t mean it can’t be styled—just that a hook isn’t needed. In these cases, it's safe to use an attribute selector or an element (type) selector, but never a class selector, because these attributes and elements are standardized in HTML and won't change. For example, if you wanted to style a specific text input type, like “email”, “url”, “password”, etc, which belongs to the **Control select text** component, you can safely do that by targeting the “type” attribute: ```css [data-kinde-control-select-text][type="email"] { /* Your styles */ } ``` Or if you wanted to target a select list’s `