> ## Documentation Index
> Fetch the complete documentation index at: https://developers.firmly.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Generic OIDC

> Configure any OpenID Connect–compliant Identity Provider in firmly Connect.

<Info>
  **Generic OIDC works with any OpenID Connect 1.0–compliant Identity Provider** — Okta, Microsoft Entra ID, Google, Auth0, Keycloak, JumpCloud, OneLogin, and others. This guide covers what you fill in on the firmly Connect side. For provider-specific application setup steps (creating the OIDC application, granting scopes, mapping claims), refer to your IdP's own integration documentation.
</Info>

## Prerequisites

Before you start, make sure you have:

* **At least one verified domain** in firmly Connect — see [Verify a Domain](/firmly-connect/sso/domain-verification).
* **An OIDC application registered in your IdP** that issues an ID token containing the user's email. You will need its **Client ID**, **Client Secret**, and **Issuer URL**.
* **Permission to configure the redirect (callback) URI** on your IdP application. firmly will give you the exact URL to register.

## Get the firmly Callback URL

When you open the OIDC configuration form in firmly Connect, the page displays a read-only **Callback URL** with a copy button. This URL is the OAuth2 / OIDC redirect URI that your IdP will send the user back to after authentication.

You must register this exact URL as a permitted redirect URI in your IdP's OIDC application before the integration will work.

<Note>
  The Callback URL is **deployment-specific** — copy it directly from the firmly Connect Dashboard rather than guessing or hand-typing it. A single character mismatch will cause your IdP to reject the redirect with a `redirect_uri` error.
</Note>

<img src="https://mintcdn.com/firmly/0BX4LLOqckfwDI3q/images/firmly-connect/sso/oidc-callback-url.png?fit=max&auto=format&n=0BX4LLOqckfwDI3q&q=85&s=43eb70075f0bb1f75efd25f7d05f9620" alt="Callback URL panel with copy button" width="1380" height="232" data-path="images/firmly-connect/sso/oidc-callback-url.png" />

## Add an OIDC Identity Provider

