SAML single sign-on with any identity provider
This page is the specification, not a click path. Follow it and you will have a tested SAML 2.0 connection between your identity provider and CCTVplanner, at least one verified e-mail domain, and a sign-in policy you chose.
Before you start
- An Enterprise plan with an active subscription
- Owner or admin access to the CCTVplanner organization console at cctvplanner.io/organization
- Administrator access to your identity provider, with rights to create a SAML 2.0 application
- Rights to publish a DNS TXT record on every e-mail domain your people sign in with
- The owner's own work e-mail, at a verified domain, assigned to the SAML application. The test signs the owner in through the identity provider, so the owner runs it, not a separate test account
- A verified second factor on the owner account if you intend to make single sign-on required
- A free seat for each person who will sign in
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
Create the connection in the console
Sign in at cctvplanner.io/organization as the owner or an admin and open single sign-on.
Create a connection and give it a display name your colleagues will recognise.
A connection is in one of the four states in the table below. Only an active connection carries ordinary sign-ins. A new connection starts as a draft.
One e-mail domain belongs to one connection, so plan a separate connection for each identity provider you run.
DraftBeing filled in. Not yet usable for sign-in.TestingReady for the owner's test. Ordinary sign-ins are refused with SSO_CONNECTION_TESTING.ActiveSwitched on after a passed test. People sign in through it.DisabledSwitched off again. Sign-ins are refused with SSO_PROVIDER_DISABLED.The owner is the only role that can run the test and switch a connection on. An admin can create it and fill it in.
- 2
Claim and verify your e-mail domains
Claim each domain your people sign in with. The console lists your claimed and verified domains and shows the exact DNS TXT record to publish for each claim.
Publish the record as the console shows it, wait for DNS to propagate, then press verify.
Public e-mail domains are refused, and so is a domain another organisation has already verified.
An unverified claim expires if the record does not appear, and an organisation can hold only a few claims at once, so claim the domains you are ready to publish records for.
We re-check verified domains and drop a claim whose record has disappeared. A dropped domain is unpinned from its connection and the sign-in mode falls back to optional, so sign-in through that connection stops.
Record typeTXTHostExactly as the console shows it for that domainValueThe token the console generates for that domain, copied with the copy buttonA connection is bound to its verified domains. We check the e-mail in every assertion against them at sign-in and again at every token refresh, and an address outside them is refused with SSO_EMAIL_OUTSIDE_DOMAIN. Claim every domain and alias your people actually sign in with.
- 3
Copy the service provider values from the console
The console shows the service provider values with copy buttons. Copy them from there.
Do not type them from this page, and do not trust a value you found in a forum. The console is authoritative.
The labels in the table below are the shapes you will recognise. Your provider will call them something close.
Entity ID, Identifier, Audience URICopy from the consoleAssertion Consumer Service, Reply URL, Single sign-on URLCopy from the consoleNameID formatThe e-mail address format, urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddressThe entity ID and the address of our metadata document look alike. They are separate fields in the console. Copy each from its own field rather than reusing one for the other.
- 4
Create the SAML application in your identity provider
Create a SAML 2.0 application and enter the values you copied by hand: the entity ID into the field labelled Audience, Audience URI, Entity ID or SP Identifier, and the Assertion Consumer Service address into the field labelled ACS URL, Reply URL, Single sign-on URL, Recipient, Destination or Consumer URL.
Some providers ask for the same address twice, once as Recipient and once as Destination. Both are the Assertion Consumer Service address.
Leave the default relay state empty for a service provider initiated setup, which is how people sign in from cctvplanner.io.
If you want a tile in your identity provider that starts the sign-in, the redirect target it sends has to be on our allow list. Ask us to put your target on the list before you publish the tile.
Leave any logout field empty. Our metadata carries a Single Logout endpoint, but signing out of your identity provider is not a supported way to end a CCTVplanner session.
The field labels above are the common names across providers, not a click path in any one console. If your provider labels a field differently, match it by what it holds.
- 5
Set the NameID
Send the person's primary work e-mail, at a verified domain, in the e-mail address NameID format.
The NameID is our fallback. We read the e-mail attribute names first, in the order given in the attribute block at the end of this page, and use the NameID only when no e-mail attribute arrives.
So a NameID that is not an e-mail does not by itself break a connection that maps an e-mail attribute. A connection with neither is refused.
Pick a NameID value that is stable for the life of the account. A transient NameID changes at every sign-in and is not a usable identifier.
NameID formaturn:oasis:names:tc:SAML:1.1:nameid-format:emailAddressNameID valueThe person's primary work e-mail, at a verified domainAn e-mail address is mandatory. It can arrive as an attribute or as the NameID. Everything else is optional.
- 6
Map the attributes
Add the claims listed in the attribute block at the end of this page to the application.
For each claim we try the listed names in order and take the first one that carries a value, so a provider that sends the URI form and a provider that sends the short form both work without special handling.
Send the groups claim if you want it visible in the test result and the audit list. It is read but not used to set roles.
Send the mail attribute, not the user principal name, unless the two are identical. A user principal name whose suffix differs from the mail domain is the most common cause of a refused sign-in.
Map at least one short form name for first and last name alongside any urn:oid name, so an empty name field does not depend on which form the console's default mapping carries.
- 7
Hand us the identity provider metadata
A metadata URL is the preferred form. Paste the address of your application's federation metadata document into the console.
Prefer the URL because saving the connection re-reads it. Pasted metadata XML is a fixed document that has to be replaced by hand.
Use pasted XML when your metadata endpoint is not reachable from the public internet.
For certificate rotation, this is what each side does. A daily job here reads the identity provider's signing certificate expiry from the metadata and e-mails the organization's owner before it lapses. After your provider rotates the certificate, open the connection in the console and save it again, which re-reads the metadata URL, or paste the new document if the metadata was pasted as XML. We do not refresh the metadata on our own.
Editing an active connection's metadata puts it back into testing, and the sign-in mode returns to optional. The owner has to run the test again and switch the connection on before anyone can sign in, so do a rotation at a time you can finish it.
PreferredMetadata URL, re-read whenever the connection is savedFallbackMetadata XML, pasted once, replaced by handThe identity provider entity ID cannot be changed once the connection exists. Moving to a different identity provider means a new connection: unassign the domain from the old one first, then attach it to the new one.
- 8
Assign people and decide how accounts are created
Assign the application to the users or groups who should have access.
With just-in-time provisioning on, a first successful sign-in from a verified domain creates the account at the role you pick, if a seat is free.
With it off, people must exist in CCTVplanner first, added by hand or through provisioning, and an unknown person is refused with SSO_JIT_DISABLED.
If you want the directory to drive membership, create a provisioning token in the console and point your directory at the SCIM base address shown with it. The token is stored as a hash and is shown once, so copy it when it is created.
SCIM base addressShown in the console beside the tokenProvisioning tokenShown once, two live at a time, one year expiryJust-in-time provisioningOn or off, with the role new accounts get: editor or viewerSCIM covers Users: create, update, deactivate and delete all work. Groups are readable and always an empty list, on purpose, because roles are set in CCTVplanner.
- 9
Run the test as the owner
Work through the ordered list further down this page. It is the test, not a rehearsal of it.
The test runs from the owner's own session in the console and signs the owner in through the identity provider. Nobody else can sign in while the connection is in testing.
A connection can only be switched on after its test passes.
Run the test again after any metadata change, because that change puts the connection back into testing.
- 10
Switch the connection on and set the sign-in policy
Once the test passes, switch the connection on and choose the sign-in mode.
The console refuses to set the mode to required unless three things hold: the owner has a verified second factor, there is an active connection with at least one verified domain, and the owner has completed the test.
Required closes password sign-in for everyone at your verified domains, with one exception: the owner may keep a password if they have a verified second factor, so a broken identity provider cannot lock you out of your own tenant.
Switching to required takes effect at once. Members' password sessions are revoked and members are e-mailed.
Set the session cap and, if your policy asks for it, an idle timeout.
Sign-in modeOptional, or required for the verified domainsAccess token lifetimeFifteen minutes, fixedSession lengthTwenty-four hours by default, can be shortenedIdle timeoutOff unless you set oneMicrosoft Entra ID does not send SessionNotOnOrAfter. For Entra, our cap is the only session limit that applies.
Attributes and claims to send
E-mail, mandatory. Names tried in order: urn:oid:0.9.2342.19200300.100.1.3, http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress, mail, emailThe person's primary work e-mail, at a verified domain. Tried before the NameID. If you send no e-mail attribute at all, put the address in the NameID instead.First name, optional. Names tried in order: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname, urn:oid:2.5.4.42, givenName, firstName, first_nameThe directory's given name field.Last name, optional. Names tried in order: http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname, urn:oid:2.5.4.4, sn, surname, lastName, last_nameThe directory's surname field.Groups, optional, multi-valued. Names tried in order: http://schemas.microsoft.com/ws/2008/06/identity/claims/groups, groups, memberOfGroup names or identifiers. Read and recorded in the audit list, not used to set roles.NameID, fallback for the e-mailurn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress, carrying the same address as the e-mail attribute. Used only when no e-mail attribute arrives.Prove it works
- Assign the SAML application in your identity provider to the owner's own work account, at a verified domain.
- Open the connection in the CCTVplanner console as the owner and press the test button. The connection must still be in testing: the test is what qualifies it to be switched on.
- The console opens your identity provider in a new browser tab. Sign in there as the owner.
- That sign-in creates a twin account: a second, separate CCTVplanner account at the owner's own address, held by the identity provider and occupying no seat, because an SSO identity is never linked to an existing password account.
- The test tab confirms the outcome, signs that twin account out again and hands the result back to the original console tab, which restores the owner's own session.
- Read the result in the console: it shows the e-mail, first name, last name and groups it received from the assertion.
- Fix the attribute mapping in your identity provider and run the test again until the e-mail is present and correct.
- While the connection is still in testing, have a colleague at a verified domain attempt a sign-in and confirm it is refused with SSO_CONNECTION_TESTING. That is the state working, not a fault.
- Switch the connection on, then sign in from cctvplanner.io as a member at a verified domain.
- Check that the account landed at the role you expected and that the seat count moved as you expected.
- If you set the mode to required, confirm that a password sign-in at a verified domain is refused with SSO_REQUIRED, and that the owner can still sign in with a password plus the second factor.
When a sign-in is refused
| Symptom | Cause | Fix |
|---|---|---|
| SSO_PROVIDER_UNKNOWN at the sign-in screen | The address the person typed is at a domain that is not attached to any connection, or the claim was dropped because the DNS TXT record disappeared at a re-check. | Add and verify the domain on the connection. Check that the TXT record still resolves. Remember that one domain can belong to only one connection. |
| SSO_CONNECTION_TESTING | The connection is in testing. Either it has never been switched on, or a metadata change put it back into testing. Only the owner's test run passes through it. | Run the test, read the result, then switch the connection on and set the sign-in mode back to what you had. |
| SSO_PROVIDER_DISABLED | The connection is disabled. This is a different state from testing, with its own message. | Switch the connection on in the console. If it was disabled on purpose during an incident, sign in with a password while the mode is optional. |
| SSO_EMAIL_OUTSIDE_DOMAIN, for some people and not others | The assertion carried an address outside your verified domains. Usually a user principal name with a different suffix from the mail attribute, an acquired company's alias domain, or contractors on an external tenant. The same check runs again at every token refresh. | Map the mail attribute rather than the user principal name, or claim and verify the extra domain. There is no way to accept an unverified domain. |
| SSO_ACS_FAILED, and the assertion did look fine in the browser trace | The assertion carried no e-mail, under any of the attribute names we try, and no e-mail NameID. A provider that sends only a persistent or transient NameID hits this. | Add an e-mail claim using one of the names in the attribute block, or change the NameID format to the e-mail address format. |
| SSO_ACS_FAILED for everybody, starting on one particular day | The identity provider rotated its signing certificate and the metadata we hold is the old document. We do not re-read it on our own. | Open the connection in the console and save it again, which re-reads the metadata URL, or paste the new XML if that is how the metadata was supplied. Saving puts the connection back into testing and the mode back to optional, so run the test again and then restore the mode. |
| SSO_JIT_DISABLED or SSO_NO_SEATS after a successful sign-in at the identity provider | The assertion was accepted, but your organisation adds people manually, or there is no free seat, or no free editor seat for the role just-in-time provisioning would use. | Add the person in the console or through SCIM, or free a seat, or buy one. Lowering the just-in-time role to viewer also helps when editor seats are the constraint. |
| SSO_ACCOUNT_SUSPENDED for one person who signed in yesterday | The account was suspended, by a deactivation in your directory or a removal in the console. Sessions end and the sign-in is banned. | Reactivate the person in the directory or re-add them in the console. Nothing in the SAML configuration needs to change. |
| SSO_SUBSCRIPTION_INACTIVE for everybody at once | The organisation's subscription is no longer active. Single sign-on is refused for everyone, including sign-ins started from the identity provider. | Settle the subscription in billing. Sign-ins resume once it is active again. |
| SSO_REQUIRED for the owner, or SSO_OWNER_MFA_REQUIRED and SSO_OWNER_MFA_INCOMPLETE | The mode is required, so password sign-in is closed at your verified domains. The owner's exception applies only with a verified second factor, and only once that factor has been completed. | Enrol the owner in two-factor before you set the mode to required. Finish the second factor to continue. Otherwise sign in through the identity provider like everyone else. |
| People are signed out during the day, with SSO_SESSION_EXPIRED or SSO_SESSION_IDLE | SSO_SESSION_EXPIRED means the session reached the maximum length your organisation set. SSO_SESSION_IDLE means the idle timeout you set was reached. This is the policy working, not a fault. | For SSO_SESSION_EXPIRED, lengthen the session cap towards the twenty-four hour default if your policy allows it. For SSO_SESSION_IDLE, lengthen or clear the idle timeout, which is off unless set. Signing in again restores the session. |
| A person who used CCTVplanner before now has a second account at the same address, and their old projects are not in it. No error is shown: both sign-ins work. | An SSO identity is never linked to an existing password account, so the first sign-in through the identity provider creates a separate account. | Expect two accounts at that address and decide which one the person works in. Contact us about the work that sits on the old password account rather than waiting for a merge that does not happen on its own. |
Worth knowing
- We require signed assertions. Our metadata sets WantAssertionsSigned, so an identity provider that sends an unsigned assertion is refused. We do not sign our own authentication requests, so there is nothing for you to verify on that side and no certificate of ours to load for it.
- Our service provider metadata document carries a validUntil a couple of days ahead, and it moves forward every time the document is served. If your identity provider stores an uploaded copy and honours that field, it will treat the copy as expired. Point it at the metadata URL so it re-reads, or plan to upload a fresh document.
- Our metadata advertises a Single Logout endpoint, but do not build on it. Signing out of your identity provider is not a way to end a CCTVplanner session, and we do not support Single Logout as a control. Deprovisioning works the other way: a SCIM deactivation or a removal in the console suspends the account, ends the sessions and bans the sign-in, and an access token already in a browser dies within fifteen minutes.
- For a sign-in started at your identity provider, the redirect target has to be on our allow list. Ask us to add your target before you publish a tile.
- The console shows the owner the service provider values with copy buttons, the 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.
- What we do not have, stated plainly: no OpenID Connect, no IP allow list, no SIEM streaming, with a CSV export of the audit list instead, no group to role mapping, no SCIM Groups, no uptime SLA, no SOC 2, no ISO 27001 and no third-party penetration test report.
- SCIM detail worth knowing before you point a directory at us: Users only, PATCH supported, bulk and sort not supported, filtering with eq only on userName, externalId, id and emails[type eq "work"].value. The directory may only create people at verified domains. Deactivating suspends the account and ends the sessions, while the seat stays occupied and the projects stay with the organisation.
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.