External Login Providers
Chatto can consume external OAuth and OIDC providers for sign-in. Providers are configured in chatto.toml as repeated [[auth.providers]] tables, and the login page renders one button per configured provider.
Supported providers
Section titled “Supported providers”| Type | Use for |
|---|---|
oidc | Any standards-compatible OIDC provider |
github | GitHub OAuth apps |
gitlab | GitLab OAuth applications |
google | Google OAuth clients |
discord | Discord OAuth2 applications |
Other provider types are not exposed as curated providers yet. Use oidc for standards-compatible OIDC providers.
Provider IDs
Section titled “Provider IDs”Every provider needs a stable id. The ID appears in login URLs and is stored in external identity links, so changing it after users link accounts will strand those links.
Use short, URL-safe IDs that describe the local provider slot:
id = "chatto-hub"id = "github-main"id = "staff-google"Provider IDs must not contain spaces, /, ?, or #.
Callback URLs
Section titled “Callback URLs”Register this callback URL with each external provider:
https://chat.example.com/auth/providers/{providerID}/callbackFor example, a provider with id = "github-main" on https://chat.example.com uses:
https://chat.example.com/auth/providers/github-main/callbackChatto derives the callback from webserver.url, so set that value to the public HTTPS origin of your server.
For older OIDC client registrations, Chatto also serves /auth/oidc and /auth/oidc/callback as compatibility aliases for the configured OIDC provider. New registrations should use the provider-specific callback URL.
Configuration
Section titled “Configuration”[webserver]url = "https://chat.example.com"
[[auth.providers]]id = "chatto-hub"type = "oidc"label = "Chatto Hub"issuer_url = "https://hub.chatto.dev"client_id = "..."client_secret = "..."# Keep false for invite-only/account-linking deployments.auto_provision = falseissuer_url must be an absolute http or https URL. Chatto uses OIDC discovery from that issuer and verifies the ID token before matching the external identity.
By default, Chatto does not request email claims from OIDC providers:
[[auth.providers]]id = "idp-main"type = "oidc"label = "Company SSO"issuer_url = "https://idp.example.com"client_id = "..."client_secret = "..."auto_provision = trueEmail-less accounts can sign in, link identities, and count toward limits.max_users through the linked OIDC subject. They do not receive a Chatto verified email unless the provider later returns an explicitly verified email claim.
For container platforms, configure providers with counted environment variables. Each provider uses CHATTO_AUTH_PROVIDERS_<index>_<field>, with indexes starting at 0 and no gaps:
CHATTO_AUTH_PROVIDERS_0_ID=chatto-hubCHATTO_AUTH_PROVIDERS_0_TYPE=oidcCHATTO_AUTH_PROVIDERS_0_LABEL="Chatto Hub"CHATTO_AUTH_PROVIDERS_0_ISSUER_URL=https://hub.chatto.devCHATTO_AUTH_PROVIDERS_0_CLIENT_ID=...CHATTO_AUTH_PROVIDERS_0_CLIENT_SECRET=...CHATTO_AUTH_PROVIDERS_0_REQUEST_EMAIL=falseCHATTO_AUTH_PROVIDERS_0_AUTO_PROVISION=true
CHATTO_AUTH_PROVIDERS_1_ID=github-mainCHATTO_AUTH_PROVIDERS_1_TYPE=githubCHATTO_AUTH_PROVIDERS_1_LABEL=GitHubCHATTO_AUTH_PROVIDERS_1_CLIENT_ID=...CHATTO_AUTH_PROVIDERS_1_CLIENT_SECRET=...CHATTO_AUTH_PROVIDERS_1_AUTO_PROVISION=falseSupported fields are ID, TYPE, LABEL, CLIENT_ID, CLIENT_SECRET, ISSUER_URL, SCOPES, REQUEST_EMAIL, AUTO_PROVISION, and PROVIDER_OPTIONS_<KEY>. SCOPES is comma-separated, for example CHATTO_AUTH_PROVIDERS_0_SCOPES=openid,profile,groups.
Any CHATTO_AUTH_PROVIDERS_<index>_* variables replace providers from chatto.toml.
Chatto also accepts the older single-provider OIDC variables for compatibility:
CHATTO_AUTH_OIDC_ENABLED=trueCHATTO_AUTH_OIDC_ISSUER_URL=https://hub.chatto.devCHATTO_AUTH_OIDC_CLIENT_ID=...CHATTO_AUTH_OIDC_CLIENT_SECRET=...# CHATTO_AUTH_OIDC_LABEL="Chatto Hub"Those legacy variables create one oidc provider with id = "oidc". Do not combine counted CHATTO_AUTH_PROVIDERS_<index>_* variables with CHATTO_AUTH_OIDC_ENABLED.
[webserver]url = "https://chat.example.com"
[[auth.providers]]id = "github-main"type = "github"label = "GitHub"client_id = "..."client_secret = "..."auto_provision = false[webserver]url = "https://chat.example.com"
[[auth.providers]]id = "gitlab-main"type = "gitlab"label = "GitLab"client_id = "..."client_secret = "..."auto_provision = false[webserver]url = "https://chat.example.com"
[[auth.providers]]id = "staff-google"type = "google"label = "Google"client_id = "..."client_secret = "..."auto_provision = false[webserver]url = "https://chat.example.com"
[[auth.providers]]id = "discord-main"type = "discord"label = "Discord"client_id = "..."client_secret = "..."auto_provision = falseScopes
Section titled “Scopes”By default, Chatto requests the minimum provider scopes needed to identify the
provider account. Email scopes are only requested when request_email = true.
| Type | Scopes when request_email = false | Scopes when request_email = true |
|---|---|---|
oidc | openid, profile | openid, profile, email |
github | none | read:user, user:email |
gitlab | none | read_user |
google | openid, profile | openid, profile, email |
discord | identify | identify, email |
You can override scopes per provider:
[[auth.providers]]id = "chatto-hub"type = "oidc"issuer_url = "https://id.example.com"client_id = "..."client_secret = "..."scopes = ["openid", "profile", "groups"]For OIDC providers, Chatto always includes openid even if you omit it from a custom scope list.
request_email defaults to false. Set request_email = true to request provider email scopes. For OIDC, the default request is openid profile; Chatto can create, link, and sign in accounts from the provider sub without receiving an email claim.
Auto-provisioning
Section titled “Auto-provisioning”auto_provision controls whether an unlinked provider identity may create a new account.
auto_provision = falseis the safe default. Unlinked users are returned to the login screen with an explanation, and existing users can still link the provider from account settings.auto_provision = truecreates a short-lived pending account-creation flow after the provider callback. The user must explicitly confirm the username before the account is created.
Auto-provisioning never silently merges by email. If a person already has a local account, they should sign in with that account and link the provider from account settings.
Account matching
Section titled “Account matching”Chatto matches external logins by provider identity, not by email address.
- OIDC providers are matched by verified issuer URL plus subject.
- OAuth-only providers are matched by the configured provider ID plus provider user ID.
- Email claims are optional profile data and are not used to pick an account.
If a provider callback returns an identity that is not linked to an account, Chatto does not silently pick an account by email.
Set auto_provision = true on a provider to allow new users from that provider to create accounts. If auto_provision is omitted or false, an unlinked provider identity cannot create an account.
Existing users can link providers from their account settings. Linking requires the user to already be signed in, lets Chatto create a short-lived provider link-start URL, and asks the user to confirm the pending link after the provider callback. Pending create and link tokens are short-lived and scoped to that specific action.
Accounts created through an email-less provider are passwordless until the user adds a password in account settings. Password reset by email requires a verified email address, so operators running SSO without email should keep at least one trusted provider link available for affected users.
Verified email and verified factors
Section titled “Verified email and verified factors”A linked external identity is a verified sign-in factor. It is enough for login and for limits.max_users, even when the provider did not return an email address.
A Chatto verified email is stricter. Chatto creates one from a provider email only when the provider adapter has an explicit verification signal:
| Provider | When Chatto stores a verified email |
|---|---|
oidc | email is present and email_verified = true |
github | The GitHub emails API returns a verified primary email |
google | Goth profile data includes verified_email or email_verified |
discord | Goth profile data includes verified = true |
gitlab | Not currently promoted to a Chatto verified email |
Verified email matters for email password reset and for owners.emails owner promotion. A linked SSO identity alone does not match owners.emails.
Discovery fields
Section titled “Discovery fields”Public clients can discover configured providers through server discovery:
chatto.discovery.v1.ServerDiscoveryService.GetServerreturns provider IDs, types, labels, and login URLs inlogin.providers.
You can call the discovery RPC with Connect JSON:
curl -X POST https://chat.example.com/api/connect/chatto.discovery.v1.ServerDiscoveryService/GetServer \ -H 'Content-Type: application/json' \ -H 'Connect-Protocol-Version: 1' \ --data '{}'Provider IDs stay provider-specific, so an OIDC provider can use an ID such as chatto-hub while reporting its provider type as oidc.