<Steps>
  <Step title="Open Settings → Single Sign-On">
    Navigate to the **Single Sign-On** page in your firmly Connect Dashboard settings.
  </Step>

  <Step title="Click Add Identity Provider">
    The IdP picker dialog opens with all available protocols.
  </Step>

  <Step title="Select OpenID Connect">
    Click the **OpenID Connect** tile to open the configuration form.
  </Step>

  <Step title="Fill in the form fields">
    See the [Field reference](#field-reference) below for every field.
  </Step>

  <Step title="Click Save">
    The IdP is created in **disabled** state. You can now test it, bind it to verified domains, and enable it.
  </Step>
</Steps>

<img src="https://mintcdn.com/firmly/0BX4LLOqckfwDI3q/images/firmly-connect/sso/oidc-picker.png?fit=max&auto=format&n=0BX4LLOqckfwDI3q&q=85&s=e05a1ae33906ace07b44df921405e35c" alt="IdP picker with OpenID Connect tile" width="708" height="444" data-path="images/firmly-connect/sso/oidc-picker.png" />

## Field reference

| Field             | Required | What to enter                                                                                                                                                                                                                                    |
| ----------------- | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Issuer URL**    |    Yes   | The OIDC issuer URL of your IdP — must use `https://` (for example, `https://accounts.google.com`). The form accepts either the bare issuer URL or the full `…/.well-known/openid-configuration` discovery URL; firmly canonicalizes it on save. |
| **Client ID**     |    Yes   | The Client ID for the OIDC application you registered in your IdP.                                                                                                                                                                               |
| **Client Secret** |    Yes   | The Client Secret for that application. Stored encrypted; the field is masked with a show / hide toggle.                                                                                                                                         |
| **Email Claim**   |    No    | The JWT claim name that contains the user's email address. Leave empty to use the standard `email` claim — change only if your IdP exposes the email under a non-standard claim name.                                                            |

<img src="https://mintcdn.com/firmly/0BX4LLOqckfwDI3q/images/firmly-connect/sso/oidc-fields.png?fit=max&auto=format&n=0BX4LLOqckfwDI3q&q=85&s=40b73b9e01b4873ffd4d524ec47f41c3" alt="OpenID Fields" width="1384" height="693" data-path="images/firmly-connect/sso/oidc-fields.png" />

<Note>
  firmly automatically requests the `openid profile email` scopes when initiating the OIDC flow — you do not configure scopes on the form. Make sure your IdP application allows these scopes.
</Note>

## Bind the IdP to verified domains

The IdP configuration form includes an **Authorized Domains** section listing every domain you have verified. Each verified domain appears as a toggle.

* Turn on the toggle for each domain you want this IdP to handle.
* A single IdP can be bound to multiple domains.
* A single domain can be bound to multiple IdPs (users will be presented with a choice at sign-in).
* **At least one domain must be bound** before the IdP can be enabled.

Unverified domains do not appear in this list. To bind a new domain to this IdP, [verify the domain](/firmly-connect/sso/domain-verification) first — it will then show up here automatically.

## Enable the IdP

The **Enabled** toggle at the top of the form becomes available once:

* All required fields are filled and pass validation, **and**
* At least one verified domain is bound under **Authorized Domains**.

Toggle **Enabled** on to make the IdP usable for sign-in. A disabled IdP keeps all its configuration but cannot complete authentication for any user.

## Test the connection

The **Test Connection** button appears on the IdP form in **edit** mode (after the initial save), provided there are no unsaved changes and all required fields are filled.

Clicking **Test Connection** performs a real OIDC round trip against your IdP:

1. firmly redirects you to your IdP's authorization endpoint.
2. You authenticate with a real account at your IdP.
3. Your IdP redirects back to firmly with an authorization code.
4. firmly exchanges the code for an ID token, validates the signature against your IdP's JWKS, and extracts the configured claims.

On success, the form displays the extracted claims (email, name, sub). On failure, it displays a formatted error explaining where the round trip broke down (for example, `invalid_client`, `redirect_uri_mismatch`, signature verification failure, missing email claim).

<Warning>
  Always run **Test Connection** successfully *before* enabling the IdP for a domain that you plan to enforce SSO on. A misconfigured IdP combined with enforcement will lock users out of the dashboard until the configuration is fixed.
</Warning>

<img src="https://mintcdn.com/firmly/0BX4LLOqckfwDI3q/images/firmly-connect/sso/oidc-test-connection.png?fit=max&auto=format&n=0BX4LLOqckfwDI3q&q=85&s=0a174cd86339366d028f877673225f64" alt="Test Connection button and success result" width="1380" height="373" data-path="images/firmly-connect/sso/oidc-test-connection.png" />

## Rotate the Client Secret

If you rotate the Client Secret in your IdP (or it leaks and you need to invalidate it):

1. Generate a new Client Secret in your IdP application.
2. Open the IdP configuration in firmly Connect, paste the new value into **Client Secret**, and click **Save**.
3. Run **Test Connection** to confirm the new secret works.

There is no separate "rotate" workflow — updating the field and saving is the rotation.

## Disable or delete the IdP

* **Disable** — turn the **Enabled** toggle off on the form. The configuration is preserved, the IdP is removed from sign-in, and any domain enforcement that depended solely on this IdP becomes unavailable.
* **Delete** — from the IdP row's actions menu on the SSO page, choose **Delete**. This is a hard delete, recorded in the audit log, and will unbind the IdP from any domains that referenced it.

## Troubleshooting

<Tabs>
  <Tab title="Invalid issuer">
    The discovery document at `<issuer-url>/.well-known/openid-configuration` must be reachable from firmly, and its `issuer` field must match the configured **Issuer URL** exactly (per OIDC §4.3). If you used a discovery URL in the form, firmly stores the bare issuer URL after canonicalization — reopen the form to see the stored value.
  </Tab>

  <Tab title="Email claim missing">
    Your IdP's ID token doesn't contain a usable email value. Confirm the OIDC application has the `email` scope granted, that the user has an email attribute populated in the IdP, and (if the IdP uses a non-standard claim name) set the **Email Claim** field to the actual claim name.
  </Tab>

  <Tab title="Redirect URI mismatch">
    Your IdP rejects the redirect with `redirect_uri_mismatch` (or similar). Copy the **Callback URL** from the firmly Connect form *verbatim* and paste it into your IdP application's list of allowed redirect URIs. Trailing slashes, scheme (`http` vs `https`), and host casing all matter.
  </Tab>

  <Tab title="Test Connection fails after a saved change">
    The **Test Connection** button is hidden while there are unsaved changes on the form. Save first, then click **Test Connection**.
  </Tab>
</Tabs>

## Next steps

<CardGroup cols={2}>
  <Card title="Verify a Domain" icon="at" href="/firmly-connect/sso/domain-verification">
    Add and verify the domains you want this IdP to handle, and enable enforcement when you're ready.
  </Card>

  <Card title="SSO Overview" icon="shield-check" href="/firmly-connect/sso/overview">
    Recap the full setup flow and per-domain enforcement model.
  </Card>
</CardGroup>
