Keyway SSO for Craft CMS › Guides

Okta SSO for Craft CMS: SAML login for the control panel

What to put in Okta's app integration, what to paste back into Craft, and which of Okta's defaults will quietly break the second login if you leave them alone. Okta's admin console changes wording from time to time — where a name below does not match what you see, look for the setting that does the same job.

Verification status, plainly. This guide covers SAML 2.0 with Okta, and that path was run end to end against a live Okta tenant on 17 September 2026 (Integrator Free Plan, fresh Craft 5.11 install on default settings): the first sign-in created the account just in time with the mapped group, and the second one updated it and reached the control panel. Single Logout will not work with Okta — by Okta's own documentation (read 17 September 2026) Okta will not send a logout request to the application after an ordinary Okta sign-out; that half was not exercised on the live tenant. With Okta as your only provider, plan on single sign-on and not single logout. OpenID Connect with Okta has not been checked — the OIDC side of the plugin is written to the specification and exercised against a different provider, so if you go that way, treat it as unverified and test it carefully before anyone depends on it.

What you will need

Step 1 — Turn the plugin on and copy this site's values

  1. Open Settings → Plugins → Keyway SSO and set Protocol to SAML 2.0.
  2. Optionally change Login button label (default: Sign in with SSO, at most 120 characters).
  3. Note down This site's URL — the copy field above SP entity ID, this site's base URL without a trailing slash — and ACS URL this site answers on. Both are readable before you save anything.

You may type those two values into SP entity ID and ACS URL now, but do not expect the save to go through yet and do not expect the metadata file: the save is rejected until Okta's three values are in too, and a rejected save stores nothing. Create the application first.

Step 2 — Create the application in Okta

Create a new app integration of the SAML 2.0 kind, give it a name, then work through its SAML settings:

Okta settingValue
Single sign-on URLthe ACS URL this site answers on value from Step 1
Use this for Recipient URL and Destination URLleave it checked
Audience URI (SP Entity ID)exactly what you put in SP entity ID
Default RelayStateleave empty
Name ID formatEmailAddress — and not Unspecified or Transient
Application usernameEmail

The Recipient and Destination checkbox is load-bearing. The plugin compares the response's Destination attribute (when present) and the assertion's SubjectConfirmationData/@Recipient against the configured ACS URL, exactly, with no substring or prefix leniency and no way to relax it. If those three addresses are not the same string, the login fails with destination_mismatch or confirmation_invalid.

The Name ID format has to be a stable one. Accounts this plugin creates are recognised on later logins by account, issuer and Name ID. Transient is a new value on every login by definition, which means the second login of every user is refused with linking_disabled. Use EmailAddress or Persistent. The plugin does not read the format attribute, so there is no error message pointing at this.

Attribute statements. Add three, with these names exactly — the plugin matches on the attribute's Name: emailuser.email, firstNameuser.firstName, lastNameuser.lastName.

Group attribute statement. For group mapping, add one named groups with the filter Matches regex and the expression .*. That sends every Okta group the user belongs to; the narrowing happens in Craft, in the Groups table.

Signing. The assertion must be signed, with RSA-SHA256. The plugin requires a signed assertion unconditionally. Leave assertion encryption off unless you have a reason for it — there is no field for an SP certificate here, so a certificate matching your private key would have to reach Okta by another route.

Assign somebody, then collect three values from the app's sign-on settings — usually behind the link with the SAML setup instructions:

Craft fieldOkta value
IdP SSO URLIdentity Provider Single Sign-On URL
IdP entity IDIdentity Provider Issuer
IdP signing certificatethe X.509 Certificate, in PEM form (the -----BEGIN CERTIFICATE----- block)

Step 3 — Paste Okta's values back and save

In the SAML 2.0 section: IdP entity ID takes Okta's Identity Provider Issuer (compared byte for byte against the assertion issuer), IdP signing certificate the full certificate (a fingerprint is rejected), IdP SSO URL Okta's sign-on URL — required, because without it there is nowhere to send the browser. SP entity ID and ACS URL repeat what you gave Okta. Clock skew (seconds) defaults to 60 and caps at 120.

Leave SP private key empty unless you turned on encrypted assertions, and leave the logout fields empty too on an Okta installation — see the limits below for why.

Save and read the screen. Under ACS URL the plugin comments on what you typed: no message means it is identical to the address this site answers on; anything else describes exactly how it differs. A banner saying the connection "is not usable yet" means the login screen still offers password login only.

Step 4 — Attributes and groups

An empty Attributes table does not mean "map nothing" — it means "use the shipped defaults", and those defaults are exactly what Step 2 configures in Okta: emailemail (required), firstNamefirstName, lastNamelastName. So with the attribute statements above you can leave the table alone.

Groups. Source attributes defaults to groups. Each row of the Groups table maps an Okta group to a Craft group handle with Exact, Prefix or Suffix matching; there are no regular expressions, on purpose. Prefix and suffix patterns must be at least two characters, and an empty pattern is refused — it would match everything Okta sends. Sync mode is Append by default; Replace makes Okta the only source of truth, which also means a login mapping to nothing empties the account's group list. Allow admin escalation is off by default and worth leaving off: with it on, whoever administers your Okta groups can grant Craft admin. Detail: group mapping.

Provisioning. Create accounts on first login and Update accounts on every login are on by default; Match existing accounts by is E-mail. Link to existing Craft accounts is off, so a Craft account that already exists with the same address is not adopted until you say so — and Linking may include admin accounts is a separate switch, because "let the team sign in with SSO" and "let Okta hand out the owner's account" are not the same sentence.

Step 5 — Keep a way back in, then test

Keep at least one Craft admin whose password you know, and confirm that password still works before you rely on it. Admins may still use a password is on by default, and if your settings would leave nobody able to reach the control panel when Okta is unreachable, the plugin turns it back on as you save and says so. It checks the settings, not the accounts: an Emergency accounts entry only counts if it names an existing account with a local Craft password — and accounts this plugin created from Okta logins have none. Full detail: password login and lockout.

Then open the Craft login screen in a private window and sign in as the user you assigned. The SSO button appears only when the configuration is usable. Afterwards open Open sign-in diagnostics — after a success as well as after a failure. If the panel reports that the diagnostics store is unavailable, the migration has not run: php craft up.

A login has five minutes between pressing the SSO button and the assertion coming back; after that the single-use login state has expired. That is a stale browser tab, not a session length.

Known limits with Okta

This list covers what is specific to Okta. The limits that apply to every provider are on the troubleshooting page; read them once before you go live.

Keyway SSO for Craft CMS 5

SAML 2.0 and OpenID Connect sign-in for the Craft control panel: attribute and group mapping, just-in-time accounts, an admin password fallback with a guard that switches admin password login back on, with a warning, if your settings would otherwise leave nobody able to sign in, and a diagnostics screen that tells you why a login was refused. The plugin is in final testing and is on its way to the Craft Plugin Store.

Read the deployment documentation