Authentication
Tindra supports password login and OAuth/OIDC single sign-on, with local authenticator-based MFA for both sign-in methods.
Password login
Password login is enabled when no SSO configuration is present. There is no public registration page: the installer or server administrator creates the first account, and additional users join by invitation. See Self-Hosting for account creation.
OAuth providers
Create your administrator account before enabling SSO, then configure your provider and the public callback base together:
OAUTH_REDIRECT_BASE=https://tindra.example.com
The callback URL pattern is:
{OAUTH_REDIRECT_BASE}/api/auth/{provider}/callback
Tindra supports GitHub, Google, Microsoft, Auth0, Zitadel, and generic OIDC providers. You can configure more than one provider; successfully initialized providers appear on the login page.
Setting the callback base or provider credentials selects SSO-only authentication, even if the configuration is incomplete or provider discovery fails. Configure all required values before restarting. See Disabling password login for the affected login and recovery flows.
GitHub
GITHUB_CLIENT_ID=your-client-id
GITHUB_CLIENT_SECRET=your-client-secret
Register an OAuth app with callback https://tindra.example.com/api/auth/github/callback. GitHub must supply a verified email for first-time email linking or invitation acceptance.
GOOGLE_CLIENT_ID=your-client-id
GOOGLE_CLIENT_SECRET=your-client-secret
Register an OAuth client with authorized redirect URI https://tindra.example.com/api/auth/google/callback.
Microsoft
MICROSOFT_CLIENT_ID=your-client-id
MICROSOFT_CLIENT_SECRET=your-client-secret
MICROSOFT_TENANT=your-directory-tenant-uuid
Use the Directory (tenant) ID in UUID format and register https://tindra.example.com/api/auth/microsoft/callback as the redirect URI. Shared tenant aliases such as common, organizations, and consumers are not supported.
Microsoft sign-in requires explicit linking to an existing Tindra account because an email address alone is not proof of a verified email. Use the administrative linking procedure below. An invitation alone does not replace this linking step for a provider without verified-email claims.
Auth0
AUTH0_DOMAIN=your-tenant.auth0.com
AUTH0_CLIENT_ID=your-client-id
AUTH0_CLIENT_SECRET=your-client-secret
Callback: https://tindra.example.com/api/auth/auth0/callback.
Zitadel
ZITADEL_ISSUER_URL=https://your-instance.zitadel.cloud
ZITADEL_CLIENT_ID=your-client-id
ZITADEL_CLIENT_SECRET=your-client-secret
Callback: https://tindra.example.com/api/auth/zitadel/callback.
Generic OIDC
OIDC_ISSUER_URL=https://your-provider.example.com
OIDC_CLIENT_ID=your-client-id
OIDC_CLIENT_SECRET=your-client-secret
OIDC_PROVIDER_NAME=oidc
The issuer must support OIDC discovery. OIDC_PROVIDER_NAME defaults to oidc and determines the provider identity, login-button label, and callback path. With the example above, register https://tindra.example.com/api/auth/oidc/callback. If you change the name, update the callback and account-linking configuration too.
New user provisioning
SSO admission follows these rules:
| Account state | What happens |
|---|---|
| Provider identity already linked | Tindra signs in to the linked account. |
| Unlinked identity with a verified email matching an existing account | Tindra links it to that account, preserving its permissions. |
| New verified email with an unused, unexpired matching invitation | Tindra creates the account and consumes the invitation, subject to USER_LIMIT. |
| New email without a valid invitation | Sign-in is refused; an administrator must invite the user. |
| Unlinked identity without a verified email | Automatic linking is refused; use administrative linking. |
Invite users from Settings > Users > Invite user, using the email their provider verifies. They can then sign in with SSO without creating a local password. New SSO accounts have no management permissions by default. Assign permissions after they join, as described in User Management.
First user gets all permissions
Bootstrap the instance with the installer or tindra users create; the CLI creates an administrator with all management permissions. SSO does not automatically create the first administrator. For an existing instance, link your existing administrator rather than creating another account just to enable SSO.
Administrative SSO linking
A server administrator can link an existing Tindra account to a provider identity when verified-email linking is unavailable:
docker compose exec tindra /tindra users link-sso user@example.com \
--provider microsoft \
--subject '<verified-token-sub>'
Use the exact provider name configured in Tindra and the sub claim from a verified ID token issued for this Tindra application's client ID. Confirm the identity with the provider administrator before linking it. For Microsoft, sub is application-specific and is not the Azure Object ID (oid).
The command requires database access from the server and an existing account. If the account does not exist, an administrator must create it first; users create grants administrative permissions, so adjust those in Settings > Users before handing access to a regular member. Linking preserves the account's current permissions and MFA requirements, and an existing identity link cannot be reassigned.
MFA enforcement
With REQUIRE_MFA=true (the default), users without a local authenticator are sent to /setup-mfa after password or SSO login. Their session can access only the account and MFA-enrollment endpoints until setup is complete. Other session-authenticated API requests return 403 with X-Tindra-MFA-Required: setup.
Scan the QR code with an authenticator app, then confirm a six-digit TOTP code. Once enrolled, users must verify their local authenticator on every password or SSO login, even if the identity provider also uses MFA. Login challenges expire and can complete a login only once; restart sign-in if a challenge has expired or already been used.
To make enrollment optional:
REQUIRE_MFA=false
This does not bypass the authenticator for users who have already enrolled. Project API tokens authenticate separately and do not require an interactive TOTP code.
Account name in authenticator apps
The entry appears as hostname: user@example.com, using the hostname from PUBLIC_URL. Scheme, port, and path are stripped, so https://tindra.example.com:8443/app shows as tindra.example.com. If no usable hostname is available or the address is IPv6, the label falls back to Tindra.
Replacing an authenticator
Replacing an enrolled factor through the MFA setup API requires a code from the current authenticator. The new secret remains pending until its code is confirmed, so starting replacement does not immediately disable the existing factor. If the current authenticator is lost, use administrator-assisted recovery.
Locked out
A server administrator can clear the local authenticator:
docker compose exec tindra /tindra users disable-mfa you@example.com
The user then authenticates with the instance's configured method, password or SSO, and enrolls again if MFA is required. This leaves the password and SSO link intact. See User Management for administrative API access and password-reset recovery.
Disabling password login
Any nonempty OAUTH_REDIRECT_BASE, provider client ID/secret, OIDC_ISSUER_URL, ZITADEL_ISSUER_URL, or AUTH0_DOMAIN selects SSO-only authentication. A provider does not have to initialize successfully for that policy to apply.
SSO-only mode disables local password login, password-based invitation acceptance, and password-reset redemption. A reset link cannot bypass that policy. If all configured providers fail to initialize, fix the configuration or provider availability and restart Tindra; password login does not become a fallback automatically.
To intentionally restore local login, remove the SSO callback base and provider configuration from the effective server environment and restart. Make sure the administrator has a usable local password. Do not leave old credentials in a mounted .env file or Compose environment block.
Troubleshooting
| Message or symptom | Next step |
|---|---|
| Invitation required | Invite the exact email verified by the provider; replace expired or already-used invitations. |
| Provider must verify your email | Verify the email with the provider, or ask the server administrator to link the verified provider subject explicitly. |
| User limit reached | Free a user slot or increase the instance's user limit, then retry. |
| SSO required but no provider buttons work | Check the server's provider-initialization logs, callback base, credentials, issuer, and Microsoft tenant UUID. Correct the configuration and restart. |
| Login attempt does not match this browser | Restart sign-in in the browser where you will finish it, with cookies enabled. |
| MFA setup required | Complete local enrollment, including after SSO login or an administrator clears the authenticator. |