Single sign-on
Let your people sign in at your own identity provider — Entra ID, Okta, Keycloak, Google Workspace — instead of keeping a second password for mail.
If your organisation already has an identity provider, your people should not need a second password just for mail. With single sign-on they sign in where they always sign in, and Nixt Server issues its own tokens on the strength of that — so your corporate password never reaches IMAP, JMAP or submission at all.
Nixt Server is an OpenID Connect relying party. It works with anything that speaks OpenID Connect: Microsoft Entra ID, Okta, Keycloak, Google Workspace, Ping, and most others.
Before you start
You need two things from your provider:
- The issuer URL. Something like
https://login.microsoftonline.com/<tenant-id>/v2.0orhttps://keycloak.example.com/realms/staff. It must behttps. - A client id and secret, from registering Nixt Server as an application there.
When you register the application, give it this redirect URI:
https://mail.example.com/oauth/federated/callback
Ask for the openid and email scopes, and make sure the provider releases an email address — that is what Nixt Server matches against a mailbox.
Turn it on
sudo -u versealx versealx-server admin put tenants/1/federation \
"issuer=https://keycloak.example.com/realms/staff" \
clientId=versealx-server \
"clientSecret=the-secret-from-your-provider"
| Field | Meaning |
|---|---|
issuer | The issuer URL, exactly as your provider spells it. Every token is checked against it. |
clientId | What your provider knows Nixt Server as. |
clientSecret | The secret that goes with it. Required the first time; leave it out later and the stored one is kept. It is never shown again. |
scopes | What to ask for. openid email if you leave it out; openid is always added. |
claim | Which claim holds the mailbox address. email if you leave it out. Entra ID users often want upn. |
enabled | false configures it without switching it on. |
Check what is configured at any time — the secret is never in the answer:
sudo -u versealx versealx-server admin get tenants/1/federation
The discoveryUrl in that answer is where Nixt Server will fetch your provider’s configuration from. Open it in a browser to confirm it is the right one.
Turning it off
sudo -u versealx versealx-server admin put tenants/1/federation \
"issuer=https://keycloak.example.com/realms/staff" clientId=versealx-server enabled=false
That keeps everything you typed and stops using it. To forget it entirely:
sudo -u versealx versealx-server admin delete tenants/1/federation
What your people see
The sign-in page gains a second button: Sign in with your organisation. They type their address, press it, sign in wherever they normally do, and come back signed in.
Both ways of signing in work: the one an app like Nixt Mail uses, and the one a terminal uses when you run versealx login.
Passwords keep working. Turning on single sign-on does not take away the passwords your accounts already have — an account with one can still use it. If you want people to use the provider and nothing else, remove their passwords.
Matching people to mailboxes
The address in the provider’s token has to match a mailbox in the tenant. ada@example.com at your provider signs in to ada@example.com here.
Signing in does not create a mailbox. Somebody who exists at your provider and has no mailbox here is refused. Create accounts first, with SCIM, the admin API or the command line — those paths check who is asking and write it down, and a sign-in that quietly made accounts would do neither.
A disabled account stays disabled. If you disable or remove someone here, they do not sign in, whatever your provider says about them. That is usually the reason you disabled them.
If the provider says an address is not verified, the sign-in is refused. Set claim to a claim your provider treats as authoritative — upn on Entra ID — if its email is self-service.
A provider inside your network
Two settings in versealx-server.toml cover the on-premises case:
[federation]
allow_private = true
trust = "/etc/versealx-server/internal-ca.pem"
| Setting | When you need it |
|---|---|
allow_private | Your provider is on a private, internal or loopback address. Off by default: the issuer is a URL a tenant administrator typed, and without this a tenant could point the server at something on your internal network. |
trust | Your provider’s certificate was signed by your own certificate authority rather than a public one — usual for AD FS and on-premises Keycloak. This adds a root; the certificate is still checked. |
Both are node settings rather than tenant settings, so a tenant cannot grant itself either.
When a sign-in does not work
The page says only that the sign-in did not complete. That is deliberate — it is shown to whoever is standing at it, and they have not yet proved they are anyone, so it must not say whether an address exists or what happened to it.
The reason is in the server’s log:
sudo journalctl -u versealx-server -n 50 | grep -i federat
| What the log says | What to do |
|---|---|
it is issued for … not … | The issuer in your configuration is not the one the provider publishes. Copy it exactly from the discovery document. |
no key the provider publishes verifies it | The provider signs with an algorithm Nixt Server does not take. RSA and P-256/P-384 ECDSA are taken. |
it carries no nonce / its nonce is not the one this sign-in asked for | The provider is not returning the nonce. Most providers need nothing set for this; check the application registration. |
it carries no email | The provider is not releasing the claim. Add the scope that releases it, or set claim to one it does release. |
the provider says that address is not verified | See Matching people to mailboxes above. |
not on the public Internet | Set allow_private, above. |
signed in at the provider and has no mailbox in this tenant | Create the account first. |
Something unclear or out of date on this page? Tell us.