DocsOpen Moon AI
Browse the docs

Single sign-on (OpenID Connect)

What Moon AI expects from your OpenID Connect provider, how a sign-in works, which claims are read, and the routes that read or save the configuration.

On this page

Single sign-on for a managed organization uses OpenID Connect: your members sign in to Moon AI with your organization’s credentials (Microsoft Entra ID, Google Workspace, Okta, Keycloak…). Setting it up from the admin console is covered in Single sign-on.

What your provider must offerLink to the What your provider must offer section

ItemExpected
DiscoveryA /.well-known/openid-configuration document under the issuer, over HTTPS, whose issuer is the issuer itself. Its authorization, token and key URLs use HTTPS.
FlowAuthorization code with PKCE (S256).
ApplicationA client ID and, usually, a client secret. Without a secret, no client authentication is sent.
Redirect URLhttps://chat.realmoon.ai/api/v1/orgs/sso/callback
Token endpoint authenticationclient_secret_basic if the provider advertises it (or advertises nothing), otherwise client_secret_post.
ID token signatureRS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384 or ES512, with a published RSA or EC key. none and HMAC algorithms (HS…) are refused.
Requested scopesopenid email profile by default; openid is always added.

How a sign-in worksLink to the How a sign-in works section

  1. The member chooses “Continue with my organization’s SSO” and enters their address, or opens the organization’s sign-in link: https://chat.realmoon.ai/auth?org_sso=<org_id>.
  2. Moon AI redirects to your provider with a single-use state and nonce, valid for 10 minutes and bound to the browser, plus the PKCE challenge. The address entered is passed as login_hint.
  3. Your provider sends the member back to the redirect URL. Moon AI exchanges the code, then checks the ID token: signature, iss, aud, azp (when aud has several values), exp and iat (60 seconds of tolerance), sub and nonce.
  4. Moon AI reads the address from the chosen claim (email by default) and requires email_verified to be true, unless the “Trust email addresses from this provider” option is on. For a Microsoft Entra ID issuer specific to your tenant (https://login.microsoftonline.com/<tenant id>/v2.0), an address without email_verified is accepted.
  5. The account is opened or created according to the organization’s rules, then the Moon AI account’s two-factor authentication is requested if it is turned on.

An address read from a claim other than email only counts as verified with the “Trust email addresses from this provider” option.

Who sign-in can let inLink to the Who sign-in can let in section

  • Without a verified domain: active or suspended members of the organization (a suspended member stays suspended) and people invited as members.
  • With a verified domain, or an issuer served on your domain: any address in that domain; the account is created if it does not exist. On a workspace paid by card, or with no free seat, the person is signed in without being added to the organization.
  • Never the account of the organization’s owner, nor that of a platform administrator.
  • Never an address from a domain verified by another organization, or from a public email provider.

When sign-in is mandatory, the organization’s owner and admins keep their other ways to sign in, so they do not lose access if the provider goes down. When it becomes mandatory, the sessions of every account in the verified domains are closed, except the owner’s.

Claims readLink to the Claims read section

SettingDefaultPurpose
claim_emailemailThe member’s address.
claim_namenameThe display name; otherwise given_name and family_name, then the start of the address.
claim_groupsnoneThe member’s groups at the provider: a string or a list (up to 500).
group_map{}Provider groups to organization groups.

group_map maps the name or ID of a provider group to one or more organization groups: up to 200 entries, 50 groups per entry. The target groups are static groups, neither synced from the directory nor granting the admin role. At each sign-in, with claim_groups set, the member joins the groups mapped from their provider groups and leaves the ones single sign-on had given them; groups added by hand are never removed.

JSON
{
  "Enseignants-Lycee": ["<id of the Enseignants group>"],
  "Eleves-Seconde": ["<id of the Secondes group>", "<id of the Élèves group>"]
}

Read the configuration through the APILink to the Read the configuration through the API section

GET /api/v1/orgs/{org_id}/sso · security:read

cURL
curl https://chat.realmoon.ai/api/v1/orgs/$ORG_ID/sso \
  -H "Authorization: Bearer $MOONAI_ADMIN_KEY"
Python
import os
import requests

r = requests.get(
    f"https://chat.realmoon.ai/api/v1/orgs/{os.environ['ORG_ID']}/sso",
    headers={"Authorization": f"Bearer {os.environ['MOONAI_ADMIN_KEY']}"},
    timeout=30,
)
r.raise_for_status()
sso = r.json()
print(sso["sso"]["status"] if sso["sso"] else "not configured", sso["sign_in_url"])
JavaScript
const r = await fetch(`https://chat.realmoon.ai/api/v1/orgs/${process.env.ORG_ID}/sso`, {
  headers: { Authorization: `Bearer ${process.env.MOONAI_ADMIN_KEY}` },
});
if (!r.ok) throw new Error(await r.text());
const { sso, sign_in_url } = await r.json();
console.log(sso ? sso.status : 'not configured', sign_in_url);
JSON
{
  "sso": {
    "id": "8b0e2c4a-6d8f-4a1b-9c3e-5f7a9b1d3e5f",
    "org_id": "8c1f2a4e-5b6d-4e7f-9a0b-1c2d3e4f5a6b",
    "issuer": "https://login.microsoftonline.com/<tenant id>/v2.0",
    "client_id": "<client id>",
    "has_secret": true,
    "scopes": "openid email profile",
    "claim_email": "email",
    "claim_name": "name",
    "claim_groups": "groups",
    "group_map": { "Enseignants": ["<group id>"] },
    "enforced": false,
    "trust_email": false,
    "status": "active",
    "provider_metadata": { "issuer": "https://login.microsoftonline.com/<tenant id>/v2.0", "key_count": 3 },
    "tested_at": 1762339200,
    "last_error": null,
    "created_at": 1762000000,
    "updated_at": 1762339200
  },
  "redirect_uri": "https://chat.realmoon.ai/api/v1/orgs/sso/callback",
  "verified_domains": ["ecole.fr"],
  "sign_in_url": "https://chat.realmoon.ai/auth?org_sso=8c1f2a4e-5b6d-4e7f-9a0b-1c2d3e4f5a6b",
  "can_configure": false
}

sso is null when nothing is configured; status is draft, active or disabled. The secret is never returned (has_secret).

Save the configurationLink to the Save the configuration section

Configuring, testing and removing single sign-on gives access to members’ accounts: only the organization’s owner and admins can do it, from the admin console › “Sign-in” or with their own session. An admin key gets 403 owner_only on these routes (can_configure: false).

Method and pathPurpose
PUT /api/v1/orgs/{org_id}/ssoSave the whole configuration.
POST /api/v1/orgs/{org_id}/sso/testTest an issuer, without turning anything on.
DELETE /api/v1/orgs/{org_id}/ssoRemove the sign-in and its secret.

Body of PUT /sso: it replaces the whole configuration; a missing field goes back to its default value.

FieldTypeRequiredDescription
issuerstringyesThe issuer, starting with https://, without parameters (8 to 512 characters).
client_idstringyesThe client ID, without spaces.
client_secretstringnoThe secret; missing or empty, the saved secret is kept.
scopesstringnoSpace-separated scopes, up to 20.
claim_email, claim_name, claim_groupsstringnoThe claims read.
group_mapobjectnoMissing: the mapping is cleared.
enabledbooleannofalse by default: a PUT without enabled turns sign-in off. With true, the provider is tested before it is turned on.
enforcedbooleannoMandatory sign-in for accounts in the verified domains. Requires enabled and at least one verified domain.
trust_emailbooleannoTrust the provider’s addresses; missing, the saved choice is kept.

Changing issuer or client_id puts the configuration back in draft, clears the secret (unless it is sent in the same request) and the members’ links with the old provider: a second PUT with enabled: true turns it on. Each change is reported to the organization’s owner.

StatuscodeCause
400invalid_requestInvalid field (fields), enforced without enabled.
400sso_test_failedWith enabled: true, the provider does not respond as expected; reason gives the cause.
403owner_onlyNeither the organization’s owner nor one of its admins, or an admin key.
409sso_enforce_needs_domainMandatory sign-in without a verified domain.
409directory_group_admingroup_map targets a group that grants the admin role.

POST /sso/test takes {"issuer": "…"} (optional: otherwise the saved issuer) and returns 200 with {"ok": true, "issuer", "authorization_endpoint", "token_endpoint", "jwks_uri", "key_count"}, or {"ok": false, "reason"}. It is limited to 20 attempts per organization in 10 minutes.

reasonCause
issuer_invalidURL that does not start with https://, or that contains credentials or parameters.
provider_unreachableNo response within 8 seconds, response too large or unreadable, URL refused.
provider_http_errorThe discovery document or the keys do not return 200.
discovery_invalidIncomplete document, or URLs that do not use HTTPS.
issuer_mismatchThe document’s issuer differs from the URL tested.
jwks_invalidNo usable RSA or EC signing key.

Errors members seeLink to the Errors members see section

The member sees a plain-language message; the most common ones and their causes are listed in Single sign-on. Starting a sign-in is limited to 30 attempts per IP address in 10 minutes.

See alsoLink to the See also section

Moon AI

Moon AI in action

0:00

Explore

Screenshots of chat.realmoon.ai taken on October 29, 2026, with fictional data.

Moon AI

Your preferences

Visits counted without cookies.

Our server counts visits without cookies or trackers. Your theme and your answer about ad measurement are remembered on this device.

Ad measurement

With your consent, our ad networks’ trackers (Google) measure our ads, from the visit to the sign-up and then to the first subscription and its amount, and may show you our ads. Your answer is valid for 13 months; you can change it here at any time.

No answer saved on this device.

After you decline, no tag is loaded anymore and the site deletes the cookies they had set on realmoon.ai. Those on the ad networks’ own domains are managed with them or in your browser.

The Moon AI app has its own privacy settings.