Skip to content

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.

TypeUse for
oidcAny standards-compatible OIDC provider
githubGitHub OAuth apps
gitlabGitLab OAuth applications
googleGoogle OAuth clients
discordDiscord OAuth2 applications

Other provider types are not exposed as curated providers yet. Use oidc for standards-compatible OIDC providers.

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 #.

Register this callback URL with each external provider:

https://chat.example.com/auth/providers/{providerID}/callback

For example, a provider with id = "github-main" on https://chat.example.com uses:

https://chat.example.com/auth/providers/github-main/callback

Chatto 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.

[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 = "..."

issuer_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.

Chatto requests provider-specific default scopes:

TypeDefault scopes
oidcopenid, profile, email
githubread:user, user:email
gitlabread_user
googleopenid, profile, email
discordidentify, 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.

Set request_email = false to omit the default email scope for providers where Chatto adds one automatically.

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 treated as profile data and are not used to pick an account.

If a provider callback returns an identity that is not linked to a Chatto account, login is rejected until a future account-linking or account-creation flow explicitly links that identity.

Public clients can discover configured providers in two places:

  • GraphQL Server.authProviders returns provider IDs, types, labels, and login URLs.
  • GET /api/server returns the same metadata in authProviders.

Older clients may still read /api/server.authMethods. That legacy field stays method-oriented, so OIDC appears as oidc even when the configured provider ID is something like chatto-hub.