What enterprise identity gives you
Elliptic lets you put your own identity provider in front of the workspace. Instead of every person managing a separate Elliptic password, you connect the directory your company already runs, and membership follows it. There are four building blocks: you verify a domain to prove you own it, you connect single sign-on (OIDC) so people log in through your IdP, you add SCIM 2.0 so accounts are created and deactivated automatically, and you can connect LDAP or Active Directory to authenticate directly against an on-prem directory. IdP group sync rides on top of SSO to turn directory groups into project roles.
All of this is configured under Settings. SSO, IdP group mappings, LDAP, and verified domains are write-protected behind the org admin or owner role, while the sign-in endpoints your members hit (/auth/sso/..., /auth/ldap/login) and the SCIM endpoints your IdP hits are public, authenticated by their own signed state or bearer token rather than by a session.
Domain verification
A verified domain is how you prove to Elliptic that your organization controls an email domain like acme.com. Verifying a domain unlocks domain-gated SSO, and a verified domain is globally unique, so one domain can be verified by exactly one workspace.
You add a domain, Elliptic hands you a DNS TXT record, you publish it at your DNS provider, and then Elliptic checks for it over DNS. Until the record is found, the domain sits in a Pending state.
- Add the domainIn Settings, open Verified domains, type the domain (for example
acme.com), and select Add domain. Elliptic normalizes what you type: it strips anyhttp://orhttps://and trailing slash, and if you paste a full email address it keeps only the part after the@. The domain is created in the Pending state. - Copy the TXT recordElliptic generates a unique token and shows you a TXT record of the form
elliptic-verify=<token>. The record name is the root of the domain (shown as@). Use the copy button to grab the exact value. - Publish it in DNSAt your DNS provider, add a TXT record on the domain with that
elliptic-verify=...value. DNS changes can take a few minutes to propagate. - VerifyBack in Elliptic, select Verify. Elliptic looks up the domain's TXT records and checks that the expected
elliptic-verify=<token>value is present. If it is, the domain flips to Verified and records the time. If it isn't there yet, you get a clear message to add the record and allow time for DNS to propagate, and you can retry.
Under the hood Elliptic resolves the TXT records over DNS-over-HTTPS (it queries https://dns.google/resolve), so it needs no special network setup and works the same on the hosted instance and a self-hosted one. The lookup reads only TXT records for the exact domain you added.
You can remove a domain at any time. Removing a verified domain frees it to be claimed again, so do it only when you intend to disconnect that domain from the workspace.
Single sign-on (OIDC)
SSO connects your organization to an OpenID Connect identity provider, gated by an email domain. Once it's enabled, anyone whose IdP email is on that domain can sign in through your IdP, and if they don't have a Elliptic account yet, one is created for them on first login (just-in-time provisioning). Elliptic ships OIDC today. SAML is a deferred follow-up and is not available yet.
Connect your IdP
There is one SSO connection per organization. You configure it in Settings under Single sign-on (OIDC) with these fields:
| Field | What it is |
|---|---|
| Email domain | The domain SSO is gated on, for example acme.com. Only users whose IdP email is on this domain are accepted. The domain is stored lowercased and is unique across organizations, so a domain connected to one org's SSO can't be connected to another's. |
| Issuer URL | Your IdP's OIDC issuer, for example https://idp.example.com. Elliptic appends /.well-known/openid-configuration to discover the authorization, token, and userinfo endpoints automatically, so you don't enter those by hand. |
| Client ID | The OAuth client ID for the application you register in your IdP. |
| Client secret | The client secret for that application. It's encrypted at rest and never returned. When editing an existing connection, leave it blank to keep the current secret. |
| Redirect URI | Where the IdP sends users back after they authenticate. Elliptic pre-fills this with your instance's /auth/sso/callback URL. Register the same value in your IdP. |
Register an OIDC application in your IdP with the redirect URI above, then paste the issuer, client ID, and client secret into Elliptic and select Save SSO. The connection carries an enabled flag, and the sign-in flow only works while it is enabled.
The sign-in flow
Once the connection is enabled and its domain is set, a member signs in through your IdP like this:
- Start by domainThe login surface calls
/auth/sso/start?domain=acme.com. Elliptic finds the enabled SSO connection for that domain, reads your IdP's discovery document, and returns the IdP authorization URL withscope=openid email profileand a signedstatevalue. If no enabled SSO is configured for the domain, it says so. - Authenticate at the IdPThe user is sent to your IdP, signs in there, and the IdP redirects back to the configured redirect URI with an authorization
codeand thestate. - Exchange and verifyElliptic calls
/auth/sso/callback?code=...&state=.... It verifies the signed state (which is short-lived, valid for ten minutes), decrypts the client secret, exchanges the code for tokens at the IdP's token endpoint, and fetches the user's profile from the userinfo endpoint. - Check the email domainElliptic reads the email from userinfo and requires its domain to match the connection's domain exactly. If the IdP returns no email, or the email is on a different domain, the login is rejected. This is the guardrail that keeps a connection scoped to the company that owns it.
- Provision and sign inIf no Elliptic account exists for that email, one is created just-in-time, marked email-verified, with the name from the IdP profile. If the user isn't yet a member of the org, they're added as a Member. Elliptic then issues the session cookies and the user is in.
IdP group sync
Group sync turns the groups your IdP reports into project roles inside Elliptic. You map an IdP group name to a project plus a role, and when a member signs in via SSO, the groups in their profile are reconciled against those mappings so they land in the right projects with the right access automatically. It's an extension of SSO, configured right below the SSO connection in Settings.
Map groups to project roles
Each mapping is a triple: an IdP group name, a project, and one of the project roles. Add as many as you need.
| Project role | Grants |
|---|---|
| Admin | Full control over the project, the highest project role. |
| Member | Works inside the project: tasks and the board. |
| Commenter | Can comment but not change project structure. |
| Viewer | Read-only access, the lowest project role. |
When a user belongs to several groups that map to the same project, the highest role wins. So if engineering maps a project to Member and eng-leads maps the same project to Admin, a user in both gets Admin. The ranking, from lowest to highest, is Viewer, Commenter, Member, Admin.
synced). Anyone you added to a project by hand is left completely alone: group sync will never change their role or remove them. Sync owns its own rows and nothing else.Reconcile computes the desired memberships from the user's groups, then: it adds a synced membership for any mapped project the user isn't in, changes the role on an existing synced membership when the mapping calls for a different role, and, when removal is enabled, removes synced memberships for projects the user no longer has a matching group for. Manual memberships are never in scope for any of these.
By default the connection runs sync on every login, and it reads groups from the groups claim in the IdP profile. Auto-removal of stale synced memberships is off by default, so the conservative behavior is to grant and update access without revoking it. These are connection-level defaults rather than toggles in the Settings UI today, so out of the box you get grant-and-update sync on each login.
Dry-run preview
Before you trust a set of mappings, the API can preview exactly what a sync would do for a given user and group set without changing anything. The preview runs the same reconcile engine in dry-run mode and returns the diff it would apply, split into adds, changes, and removes, each listing the project and the role. Nothing is written. Use it to sanity-check a new mapping or to understand why someone is landing in a project.
SCIM 2.0 provisioning
SCIM lets your IdP (Okta, Microsoft Entra ID, and others) create, update, and deactivate Elliptic members automatically, so org membership tracks your directory without anyone clicking Invite. Where SSO provisions a user the first time they happen to log in, SCIM provisions them up front and deactivates them the moment they're offboarded in your IdP. Elliptic implements SCIM 2.0 for users.
Mint a token and point your IdP at it
- Generate the tokenIn Settings under SCIM provisioning, select Generate token. Elliptic mints a per-org bearer token (it begins with
scim_) and shows you the raw value once. Copy it immediately, it won't be shown again. Generating again rotates the token: the old one is revoked and a new one is issued. - Copy the base URLElliptic shows the SCIM base URL for your org, of the form
/scim/v2/orgs/{org_id}on your instance. The Settings page renders it as a full URL you can copy. - Configure your IdPIn Okta or Entra, set up SCIM provisioning pointing at that base URL, with the token as the bearer credential. Your IdP will then create and manage users under
/scim/v2/orgs/{org_id}/Users.
# SCIM base URL your IdP points at
https://elliptic.sh/scim/v2/orgs/{org_id}
# every request carries the per-org bearer token
Authorization: Bearer scim_xxxxxxxxxxxxxxxxxxxxxxxxEvery SCIM request is authenticated by that bearer token and scoped to your org. A missing or non-matching token is rejected. The Settings page shows whether a token is configured, its non-secret prefix, and when it was last used, so you can confirm your IdP is actually talking to Elliptic. You can revoke the token to cut the connection off entirely.
The provisioning lifecycle
Your IdP drives the standard SCIM Users endpoints, and Elliptic maps them onto org membership:
| SCIM operation | What Elliptic does |
|---|---|
| POST /Users (provision) | Reads the user's email from userName (falling back to the first entry in emails) and their name. If no Elliptic account exists for that email, it creates one just-in-time, marked email-verified. If they aren't a member of the org, it adds them as a Member, and records a scim.user.provisioned event. |
| GET /Users, GET /Users/{id} | Returns SCIM User resources for the org's members, with active reflecting whether the person is still a member. |
| PUT /Users/{id} | Sets the user active or inactive based on the resource's active field (defaulting to active when absent). |
| PATCH /Users/{id} | Honors the common Azure and Okta 'replace active' patch op: Elliptic reads the active value from the operation whose path is active and activates or deactivates accordingly. |
| DELETE /Users/{id} | Deactivates the user (treated the same as setting active to false) and returns 204. |
Deactivating a user drops their org membership but preserves the account and everything they authored. Tasks, notes, meetings, and history stay intact, the person simply loses access to the workspace, and a scim.user.deactivated event is recorded. Re-activating them re-adds the membership as a Member.
LDAP / Active Directory
If you run an on-prem LDAP directory or Active Directory, you can have Elliptic authenticate members directly against it. People sign in with their directory username and password, Elliptic binds to the directory to check the credentials, and provisions them just-in-time on the first successful sign-in. There's one LDAP connection per organization.
Connect the directory
Configure the connection in Settings under LDAP / Active Directory. The form edits these fields:
| Field | What it is | Example |
|---|---|---|
| Server URI | The directory server to connect to. Use an ldaps:// URI for TLS. | ldaps://ad.example.com |
| Bind DN | The service account Elliptic binds as to search the directory. | cn=service,dc=example,dc=com |
| Search base | Where in the tree to search for the signing-in user. | dc=example,dc=com |
| Search filter | How to find the user by their username. {username} is substituted in, safely escaped. | (sAMAccountName={username}) |
| Email attribute | The directory attribute that holds the user's email. | mail |
| Bind password | The service account's password. Encrypted at rest and never returned. Leave blank when editing to keep the current one. | — |
The connection also carries a few settings that default to standard Active Directory values: TLS is on (the connection is made over SSL when the URI uses ldaps://), and the given-name and family-name attributes default to givenName and sn, which are combined to build the display name. With those defaults, a standard AD setup often needs little more than the server URI, bind DN, bind password, and search base. Like the other secrets here, the bind password is encrypted at rest and never returned.
Test the connection
Before you rely on it, use Test connection. Elliptic performs the service bind with your bind DN and password and runs a small sample search against the search base, then returns a plain-language result. On success you get a confirmation that it connected and how many sample entries the search base returned. On failure you get a specific message, for example that the service bind failed (check the bind DN and password) or that the connection itself couldn't be made. This turns directory misconfiguration into a readable diagnostic instead of a failed login later.
The login flow
When a member signs in with their directory credentials at /auth/ldap/login, Elliptic runs the standard service-bind-then-rebind pattern:
- Service bindElliptic binds to the directory as the configured service account (the bind DN and decrypted bind password). If that bind fails, the login is rejected.
- Search for the userIt runs your search filter with the submitted username substituted in (escaped to prevent injection) under the search base, requesting the email, first-name, and last-name attributes. If no entry matches, the login fails.
- Rebind as the userIt then attempts a fresh bind as the found user's distinguished name with the password they typed. A successful bind proves the password, a failed one rejects the login. This is the actual credential check.
- Provision and sign inOn success, Elliptic reads the email from the directory entry. If no Elliptic account exists for that email, it creates one just-in-time (email-verified, with the name built from the first and last attributes). If the user isn't a member of the org, it adds them as a Member, then issues the session.
