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

# Single sign-on with Feishu/Lark, DingTalk and OIDC

> Let your people sign in to Alforse with Feishu or Lark, DingTalk, or any OpenID Connect identity provider such as Okta, Entra ID, Auth0 or Keycloak.

Besides [SAML 2.0](https://docs.alforse.com/docs/reference/single-sign-on.md), Alforse can hand sign-in over to your company's Feishu / Lark or DingTalk organization, or to any OpenID Connect (OIDC) identity provider. A company administrator sets this up once on the **Single Sign-On** page; from then on, people who enter a work email on a verified domain are sent to that provider to sign in.

## Concepts

* **One connection per company.** Your company has one single sign-on connection, with one protocol: **OpenID Connect**, **Feishu / Lark**, **DingTalk**, or SAML. Saving one of the first three on this page replaces a SAML connection (see [Switching from SAML](#switching-from-saml)).
* **Verified domains route sign-ins.** Only email domains you have proven with a DNS record send people to the provider.
* **Invite-first.** Single sign-on never creates accounts on its own. A person gets in only as an existing member, or by accepting a pending invitation from your company.
* **Linked accounts.** The first successful sign-in links the provider account to the Alforse person. Later sign-ins use that link directly.

## Before you start

* **Permission.** You need permission to change company settings (`settings` update). Without it the page shows **"Administrators only"**.
* **Availability.** If single sign-on isn't part of your subscription, the page shows **"Single sign-on isn't in your plan"**.
* **Provider access.** You need rights to create an application in your identity provider: a custom app in the Feishu / Lark open platform, an internal app in the DingTalk developer console, or an OIDC web application in your IdP.
* **DNS access.** You will publish a TXT record for each email domain.

## Open the Single Sign-On page

1. Sign in to the ERP at [https://app.alforse.com](https://app.alforse.com).
2. In the same browser, open **[https://api.alforse.com/identity](https://api.alforse.com/identity)**.

If the page shows **"Sign in to continue"**, select **Sign in**, sign in to the ERP, and open the address again. The **EN** / **中文** buttons at the top switch the page between English and Simplified Chinese. The status next to the title reads **Active** once a connection exists, otherwise **Not configured**.

The page has five cards: **Identity Provider**, **Require single sign-on**, **Email Domains**, **Sign-in Links** and **Linked Accounts**. Only **Identity Provider** shows until you have saved a connection.

Alforse screenshot**Single Sign-On page at api.alforse.com/identity: Identity Provider card with Provider select, Redirect URI copy field and Connect button**

Every provider is set up from the Identity Provider card.

## The Identity Provider card

| Field | Shown for | What to enter |
| - | - | - |
| **Provider** | All | **OpenID Connect (Okta, Entra ID, Auth0, Keycloak…)**, **Feishu / Lark** or **DingTalk**. |
| **Redirect URI** | All | Read-only, with a copy button. Register this exact value with your provider. |
| **View setup guide** | All | Opens the provider-specific steps in a side panel. |
| **Issuer URL** | OpenID Connect | Your IdP's issuer, starting with `https://`. |
| **Region** | Feishu / Lark | **Feishu (feishu.cn)** or **Lark (larksuite.com)**. |
| **Client ID** / **App ID** / **Client ID (AppKey)** | All | The application's ID from the provider. |
| **Client secret** / **App Secret** / **Client Secret (AppSecret)** | All | The application's secret. Once saved it is never shown again; the field then says "Saved. Leave empty to keep it." |
| **Tenant key** (optional) | Feishu / Lark | Your Feishu tenant key. Leave it empty and Alforse reads it from Feishu with the App Secret. |
| **CorpId** | DingTalk | Your DingTalk organization's CorpId. Required. |

Select **Connect** (or **Save changes** for an existing connection). Alforse checks the settings with the provider before saving and confirms with "Single sign-on saved".

### The Redirect URI

Every provider application must use this one redirect (callback) URI:

```text theme={null}
https://api.alforse.com/api/web/auth/v1/sso/oauth/callback
```

It is the same for every company and every provider. Copy it from the page rather than typing it.

## Set up your provider

**Feishu / Lark**

**In the Feishu Open Platform** ([https://open.feishu.cn](https://open.feishu.cn), or [https://open.larksuite.com](https://open.larksuite.com) for Lark):

1. Create a **custom app** (企业自建应用).
2. Under **Credentials & Basic Info**, copy the **App ID** and **App Secret**.
3. Under **Security Settings → Redirect URLs**, add the Redirect URI shown above.
4. Under **Permissions**, allow:
   * reading the user's basic info (required);
   * reading the user's enterprise email, so people can be matched by email;
   * reading tenant info, if you will leave **Tenant key** empty in Alforse.
5. Create a version and publish the app to the people who should sign in.

**In Alforse:** choose **Feishu / Lark**, pick the **Region** that matches the platform you used, paste **App ID** and **App Secret**, optionally paste the **Tenant key**, and select **Connect**.

* Only the **enterprise email** your Feishu tenant issued counts as verified. An address a user typed into their own profile is never used for matching.
* People without an enterprise email are connected once with a [sign-in link](#sign-in-links).

**DingTalk**

**In the DingTalk developer console** ([https://open-dev.dingtalk.com](https://open-dev.dingtalk.com)):

1. Under **App Development**, create an **internal app** (企业内部应用).
2. Under **Credentials & Basic Info**, copy the **Client ID (AppKey)** and **Client Secret (AppSecret)**.
3. Under **Security Settings → Redirect URL**, add the Redirect URI shown above.
4. Under **Permissions**, allow reading the user's personal information (`Contact.User.Read`).
5. Copy your organization's **CorpId** from the developer console home page.

**In Alforse:** choose **DingTalk**, paste **Client ID (AppKey)**, **Client Secret (AppSecret)** and **CorpId**, and select **Connect**.

> [!NOTE]
>
> DingTalk emails are maintained by the users themselves, so Alforse never uses them for matching. Connect each person once with a [sign-in link](#sign-in-links); after that they sign in with DingTalk directly.

**OpenID Connect**

**In your identity provider** (Okta, Entra ID, Auth0, Keycloak, or any OIDC provider):

1. Create an OpenID Connect **web application**. In Okta: **Applications → Create App Integration → OIDC – Web Application**.
2. Set the grant type to **Authorization Code** and the sign-in redirect URI to the Redirect URI shown above.
3. Assign the people or groups who may sign in.
4. Copy the **Client ID** and **Client secret**.
5. Find the **Issuer URL**. In Okta: **Security → API → Authorization Servers → Issuer URI**, for example `https://your-org.okta.com/oauth2/default`.

**In Alforse:** choose **OpenID Connect**, enter the **Issuer URL**, **Client ID** and **Client secret**, and select **Connect**.

Requirements on the provider side:

* The issuer must be an `https://` URL without credentials, query or fragment, and must match the `issuer` in its discovery document exactly.
* Every endpoint in the discovery document must be `https://` on the issuer's own host.
* ID tokens must be signed with **RS256**.
* Alforse requests the scopes `openid email profile` and uses PKCE. The ID token must carry `email` and `email_verified: true` for people to be matched by email.

## Verify your email domains

Once the connection is saved, add each domain your people sign in with in the **Email Domains** card: type it under **Add a domain** (for example `example.com`) and select **Add**. A new domain is **Pending** and shows the TXT record to publish:

| Field | Value |
| - | - |
| **Host** | `_alforse-challenge.example.com` |
| **Value** | `alforse-domain-verification=<your unique token>` |

Publish the record with your DNS provider, then select **Verify**. On success the domain shows **Verified** and the page says "Domain verified". The rules are the same as for SAML: see [Verifying a domain](https://docs.alforse.com/docs/reference/single-sign-on.md#verifying-a-domain).

## How a sign-in is matched to a person

People sign in from the ERP login page by entering their work email and selecting **Continue**. An email on a verified domain sends them to your provider. When they come back, Alforse looks only inside your company, in this order:

1. **Linked account.** The provider account is already linked to a person: that person is signed in.
2. **Verified email.** The provider reports a verified email on one of your verified domains. A matching active member is signed in; a matching pending invitation is accepted and its role applied. The account is then linked.
3. **Sign-in link.** The person opened a one-time sign-in link you issued. The account is linked to the member or invitation the link was made for.

Anyone else is refused, and no account is created. For Feishu / Lark and DingTalk, Alforse also checks that the provider account belongs to the tenant key or CorpId saved on your connection.

NOTE

**One provider account per person**

Each person can have one linked account per provider. To link a different account, revoke the existing one under **Linked Accounts** first.

## Sign-in links

Use the **Sign-in Links** card to connect a person whose provider can't prove their email: everyone on DingTalk, and Feishu users without an enterprise email.

1. Choose a **Pending invitation**, or type **Or an existing member's email**.
2. Select **Create link**.
3. Copy the link from the **Sign-in link created** dialog and send it to the person yourself.

The link looks like `https://api.alforse.com/api/web/auth/v1/sso/oauth/invite?token=…`. The person opens it, signs in with the provider, and their account is linked; from then on they sign in normally.

* **Shown once.** The link is displayed only in that dialog. If it is lost, revoke it and create a new one.
* **Works once, for 7 days.** The table shows each link's **For**, **Status** (**Open**, **Used**, **Revoked** or **Expired**) and **Expires**. Select **Revoke** to cancel an open link.
* **Verified domain required.** The email of the invitation or member must be on a verified domain of the connection.
* Sign-in links are available for OpenID Connect, Feishu / Lark and DingTalk connections, not for SAML.

## Linked accounts

The **Linked Accounts** card lists every link with **Person**, **Provider account**, **Linked by** (**Verified email** or **Sign-in link**) and **Linked**. Select **Revoke** to remove a link. The person's Alforse account stays; on their next sign-in they are matched again by verified email, or need a new sign-in link.

## Requiring single sign-on

Turn on **Require single sign-on** to make your provider the only way in for people on verified domains. Other sign-in methods, such as magic links, are then refused for them. The switch takes effect once at least one domain is verified, so you can test sign-in before you enforce it.

## Switching from SAML

If your company already uses [SAML](https://docs.alforse.com/docs/reference/single-sign-on.md), the card says "Your company currently signs in with SAML. Saving another provider here replaces it."

* Saving an OpenID Connect, Feishu / Lark or DingTalk connection removes the SAML settings (the IdP metadata) from your connection. SAML sign-in stops at that moment.
* Your email domains and their verification stay, and so does **Require single sign-on**.
* While a non-SAML connection is active, the SAML card on **Settings → Security** can't be saved. Deactivate the connection on this page first.

## Deactivating

Select **Deactivate** in the **Identity Provider** card and confirm in **Deactivate single sign-on**. People on your domains no longer sign in through your provider. Domain verifications are removed; linked accounts are kept, so if you reconnect the same provider later, only the domains need verifying again.

## Troubleshooting

| Symptom or message | Cause | Fix |
| - | - | - |
| "Administrators only" | You lack permission to change company settings. | Ask an administrator for `settings` update. |
| "Single sign-on isn't in your plan" | Your subscription does not include single sign-on. | Upgrade your plan. |
| "The issuer URL must start with https\://." | The issuer is not an https URL, has a query or fragment, or differs from the `issuer` in the discovery document. | Enter the issuer exactly as the discovery document names it. |
| "The identity provider couldn't be reached. Check the issuer URL." | The discovery document could not be fetched, or its endpoints are not https on the issuer's host, or the IdP doesn't sign ID tokens with RS256. | Check the issuer URL and the IdP's signing algorithm. |
| "Enter a valid client secret." | The secret is missing, or Feishu refused the App ID / App Secret. | Re-copy the ID and secret and check the **Region**. |
| "Enter the CorpId." | DingTalk without a CorpId, or Feishu with neither a tenant key nor a readable tenant. | Enter the CorpId, or paste the Feishu tenant key, or grant the tenant-info permission. |
| "Verify this email's domain first." | You created a sign-in link for an email whose domain isn't verified. | Verify the domain, then create the link. |
| "No invitation or member uses this email." | The email matches no single active member. | Invite the person, then pick the invitation. |
| "The TXT record wasn't found yet. Try again in a few minutes." | DNS hasn't propagated, or the record is at the wrong host. | Check the host name and retry. |
| "The configuration changed in the meantime. It has been reloaded — check and try again." | Another administrator saved a change. | Review the reloaded page and repeat your change. |
| At sign-in: "Single sign-on succeeded, but this account is not yet linked to your company. Ask your administrator for a sign-in link." | The provider gave no verified email (always the case for DingTalk). | Create a sign-in link for the person. |
| At sign-in: "Single sign-on succeeded but no invite exists for `jane@example.com`. Contact your administrator." | Verified email, but the person is neither a member nor invited. | Invite them, then ask them to sign in again. |
| At sign-in: "Single sign-on rejected: this email domain is not registered for your company's single sign-on connection." | The provider's email is on a domain you haven't verified. | Verify that domain. |
| At sign-in: "This account belongs to another organization than your company's single sign-on connection." | The Feishu tenant, DingTalk CorpId or OIDC issuer doesn't match the connection. | The person must use an account in your organization; check the saved tenant key or CorpId. |
| At sign-in: "This sign-in link is unknown, already used, revoked or expired. Ask your administrator for a new one." | The link was used, revoked or is older than 7 days. | Create a new link. |
| At sign-in: "Another account of this identity provider is already linked to this user. Contact your administrator." | The person already has a different linked provider account. | Revoke the old link under **Linked Accounts**. |

## Related

**Single sign-on with SAML**

Connect a SAML 2.0 identity provider from Settings → Security.

[Open](https://docs.alforse.com/docs/reference/single-sign-on.md)

**People**

Invite the people who will sign in.

[Open](https://docs.alforse.com/docs/reference/people.md)

**Two-factor authentication**

Alforse's own second factor for other sign-in methods.

[Open](https://docs.alforse.com/docs/reference/two-factor.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.