Okta SAML single sign-on
Set up Okta as the SAML 2.0 identity provider for your CCTVplanner Enterprise organization. When you finish, people at your verified domains sign in through Okta, and you know what to do on the day Okta rotates its signing certificate.
Before you start
- An Enterprise plan on CCTVplanner with an active subscription. While the subscription is inactive, single sign-on is refused with SSO_SUBSCRIPTION_INACTIVE.
- At least one domain verified in the CCTVplanner organization console. Verification is a DNS TXT record at _cctvplanner-challenge.<your-domain> with the value cctvplanner-verify=<token the console generates>. It is re-checked weekly, and the claim is dropped if the record disappears.
- Super administrator or application administrator rights in Okta.
- A test account in Okta whose primary e-mail is at one of the verified domains.
- Two-factor enabled on the CCTVplanner owner account, if the owner wants to keep a password after sign-in is set to required.
- The CCTVplanner organization console open in a second tab, at cctvplanner.io/organization.
Values to paste
Copy these from your organization console rather than from this page. The console is the authority; the shapes below are only so you recognise the right field.
https://auth.cctvplanner.io/auth/v1/sso/saml/metadatahttps://auth.cctvplanner.io/auth/v1/sso/saml/acshttps://auth.cctvplanner.io/auth/v1/sso/saml/metadata?download=trueurn:oasis:names:tc:SAML:1.1:nameid-format:emailAddressSteps
- 1
Open the connection in the CCTVplanner console
Go to cctvplanner.io/organization and open the single sign-on section.
The console shows the service provider values with copy buttons next to them. It is the authoritative source, so copy from it rather than typing the values below.
The values below show you the shape, so you can tell at a glance that you pasted the right one into the right Okta field.
The same section lists your claimed and verified domains with the DNS TXT record to publish, the connection with its display name, provider template, entity id and certificate expiry, the sign-in policy, the provisioning tokens, and an audit list with an export button.
Leave this tab open. You will come back to it several times.
Audience URI (SP Entity ID)https://auth.cctvplanner.io/auth/v1/sso/saml/metadataSingle sign-on URL (ACS)https://auth.cctvplanner.io/auth/v1/sso/saml/acsSP metadata for uploadhttps://auth.cctvplanner.io/auth/v1/sso/saml/metadata?download=trueNameID formaturn:oasis:names:tc:SAML:1.1:nameid-format:emailAddressThe two long URLs differ only at the end, acs against metadata. Pasting the metadata URL into Single sign-on URL sends the assertion to the wrong endpoint. The sign-in fails before it reaches us, so there is no error for it in the console.
- 2
Create the app integration in Okta
In the Okta Admin Console, go to Applications, then Applications, then select Create App Integration.
Select Classic experience.
Select SAML 2.0 as the sign-in method and click Next.
We publish no integration in the Okta Integration Network. Build the app integration yourself rather than looking for us in the catalogue.
- 3
Name the integration
On the General Settings step, set the App name to something your users will recognise on their Okta dashboard, for example CCTVplanner.
Upload a logo if you want one on the dashboard tile.
App visibility controls whether the tile appears for assigned users. Leave the tile visible if you want people to start sign-in from Okta.
Click Next.
App visibility controls the dashboard shortcut only. It is not a way to switch off sign-in that starts at Okta.
- 4
Fill in the SAML settings
You are now on the Configure SAML step.
Paste the assertion consumer service URL into Single sign-on URL, and the entity identifier into Audience URI (SP Entity ID).
Leave Use this for Recipient URL and Destination URL selected.
Leave Default RelayState empty.
Single sign-on URLhttps://auth.cctvplanner.io/auth/v1/sso/saml/acsUse this for Recipient URL and Destination URLselectedAudience URI (SP Entity ID)https://auth.cctvplanner.io/auth/v1/sso/saml/metadataDefault RelayStateleave emptyA redirect target has to be on our allow list. That is the whole of what we can tell you about RelayState here, so leave the field empty.
- 5
Set the Name ID format and application username
Set Name ID format to EmailAddress and Application username to Email. Okta's own guide gives that pair as its example.
Application username decides what goes into the NameID. We try the e-mail attribute names first, in the documented order, and read the NameID only when no e-mail attribute arrives, so this setting keeps the fallback correct rather than carrying the address on its own.
Leave Update application username on at Create and update, so a later e-mail change in Okta reaches us.
Name ID formatEmailAddressApplication usernameEmailUpdate application username onCreate and updateThe Okta default is Okta username, which in many tenants is an address at @yourorg.okta.com and therefore outside your verified domains. With the email attribute statement from the next step in place, that default is survivable, but there is no reason to keep it.
- 6
Add the attribute statements
Open the Attribute Statements section on the same step.
Add the three rows in the table below. Leave Name format at Unspecified for all three, or set URI Reference if your internal standard requires it. We match on the attribute name, and both formats work.
We also accept the standard urn:oid:0.9.2342.19200300.100.1.3 and schemas.xmlsoap.org names, as well as mail, so an existing corporate attribute profile usually needs no change. Those names are tried before the NameID fallback.
The e-mail is mandatory. First name and last name are optional, but without them people show up in the member list by e-mail address only.
emailuser.emailfirstNameuser.firstNamelastNameuser.lastNameFill in the Value cell on every row you add before you continue.
- 7
Add the group attribute statement, if you want groups in the assertion
Open Group Attribute Statements and add one row.
Set Name to groups, and set the filter so that it matches every group the user belongs to. The regex filter with a single dot followed by an asterisk does that.
We read the groups attribute. We do not map groups to roles.
Skip this row if your directory has large group membership. A user in hundreds of groups produces a large assertion for no current benefit.
Roles are set in CCTVplanner, by hand or through the role that just-in-time provisioning assigns.
- 8
Finish the wizard
Click Next to reach the Feedback step.
Select I'm an Okta customer adding an internal app, then click Finish.
The other option starts a submission to the Okta Integration Network, which you do not want.
- 9
Copy the identity provider metadata URL back to CCTVplanner
Open the Sign On tab of the new app integration.
Copy the Metadata URL from that tab. Some tenants show it behind a More details link, which also lets you copy the individual URLs and the certificate.
Paste that URL into the metadata field on the connection in the CCTVplanner organization console and save.
The console accepts either a metadata URL or pasted metadata XML. Prefer the URL: re-saving the connection re-reads it, while a pasted document has to be replaced by hand every time Okta changes it.
Okta Metadata URLhttps://<your-org>.okta.com/app/<app-instance-id>/sso/saml/metadataThe metadata URL is per application. Metadata from a different app carries a different issuer, and the connection will not recognise it.
- 10
Assign people and groups
Open the Assignments tab on the app integration.
Click Assign, then Assign to People or Assign to Groups.
Assign your test account first, and nobody else, until the connection test passes.
A person who is not assigned never reaches us. Okta stops them with its own error, so the CCTVplanner sign-in screen shows nothing at all.
If just-in-time provisioning is off in CCTVplanner, assignment in Okta is not enough on its own. The person must also exist in CCTVplanner, added by hand or through SCIM, or they get SSO_JIT_DISABLED.
- 11
Test the connection, then switch it on and set the sign-in policy
Run the connection test from the console, in the order set out in the proof list below. The connection can only be switched on after the test passes.
Switch the connection on with the sign-in policy set to optional, and sign in once from the normal CCTVplanner sign-in screen with a real account at a verified domain.
Set sign-in to required only after that succeeds. Required closes password sign-in for everyone at your verified domains, and they get SSO_REQUIRED on the password form.
The owner can keep a password after that switch only with a verified second factor, and the second factor has to be completed at sign-in. That is the break-glass path if Okta is unreachable.
- 12
Plan for the signing certificate rotation
We do not re-read the identity provider metadata on our own.
A daily job reads the identity provider's signing certificate expiry from the metadata and e-mails the organization's owner before it lapses. The expiry is also shown on the connection in the console.
After Okta rotates the certificate, open the connection in the console and save it again, which re-reads the metadata URL. If the metadata was pasted as XML, paste the new document.
Saving new metadata on an active connection puts it back into testing, and ordinary sign-ins through it are then refused with SSO_CONNECTION_TESTING. Run the test again and switch the connection on.
Plan the re-save for a window you can watch, because of the testing state it puts the connection into.
Attribute statements to send
emailuser.emailfirstNameuser.firstNamelastNameuser.lastNamegroups (Group Attribute Statements, optional)a filter that matches every group the user belongs toProve it works
- Assign your test account to the Okta app integration, and nobody else yet. Its primary e-mail has to be at a verified domain.
- Leave the connection in the testing state. While it is testing, ordinary sign-ins through it are refused with SSO_CONNECTION_TESTING. That is a different state from disabled, which refuses them with SSO_PROVIDER_DISABLED.
- In the CCTVplanner organization console, open the connection and click the test button. The owner runs this test from the console, not from the sign-in screen.
- The console opens Okta in a new browser tab. Sign in there, including any multifactor prompt.
- That sign-in creates a twin account: a second, separate CCTVplanner account at your own address, held by Okta, occupying no seat, because an SSO identity is never linked to an existing password account.
- The test tab confirms the result, signs the twin account out again and hands the outcome back to the original console tab, which restores your own session.
- Read the outcome in the console tab, not in the tab that opened.
- If it failed, correct the Okta settings and run the test again. Repeat until it passes.
- Switch the connection on, with the sign-in policy set to optional.
- Sign in from the normal CCTVplanner sign-in screen with a real account at a verified domain.
- Set sign-in to required only after that sign-in succeeds.
When sign-in fails
| Symptom | Cause | Fix |
|---|---|---|
| SSO_CONNECTION_TESTING | The connection is in the testing state. A new connection starts there, and saving new metadata on an active connection puts it back there. | Run the test from the console and switch the connection on once it passes. |
| SSO_PROVIDER_DISABLED | The connection is disabled. This is not the same state as testing, and not the same message. | Switch the connection on in the console. If it has never passed the test, run the test first. |
| SSO_PROVIDER_UNKNOWN | The issuer in the assertion does not match any connection. Usually the metadata came from a different Okta app, or the connection was deleted and rebuilt after Okta was configured. | Copy the Metadata URL from the Sign On tab of this specific app integration and save it on the connection again. |
| SSO_ACS_FAILED, with the message that no e-mail was present | No e-mail reached us: the email attribute statement is missing and the NameID is not an address either. | Add the email attribute statement mapped to user.email, and set Name ID format to EmailAddress with Application username set to Email. |
| SSO_EMAIL_OUTSIDE_DOMAIN | The assertion carried an address at a domain you have not verified. A connection is bound to its verified domains, and the check runs at sign-in and again at every token refresh. | Verify the extra domain in the console, or change that person's primary e-mail in Okta so that the address the assertion carries is at a verified domain. |
| SSO_JIT_DISABLED | Just-in-time provisioning is off, so an assignment in Okta does not create the CCTVplanner account. | Turn just-in-time provisioning on and pick the role new people get, or add the person first, by hand or through SCIM. |
| SSO_NO_SEATS | Every seat is taken, or every editor seat is taken while just-in-time provisioning is set to create editors. | Free a seat, buy seats, or set the just-in-time role to one whose seats are still free. |
| SSO_ACCOUNT_SUSPENDED | The person was deactivated in the directory through SCIM. That suspends the account, ends the sessions and bans the sign-in. The seat stays occupied and the projects stay with the organization. | Reactivate them in the directory, or remove them in CCTVplanner if you want the seat back. |
| SSO_REQUIRED on the password form, for someone who has always used a password | Sign-in is set to required, so password sign-in is closed for everyone at the verified domains. | Send them through the single sign-on button. If this locked out an account that has no Okta identity, set sign-in back to optional while you sort it out. |
| SSO_OWNER_MFA_REQUIRED, or SSO_OWNER_MFA_INCOMPLETE | The owner is keeping a password while sign-in is required. That is allowed only with a verified second factor, and the second factor has to be completed. | Enrol a factor on the owner account, then finish the two-factor step at sign-in. This is the break-glass path if Okta is unreachable. |
| SSO_SESSION_EXPIRED partway through a working day | The session reached the maximum length your organization set. The default is twenty-four hours and the console can shorten it. | Sign in again, or raise the session maximum in the sign-in policy if the shorter limit was a mistake. |
| SSO_SESSION_IDLE | The session sat idle past the idle limit in your sign-in policy. | Sign in again, or change the idle limit in the console. |
| SSO_SUBSCRIPTION_INACTIVE | The Enterprise subscription is not active, for example after a failed card payment. | Settle billing. Single sign-on resumes once the subscription is active again. |
| Okta says the user is not assigned to the application, and CCTVplanner shows nothing | The assertion never left Okta, so we have no error to show. | Assign the person or their group on the Assignments tab of the app integration. |
| Sign-in fails at Okta with no CCTVplanner error at all, on a connection that looks configured | The metadata URL was pasted into Single sign-on URL, so the assertion goes to the metadata endpoint and never reaches our assertion consumer service. | Set Single sign-on URL to the address ending in acs, and keep the metadata address for the Audience URI field only. |
Worth knowing
- Sessions: an access token lasts fifteen minutes and refreshes in the background, and the verified-domain check runs again at every refresh. A session ends after twenty-four hours by default, and the sign-in policy in the console can shorten that maximum and set the idle limit.
- An Okta sign-in never attaches to an existing CCTVplanner password account at the same address. The person gets a separate account held by Okta, and whatever is in the old password account stays in the old password account.
- Sign-in started from the Okta dashboard tile reaches the same assertion consumer service endpoint. The redirect target has to be on our allow list.
- SCIM provisioning is a separate setup. In Okta: General tab, App Settings, Edit, Provisioning: SCIM, Save, then the Provisioning tab, Settings, Integration, with the bearer token under HTTP Header authentication. In CCTVplanner, the console shows the base URL, of the shape https://<project>.supabase.co/functions/v1/scim/v2, and the bearer token once. Tokens are stored as a SHA-256 hash, two can be live at a time, and a token expires after one year.
- What SCIM does and does not do: the directory can create people only at your verified domains. Deactivating a person suspends the account, ends the sessions and bans the sign-in, while the seat stays occupied and the projects stay with the organization. Filtering is eq only, on userName, externalId, id and emails[type eq "work"].value. PATCH is supported; bulk and sort are not. Groups are readable and always an empty list, on purpose, because roles are set in CCTVplanner.
- We do not support OpenID Connect, IP allow lists, SIEM streaming, group to role mapping or SCIM Groups, and we publish no uptime SLA, SOC 2, ISO 27001 or third-party penetration test report. The audit list in the console has an export button.
Stuck on something this page does not cover? Write to [email protected] and quote the error text on screen. Enterprise is the plan that carries single sign-on.
Screens and field names belong to the identity provider and change without telling us. Where this page and their own documentation disagree, theirs is right, and we would like to hear about it.