> For the complete documentation index, see [llms.txt](https://docs.klink.cloud/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.klink.cloud/integrations/single-sign-on-sso.md).

# Single Sign-On (SSO)

Single Sign-On lets your team sign in to klink.cloud with the credentials they already use for work. Instead of a separate klink.cloud password, users authenticate against your company identity provider (IdP) — Okta, Microsoft Entra ID, Google Workspace, Zitadel, or any provider that supports OpenID Connect.

klink.cloud SSO uses **OpenID Connect (OIDC)** with the Authorization Code flow. Any IdP publishing a standard discovery document (`/.well-known/openid-configuration`) will work.

Only workspace members with the **Owner** or **Admin** role can view or change SSO settings.

***

<figure><img src="/files/Jo7KBbzEJGsP7HmRnNVY" alt=""><figcaption></figcaption></figure>

### How it works

1. A user enters their work email at the login page.
2. klink.cloud matches the email domain against your configured connections.
3. On a match, the user is redirected to your identity provider.
4. The user authenticates — including any MFA or conditional access you enforce.
5. Your IdP returns the user to klink.cloud, and they are signed in.

Users never enter a klink.cloud password.

***

### Before you begin

* **Owner** or **Admin** access to your klink.cloud workspace
* Administrator access to your IdP, with permission to create an OIDC application
* Your company email domain, e.g. `acme.com`
* The klink.cloud redirect URI: `https://app.klink.cloud/auth/sso/callback`
* A test user who exists in both your IdP and your klink.cloud workspace

> **Keep a break-glass admin.** Retain at least one administrator who can sign in with email and password, so a misconfiguration or IdP outage cannot lock you out.

***

### Step 1 — Create an OIDC application in your IdP

Create a new application with these settings:

| Setting              | Value                                       |
| -------------------- | ------------------------------------------- |
| Application type     | Web application (confidential client)       |
| Grant type           | Authorization Code                          |
| Sign-in redirect URI | `https://app.klink.cloud/auth/sso/callback` |
| Scopes               | `openid`, `email`, `profile`                |

Then copy three values from your IdP:

* **Discovery URL** — your issuer URL plus `/.well-known/openid-configuration`
* **Client ID**
* **Client secret** — copy it immediately; most providers show it only once

Provider-specific paths are in [Identity provider notes](https://claude.ai/chat/ab1c7e52-ebc4-46fe-9dce-0e76cf71d7cf#identity-provider-notes).

***

### Step 2 — Add the connection in klink.cloud

1. Go to **Settings → SSO**.
2. Click **Add connection**.
3. Fill in the dialog using the reference below.
4. Click **Create connection**.

#### Field reference

<table><thead><tr><th width="211.96875">Field</th><th width="82.0625">Required</th><th>Description</th></tr></thead><tbody><tr><td><strong>Display name</strong></td><td>No</td><td>A label to identify this connection, e.g. <code>Acme Okta</code>. Visible to admins only.</td></tr><tr><td><strong>OIDC discovery URL</strong></td><td>Yes</td><td>Your provider's OpenID configuration URL, e.g. <code>https://acme.okta.com/.well-known/openid-configuration</code>. klink.cloud reads all endpoints from this document, so you don't enter them individually.</td></tr><tr><td><strong>Client ID</strong></td><td>Yes</td><td>The client identifier issued by your IdP.</td></tr><tr><td><strong>Client secret</strong></td><td>Yes</td><td>The client secret issued by your IdP. Stored encrypted and never displayed again after saving.</td></tr><tr><td><strong>Email domain</strong></td><td>No</td><td>The domain used to route logins automatically, e.g. <code>acme.com</code>. Users entering an email on this domain are sent to this connection.</td></tr><tr><td><strong>Scopes</strong></td><td>No</td><td>Defaults to <code>openid email profile</code>, which is correct for most deployments. Change only if your IdP needs extra scopes to release the user's email.</td></tr><tr><td><strong>Enabled</strong></td><td>—</td><td>When on, users can sign in through this connection. On by default.</td></tr><tr><td><strong>Auto-provision users</strong></td><td>—</td><td>When on, a member account is created automatically on a user's first successful SSO login. When off, only pre-invited users can sign in. Off by default.</td></tr></tbody></table>

> **Tip:** Test with **Auto-provision users** off first. Once a pre-invited user can sign in successfully, turn it on if you want hands-off onboarding.

***

### Step 3 — Test

1. Open a private browser window.
2. Go to the klink.cloud login page and enter a test user's work email.
3. Confirm the redirect to your identity provider.
4. Authenticate, and confirm you land back in klink.cloud signed in as the correct user.

Keep your break-glass admin active until this test passes. If it fails, see [Troubleshooting](https://claude.ai/chat/ab1c7e52-ebc4-46fe-9dce-0e76cf71d7cf#troubleshooting).

***

### Step 4 — Roll out

1. Turn on **Auto-provision users** if new staff should be created on first login.
2. Assign the klink.cloud application to the right groups in your IdP.
3. Tell your team to sign in with their work email — no password needed.

***

### Email domain and login routing

The **Email domain** field is what makes SSO automatic. When someone enters an email address at login, klink.cloud matches everything after the `@` against your enabled connections.

* **Domain matches an enabled connection** → the user is redirected to that identity provider.
* **No match** → the user signs in with email and password as normal.

**Multiple domains.** Create one connection per domain. Each can reuse the same discovery URL, client ID, and client secret if they point at the same IdP application.

**Subdomains** are not matched automatically — `mail.acme.com` needs its own connection.

**Guests and contractors** on outside domains are unaffected and continue using email and password.

***

### Provisioning and access

**Auto-provision on.** The first time someone authenticates through the connection, klink.cloud creates a member account from the email and name returned by your IdP. No invite needed. Use this when everyone assigned the app in your IdP should have access.

**Auto-provision off.** Only existing workspace members can sign in. Anyone else authenticates at the IdP but is refused by klink.cloud. Use this when you want to control the member list explicitly.

**Removing access.** Disabling a user in your IdP blocks future sign-ins immediately. It does not delete their klink.cloud member record or their historical data — to fully offboard someone, also remove them under **Settings → Team**.

***

### Managing connections

<table><thead><tr><th width="267.14453125">Action</th><th>Effect</th></tr></thead><tbody><tr><td><strong>Edit</strong></td><td>Changes apply at the next login. Re-enter the client secret if you rotate it in your IdP.</td></tr><tr><td><strong>Disable</strong> (toggle <strong>Enabled</strong> off)</td><td>Logins stop immediately; users on that domain fall back to email and password. Configuration is retained.</td></tr><tr><td><strong>Delete</strong></td><td>Permanently removes the configuration. Member accounts remain, but can no longer sign in via SSO.</td></tr><tr><td><strong>Add another</strong></td><td>Multiple connections can be active at once — useful for multiple domains or migrating between providers.</td></tr></tbody></table>

**Rotating a client secret.** Generate the new secret in your IdP, then edit the connection and paste it in. Do this during a maintenance window — sign-ins between the two steps will fail.

***

### Identity provider notes

#### Okta

**Applications → Create App Integration → OIDC – OpenID Connect → Web Application.** Add the redirect URI, assign groups, then copy the Client ID and secret from the **General** tab.

Discovery URL: `https://<your-org>.okta.com/.well-known/openid-configuration` With a custom authorization server: `https://<your-org>.okta.com/oauth2/<server-id>/.well-known/openid-configuration`

#### Microsoft Entra ID (Azure AD)

**Microsoft Entra ID → App registrations → New registration.** Set the redirect URI type to **Web**. Copy the Application (client) ID and Directory (tenant) ID from **Overview**, then create a secret under **Certificates & secrets** and copy the **Value** immediately. Confirm `openid`, `email`, and `profile` are granted under **API permissions**.

Discovery URL: `https://login.microsoftonline.com/<tenant-id>/v2.0/.well-known/openid-configuration`

> Entra ID client secrets expire on a fixed schedule. Set a reminder before the expiry date — an expired secret breaks SSO for everyone on that domain.

#### Google Workspace

Set the **OAuth consent screen** to **Internal**, then **Credentials → Create Credentials → OAuth client ID → Web application.** Add the redirect URI and copy the Client ID and secret.

Discovery URL: `https://accounts.google.com/.well-known/openid-configuration`

#### Zitadel

1. In the Zitadel Management Console, open an existing **Project** (or create one), then in the **Applications** section click **New**.
2. Give the application a name, e.g. `klink.cloud`.
3. For **Type of application**, choose **Web**.
4. For **Authentication Method**, choose **Code**. This issues a client secret, which klink.cloud requires — do not choose PKCE.
5. Under **Redirect URIs**, enter `https://app.klink.cloud/auth/sso/callback`. Optionally add your login page as the **Post Logout URI**.
6. Review the summary and click **Create**. The **Client ID** and **Client Secret** are shown once — copy them now. You can regenerate the secret later if you lose it.
7. Open the application's **Token Settings** tab and enable **User Info inside ID Token**. Without this, Zitadel may not return the user's email address and login will fail.

Discovery URL: `https://<your-instance>.zitadel.cloud/.well-known/openid-configuration` Self-hosted or with a custom domain: `https://<your-domain>/.well-known/openid-configuration`

You can also find this under **URLs** in the console's left sidebar, listed as the Discovery Endpoint.

> If your Zitadel project requires authorization on authentication, make sure your users are granted access to the project — otherwise they will authenticate successfully but be rejected before returning to klink.cloud.

#### Other OIDC providers

You need a discovery URL, a client ID, and a client secret for a confidential web client using the Authorization Code grant, with the klink.cloud redirect URI registered. Everything else is read from the discovery document. To check your discovery URL, open it in a browser — you should see JSON containing `issuer`, `authorization_endpoint`, `token_endpoint`, and `jwks_uri`.

***

### Signing in with SSO (for end users)

1. Go to the klink.cloud login page.
2. Enter your work email address.
3. You'll be redirected to your company sign-in page.
4. Sign in as you would for any other company application, completing MFA if prompted.
5. You'll be returned to klink.cloud, signed in.

If you're asked for a klink.cloud password, your email domain may not be configured for SSO — contact your workspace administrator.

***

### Security notes

* **Client secrets are encrypted at rest** and never shown again after saving. If you lose one, generate a new secret in your IdP and update the connection.
* **MFA is enforced by your IdP**, not by klink.cloud. Configure it in your provider's policies.
* **Email is the identity key.** klink.cloud matches users on the email address returned by your IdP. If a user's email changes in your directory, update it in klink.cloud too, or they'll be treated as a new user.
* **Signing out of your IdP** does not automatically end an active klink.cloud session.
* **Restrict who can manage SSO.** Only Owners and Admins can view or edit connections. Review these role assignments periodically.

***

### Troubleshooting

| Symptom                                                        | Likely cause                                                | Fix                                                                                                                                        |
| -------------------------------------------------------------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| `redirect_uri_mismatch` at the IdP                             | The redirect URI doesn't exactly match                      | Re-enter `https://app.klink.cloud/auth/sso/callback` in your IdP. Check for a trailing slash, `http` vs `https`, or a typo in the host.    |
| User is asked for a password instead of being redirected       | Domain not configured, or connection disabled               | Confirm **Email domain** matches the user's domain exactly and **Enabled** is on.                                                          |
| "Unable to load provider configuration" when saving            | Discovery URL unreachable or invalid                        | Open the URL in a browser. It must return a valid OpenID configuration document and be publicly reachable — internal-only URLs won't work. |
| `invalid_client`                                               | Wrong client ID, or an incorrect or expired secret          | Re-copy both values. If the secret was rotated or expired, generate a new one and update the connection.                                   |
| Authentication succeeds but klink.cloud says no account exists | **Auto-provision users** is off and the user wasn't invited | Invite the user under **Settings → Team**, or turn on **Auto-provision users**.                                                            |
| Login loops back to the sign-in page                           | The IdP isn't returning an email claim                      | Confirm the `email` scope is requested and that your IdP releases the email claim. Some providers require this in claims mapping.          |
| SSO suddenly stopped working for everyone                      | Expired client secret                                       | Check the secret's expiry in your IdP, generate a new one, and update the connection.                                                      |

Still stuck? Contact support with the connection's display name, the exact error text, and the approximate time of the failed attempt.
