Native SAML migration
Today, Appsmith signs users in with SAML through a Keycloak server that runs inside the Appsmith container. Appsmith is replacing Keycloak with SAML built into the Appsmith server, called native SAML. Starting with v2.7, you can switch to native SAML, and switch back, with one environment variable.
- Keycloak stays the default in v2.7. Nothing changes for your users until you switch.
- Appsmith copies your SAML configuration from Keycloak every time it starts and after every SAML change in Admin Settings. Admin central shows whether the copy is ready for native SAML.
- A later release makes native SAML the default, and keeps Keycloak available so you can roll back. A release after that removes Keycloak.
Switch to native SAML and sign in once while Keycloak is still available. This shows that your configuration works natively before native SAML becomes the default.
This page covers the v2.7 opt-in on self-hosted instances where SAML is configured.
What stays the same
- The URLs in your identity provider (IdP) stay the same. The default Assertion Consumer Service (ACS) URL is
https://<your-domain>/auth/realms/appsmith/broker/saml/endpoint, and the default entity ID ishttps://<your-domain>/auth/realms/appsmith. Keep any custom entity ID already configured for your instance. - The SAML button stays the same. Native SAML uses the existing Appsmith accounts. Wait for the account links to finish copying before testing returning users.
- SAML changes in Admin Settings still go to Keycloak first. Appsmith then copies them, so Keycloak stays current if you roll back.
Check readiness in Admin central
- Sign in as an instance administrator.
- Go to Admin Settings > Instance > Admin central.
- Find the native SAML entry. While Keycloak is in use, it's titled Before switching to native SAML. After you switch, it's titled About native SAML.
| Admin central shows | What it means | What to do |
|---|---|---|
| Native SAML is being prepared | Appsmith is copying your SAML configuration from Keycloak. | Wait, then refresh the page. |
| Native SAML is ready to test | The copy is complete and native SAML can run it. | Switch to native SAML. |
| Native SAML needs administrator action | The copy lists one or more required actions. Native SAML refuses sign-in until they're resolved. Keycloak sign-in keeps working. | Resolve each required action, then retry the copy. |
| Native SAML could not be prepared | Appsmith couldn't copy the configuration. The entry shows a failure code. | Fix the cause, then retry the copy. |
| Native SAML is on, waiting for a first sign-in | You switched to native SAML, and nobody has signed in with it yet. | Sign in once with SAML. |
| Native SAML is verified | A user signed in with native SAML using the current configuration. | Nothing. |
| SAML is back on Keycloak | You switched from native SAML back to Keycloak. | Switch again when you're ready. |
The entry also lists details such as when the configuration was copied, how many Keycloak account links were copied, and the last native sign-in that was refused. It never shows configuration values.
Switch to native SAML
Before you begin:
- Upgrade to v2.7.
- Wait for the configuration and Keycloak account links to finish copying. Check the account-link count and copy time in Admin central.
- Resolve any required actions. If the only remaining action is
NATIVE_SP_CERTIFICATE_REQUIRED, complete the certificate-trust step below. Otherwise, Admin central should show Native SAML is ready to test before you switch. - Plan for a restart. Appsmith reads the SAML engine only when it starts.
Confirm certificate trust if your IdP requires signed requests
Skip this step if Admin central doesn't list NATIVE_SP_CERTIFICATE_REQUIRED.
When your IdP requires signed sign-in requests, native SAML signs them with its own certificate, not Keycloak's. Your IdP must trust that certificate before native sign-in works.
-
Open
https://<your-domain>/api/v1/saml/native/metadata. This metadata contains the native SAML signing certificate. -
Add that certificate to your IdP as a request-signing certificate. Keep Keycloak's certificate in place too, so Keycloak sign-in keeps working until you switch, and after a rollback. If your IdP accepts only one request-signing certificate, plan a maintenance window to replace it and switch engines. Keep a copy of Keycloak's certificate for rollback.
-
Confirm the change in Appsmith. While signed in as an instance administrator, open your browser's developer console on any Appsmith page and run:
const response = await fetch("/api/v1/admin/sso/saml/native/certificate-trust", {
method: "POST",
headers: { "X-Requested-By": "Appsmith" },
});
if (!response.ok) {
throw new Error(`Certificate-trust confirmation failed: HTTP ${response.status}`);
}
await response.json();After the request succeeds, refresh Admin central. It shows Certificate trust confirmed, and
NATIVE_SP_CERTIFICATE_REQUIREDis no longer listed.
Changes on the IdP side, such as a new IdP signing certificate, don't require a new confirmation. You confirm again only after you disconnect SAML and configure it again, because that creates a new native SAML certificate.
Set the SAML engine
Set APPSMITH_SAML_ENGINE to native and restart Appsmith.
- Docker
- Kubernetes
-
Go to your installation folder and open the
stacks/configuration/docker.envfile. -
Add the following line:
APPSMITH_SAML_ENGINE=native -
Restart Appsmith:
docker-compose restart appsmith
These examples use appsmith as the Helm release, namespace, and workload name. Substitute your installation's names where needed. Keep the current chart and Appsmith image versions when changing only the SAML engine.
-
Check the installed chart version, then save your current values to a file:
helm list -n appsmith
helm get values appsmith -n appsmith -o yaml > values.yaml -
In
values.yaml, set the variable underapplicationConfig:applicationConfig:
APPSMITH_SAML_ENGINE: "native" -
Apply the updated values with the installed chart version. Replace
<chart-version>with the version from the CHART column ofhelm list, without theappsmith-prefix:helm upgrade appsmith appsmith-ee/appsmith --version <chart-version> -f values.yaml -n appsmith -
Restart the Appsmith workload so its pods read the new value, then wait for the rollout. Changing the Helm value alone might not restart existing pods. For the default StatefulSet:
kubectl rollout restart statefulset/appsmith -n appsmith
kubectl rollout status statefulset/appsmith -n appsmith --timeout=10mIf your installation uses a Deployment, replace
statefulset/appsmithwithdeployment/appsmith. If you changed the workload name, find it withkubectl get statefulset,deployment -n appsmithand use that name.
For other platforms, see Configure environment variables.
After the restart, check the engine label on the native SAML entry in Admin central. It must show Native engine for native, or Keycloak engine when rolling back to keycloak.
Sign in once
After Appsmith restarts, wait for the account-link copy to finish, then sign in with SAML. Check that you reach the expected account and workspaces. Test a returning user and, if your instance allows sign-up, a new user.
The first successful native sign-in changes the Admin central entry to Native SAML is verified. This confirms that sign-in worked for that user and the current configuration; it doesn't confirm every user or IdP configuration.
If sign-in fails, see Sign-in errors, or roll back.
Roll back to Keycloak
If you replaced Keycloak's request-signing certificate in the IdP, restore it first. Then set APPSMITH_SAML_ENGINE to keycloak, or remove the variable, and restart Appsmith. Use the same steps as in Set the SAML engine.
Users sign in through Keycloak again, to the same accounts. Admin central shows SAML is back on Keycloak. You don't need to sign in to Appsmith to roll back.
Required actions
While Admin central lists a required action, native sign-in is refused. Resolve the action before switching engines. You can keep using Keycloak while resolving actions specific to native SAML.
| Required action | Cause | How to resolve |
|---|---|---|
NATIVE_SP_CERTIFICATE_REQUIRED | Your IdP requires signed sign-in requests, and hasn't been confirmed to trust the native SAML certificate. | Confirm certificate trust. |
UNSUPPORTED_IDP_SETTING | A Keycloak identity provider setting has no native equivalent. Admin central names the setting. | See the table below. |
UNSUPPORTED_MAPPER | A Keycloak attribute mapper does something other than import the email, the first or last name, or an Appsmith claim. Admin central names the mapper. | Remove or replace the mapper in Keycloak. |
CONFLICTING_MAPPER | Several Keycloak mappers write the same claim, or the email, from different attributes. Admin central names the mappers. | Keep one mapper for each claim in Keycloak. |
Settings that UNSUPPORTED_IDP_SETTING can name:
| Setting | What it means | How to resolve |
|---|---|---|
enabled | The SAML identity provider is turned off in Keycloak. | Turn it on, or disconnect SAML. |
linkOnly | The identity provider only links accounts and doesn't sign users in. | Turn off Account linking only in Keycloak. |
firstBrokerLoginFlowAlias, postBrokerLoginFlowAlias | Keycloak runs a custom flow during sign-in. | Use Keycloak's default flows. |
authnContextClassRefs, authnContextDeclRefs | Keycloak asks the IdP for a specific authentication context, such as multi-factor authentication. | Enforce the requirement in your IdP instead, and remove it from Keycloak. |
wantAssertionsEncrypted | The IdP encrypts assertions. Native SAML doesn't support encrypted assertions. | Turn off assertion encryption in the IdP and in Keycloak. |
signatureAlgorithm | Keycloak signs requests with an algorithm other than RSA-SHA256. | Set the algorithm to RSA_SHA256 in Keycloak. Your IdP must accept it. |
useMetadataDescriptorUrl | Keycloak reloads the IdP's signing keys from its metadata URL. Native SAML trusts only the certificates copied from Keycloak. | First make sure Keycloak holds the IdP's current signing certificate, then turn off Use metadata descriptor URL. |
You change these settings in the Keycloak admin console at https://<your-domain>/auth. To sign in to it, use the Keycloak administrator credentials in the docker.env file.
After you resolve an action, restart Appsmith or retry the copy. The action disappears once a new copy no longer finds it.
Advisories
Advisories suggest improvements. They never stop sign-in, under either engine.
| Advisory | What it means | What to do |
|---|---|---|
NEW_USER_EMAIL_UNCONFIRMED | No email attribute is mapped, and some IdPs ignore the email-format NameID Appsmith asks for. Returning users sign in through the account link copied from Keycloak. A new user signs in with the email the IdP sends as an email-address NameID, in the attribute urn:oid:1.2.840.113549.1.9.1, or in a common email attribute: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress, mail, or email. Otherwise, native SAML asks them to type it once, as Keycloak does. An untrusted common email attribute that names an existing account needs a confirmation link. | Nothing is required. To skip the email form, make sure your IdP sends the email in one of those places. A native sign-in that receives the email from the IdP clears this advisory. |
NEW_USER_EMAIL_MISSING | No email attribute is mapped, and Appsmith doesn't ask the IdP for an email-format NameID. Returning users sign in through their account link. A new user signs in with the email the IdP sends in the attribute urn:oid:1.2.840.113549.1.9.1, or in a common email attribute: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress, mail, or email. Otherwise, native SAML asks them to type it once, as Keycloak does. An untrusted common email attribute that names an existing account needs a confirmation link. | Nothing is required. To skip the email form and the confirmation link, have your IdP send the email in an attribute named urn:oid:1.2.840.113549.1.9.1. Keycloak and native SAML both read it, so nothing changes in Appsmith. In Okta, add an attribute statement with that name, name format URI Reference, and value user.email. |
NAME_IMPORTERS_DISAGREE | Several Keycloak mappers import the first or last name from different attributes. Native SAML uses the first one by mapper name. | Keep one mapper for each name in Keycloak. |
When the IdP sends no email
A returning user with a copied or native account link signs in through that link. A new user needs an email for their Appsmith account. When the IdP sends none, native SAML shows a Finish signing in page that asks for the email and name, as Keycloak does. The user types them once. Native SAML links the email to the user's IdP identity, so the next sign-in skips the page.
Appsmith then emails a confirmation link to the typed address, whether or not an account has it. Only the owner of the address can open it, so no one can sign in to someone else's account, or claim an address for later, by typing it. The link expires after 15 minutes and works only in the browser where the sign-in started. Opening it signs the user in to the account with that email, or creates one with the email marked as verified.
- Mail is required. The page appears only when mail is turned on (
APPSMITH_MAIL_ENABLED) and a base URL is set for the link (APPSMITH_BASE_URL). Without them, a new user whose IdP sends no email can't sign in, and getssaml_email_missing. - Sign-up rules apply. If the email has no account, and sign-up is turned off or the email's domain isn't allowed, the sign-in fails with
saml_email_not_allowedbefore any link is sent.
The page works only in the browser that started the sign-in, and only for 10 minutes. Admin central counts how many times the page was shown, in the Email prompts issued row.
To skip the page entirely, have your IdP send the email. See NEW_USER_EMAIL_MISSING in Advisories for where to send it.
Email from a common attribute
Native SAML also reads the email from common attributes that Keycloak reads only when an administrator maps them: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress, mail, and email. Some IdPs let users set these values themselves, for example Auth0 with public sign-up. Unless an administrator explicitly trusts an attribute as described below, native SAML handles it as follows:
- A new email creates an account and signs in, with no extra step.
- An email that already has an account, or one listed in
APPSMITH_ADMIN_EMAILS, gets the same confirmation link as a typed email. Without mail, the sign-in fails withsaml_email_in_use.
When a returning user's account link supplies the email, no confirmation is needed. To avoid confirmation for a new link, have your IdP send the email as an email-address NameID or in the attribute urn:oid:1.2.840.113549.1.9.1.
If the native SAML entry in Admin central offers Trust attribute as the email, you can choose to trust that attribute. Use this only when your IdP controls the value and users can't change it. The Email read from a common attribute row names the attribute seen during sign-in.
Trusting it lets an existing account sign in without a confirmation link. Other untrusted common attributes still need confirmation for existing accounts. Copying the configuration from Keycloak keeps the choice. To undo it, click Stop trusting attribute.
If the trust button isn't available, use the IdP email settings described above or configure mail. You don't need this button to use native SAML.
Sign-in errors
When a failed sign-in redirects to the Appsmith sign-in page, its URL contains an error code. Some failures still show a generic message. Use the URL code and Last refused native sign-in in Admin central to find the cause.
Invalid or oversized requests, or too many requests, can return HTTP 400, 413, or 429 without a redirect. For 429, wait and try again.
| Error code | Cause | What to do |
|---|---|---|
saml_certificate_action_required | Your IdP requires signed requests, and the native SAML certificate isn't confirmed yet. | Confirm certificate trust. |
saml_action_required | Admin central lists a required action. | Resolve the required actions. |
saml_sync_required | An administrator changed SAML settings, and Appsmith hasn't copied them yet. | Wait a few seconds and try again. If Admin central shows Native sign-in paused, retry the copy. |
saml_email_missing | A new user signed in, and the IdP didn't send their email. Either the NameID is transient, so Appsmith can't link a typed email to the user, or mail isn't set up, so Appsmith can't confirm a typed email. | Have your IdP send the email, use a persistent NameID format, or set up mail. |
saml_email_in_use | A new user's email came from a common email attribute and already belongs to an Appsmith account, and Appsmith can't send a confirmation link. | Have your IdP send the email as an email-address NameID or in the attribute urn:oid:1.2.840.113549.1.9.1, or set up mail. If Admin central offers a trust button, you can trust the attribute. |
saml_email_not_allowed | A new user typed an email that sign-up rules don't allow. Sign-up is turned off, or the email's domain isn't allowed. | Have your IdP send the email, or change the sign-up settings. |
saml_failed | Any other reason. | Check Last refused native sign-in in Admin central, described below. |
Last refused native sign-in in Admin central shows the reason for the most recent refusal:
| Reason | What to check |
|---|---|
SIGNATURE_MISSING | The IdP signed neither the response nor the assertion. Configure the IdP to sign one of them. |
SIGNATURE_INVALID | Check the backend logs for the cause. If the certificate is unusable or doesn't match, add the IdP's current signing certificate to the SAML identity provider in Keycloak, then restart Appsmith or retry the copy. If the log says signature uses a refused algorithm, set the IdP to use RSA-SHA256 signatures and SHA-256 digests instead of MD5 or SHA-1; replacing the certificate alone won't fix that. |
EMAIL_MISSING | The response had no email, and the user has no account link. Either the NameID is transient, or mail isn't turned on (APPSMITH_MAIL_ENABLED) or no base URL is set (APPSMITH_BASE_URL), so a typed email can't be confirmed. |
EMAIL_IN_USE | A new user's email came from a common email attribute and belongs to an existing account, and Appsmith couldn't send a confirmation link. Mail isn't turned on (APPSMITH_MAIL_ENABLED), or no base URL is set for the link (APPSMITH_BASE_URL). |
OTHER | Look for Rejected SAML assertion or SAML sign-in failed in the backend logs. |
A sign-in also fails with saml_failed when:
- It took more than 30 minutes from clicking the SAML button to returning from the IdP.
- It started in one browser and finished in another.
- It started from the IdP's app dashboard instead of the Appsmith sign-in page.
Retry the copy
When Admin central shows Native SAML could not be prepared, Native SAML needs administrator action, or Native sign-in paused, fix the cause first. Then click Retry copy on the native SAML entry.
Appsmith copies the configuration from Keycloak again, without a restart, and the entry shows the result. If the copy fails again, the entry shows the new failure code. Restarting Appsmith also copies the configuration.
The button shows only while a new copy can change the result.
Differences from Keycloak
- Sign-in starts on the Appsmith sign-in page. Native SAML doesn't support sign-in started from the IdP's app dashboard.
- Encrypted assertions aren't supported.
- A typed email needs proof. When the IdP sends no email, both engines ask a new user to type one. Keycloak creates or signs in to the account for that email right away. Native SAML first sends a confirmation link to that address, so it needs mail. See When the IdP sends no email.
- Common email attributes are read, with care. Native SAML reads the email from common attributes without a mapper. Reaching an existing account requires a confirmation link unless an administrator has explicitly trusted the attribute. See Email from a common attribute.
- The IdP must sign the response or the assertion. Native SAML always checks the signature.
- Keycloak-generated claims aren't available. Claims such as
subandpreferred_usernamecame from Keycloak and have no native equivalent. - Errors appear on the Appsmith sign-in page, not on a Keycloak error page.