Password Login via an External Backend
Operaide can delegate password validation to an HTTP backend you run. Users enter email and password on the login page, Operaide forwards the credentials to the backend via HTTP Basic, and the backend returns OIDC-compatible claims. Operaide creates and signs in the user based on those claims.
Useful when the user directory lives outside Operaide: corporate LDAP or Active Directory (behind a thin HTTP gateway), a human-resources API, or a custom identity service you run as a sidecar container. Operaide never talks LDAP directly. Exposing the backend as an HTTP endpoint is the customer's responsibility.
Prerequisites
- An HTTP endpoint you control that accepts HTTP Basic authentication.
- The endpoint is reachable from the Operaide container (same network, sidecar, or public URL over TLS).
AUTH_HTTP_BASIC_*environment variables editable on the Operaide deployment.
What your backend must expose
Operaide sends a GET request to the configured URL with the user's email and password in a standard Authorization: Basic <base64(email:password)> header.
On valid credentials, the backend must respond with 200 OK and a JSON body carrying OIDC-compatible claims:
{
"sub": "a-stable-unique-id-for-this-user",
"email": "alice@company.com",
"name": "Alice Example",
"given_name": "Alice",
"family_name": "Example",
"groups": ["engineering", "admins"]
}
| Field | Required | Purpose |
|---|---|---|
sub | yes | Stable user id. Operaide matches the user by this value on every login. Must not change when the email changes. |
email | yes | Current primary email address. Updated on re-login. |
name | no | Full display name. |
given_name | no | First name. |
family_name | no | Last name. |
groups | no | Array of group names. Stored on the user record. Not yet mapped to Operaide roles. |
On invalid credentials, respond with 401. Any non-2xx status is treated as authentication failed.
The backend is free to run LDAP binds, query Active Directory, call an HR API, or generate claims any other way. Operaide treats the HTTP response as the source of truth.
Configure Operaide
Set these environment variables on the deployment:
AUTH_HTTP_BASIC_ENABLED=true
AUTH_HTTP_BASIC_AUTH_URL=https://your-backend.example.com/auth
Restart the container. The login page now validates email and password against your backend instead of against the built-in password database.
Identity stays stable across email changes
Operaide matches users on every login by sub first. The internal user record stays the same even when the backend renames the user's email. The new email is moved to the front of the user's email list. Older addresses are retained so invites to old addresses still work and the user can still sign in via an earlier email.
Example: Alice marries and her email changes from alice.smith@company.com to alice.jones@company.com. The backend keeps returning the same sub for both addresses. On the next sign-in with the new email, Operaide finds the same account and promotes alice.jones@... to the primary email slot. alice.smith@... stays on the record.
First sign-in attaches to an organization
The first successful External Password Login for a given user creates the Operaide account and attaches it to an organization. Which organization depends on the emailDomainRegex setting.
See Auto-Provisioning for the shared rule, how to set the regex, deployment shapes, and what to do when a sign-in fails silently.
Troubleshooting
"Authentication failed (status 401)". The backend rejected the credentials. Check the backend's own logs.
"Auth backend claims invalid: <field>: <reason>".
The backend responded 200 but the body does not match the required OIDC schema. The error names the missing or invalid field. Fix the backend's response.
"Auth backend not reachable".
Network-level failure (connection refused, timeout, DNS). Verify that the container can reach the value in AUTH_HTTP_BASIC_AUTH_URL.
Login succeeds at the backend but Operaide rejects with "No Organization found".
No organization has an emailDomainRegex that matches the claim email. See Auto-Provisioning: When auto-provisioning fails silently.
Limitations
- One backend per deployment.
AUTH_HTTP_BASIC_AUTH_URLis a single value. Routing across multiple backends happens inside your own backend, not in Operaide. - Password login becomes single-source. When
AUTH_HTTP_BASIC_ENABLED=true, the built-in email-and-password path is replaced. Existing Operaide-internal passwords are no longer consulted. OIDC redirect login (AUTH_OPENID_ENABLED=true) stays available in parallel if also configured. - No group-to-role mapping. The
groupsclaim is stored on the user record but does not drive Operaide roles yet. Role assignment happens through Organization Settings. - HTTPS is expected in production. Credentials leave Operaide in an HTTP Basic header. In production the backend URL must be
https://. Operaide does not enforce this at configuration time.
Common mistakes
- Using the email as
suband then renaming the email.submust be stable across renames. Use an immutable identifier such as an LDAP objectGUID, a database primary key, or an employee ID. Otherwise re-login after an email change creates a duplicate account. - Returning
200 OKwith an error in the body. Operaide inspects the status code and the JSON shape. Any2xxwith a valid claim object is treated as success. Use status codes to signal failure. - Logging request headers in the backend. Operaide does not log the password, but the backend receives it in the Basic header. Ensure the backend omits the
Authorizationheader from logs. - Omitting
sub. Withoutsub, Operaide cannot match the user on re-login and treats every login as a candidate for account creation. Always includesub.