Single sign-on

    Single sign-on security

    What our SAML single sign-on enforces, what it does not, and the answers we give to a vendor security questionnaire. When you finish you will know which of your controls we carry, which stay with your identity provider, and which we do not offer at all.

    Before you start

    • Enterprise plan, single sign-on and SCIM are not part of Studio
    • A SAML 2.0 identity provider you administer
    • A metadata URL from that provider, or its metadata XML document
    • Control of DNS for every domain you will verify
    • Owner access to the organisation console at cctvplanner.io/organization
    • Your questionnaire open, so you can match our answers to its sections
    1. What single sign-on enforces, and what it does not

      Single sign-on decides who may open a session, and nothing else.

      With the mode set to required, password sign-in stops working for everyone at your verified domains, and an attempt is refused with SSO_REQUIRED.

      It does not decide what a signed-in person may do: roles are set in CCTVplanner, and group claims are read from the assertion but are not mapped to roles.

      It does not restrict where a person signs in from either, because there is no IP allow list.

      Sign-in mode is set per organisation, so one tenant being required says nothing about another.

    2. What the organisation console shows the owner

      Everything a reviewer usually asks to see sits on one screen, at cctvplanner.io/organization.

      The service provider values, each with a copy button. Take them from there and not from any document, including this one.

      The domains you have claimed and the ones we have verified, with the DNS TXT record to publish.

      The connection, with its display name, the provider template it was built from, its entity id, and the expiry date of your identity provider's signing certificate.

      The sign-in policy, the provisioning tokens, and an audit list with an export button.

      The service provider entity id and assertion consumer service URL are not printed on this page on purpose. Read them from the console, or ask us and we will send them in writing.

    3. Domain verification comes first

      A connection is bound to verified domains. Until a domain is verified, no connection can carry it.

      You publish a DNS TXT record, and we re-check verified domains weekly and drop the claim if the record disappears.

      An assertion carrying an address outside your verified domains is refused with SSO_EMAIL_OUTSIDE_DOMAIN, at sign-in and again at every token refresh. A misbehaving identity provider can neither mint an account at a domain that is not yours nor keep one alive.

      SCIM is held to the same rule: the directory may only create people at verified domains.

      TXT record name_cctvplanner-challenge.<your-domain>
      TXT record valuecctvplanner-verify=<token the console generates>

      Copy the token from the organisation console. Do not retype a value from any document, including this one.

    4. Metadata, and what happens when your certificate rotates

      The console takes either a metadata URL or a pasted metadata XML document for a connection.

      Prefer the URL. Re-saving the connection re-reads it, whereas a pasted document has to be replaced by hand.

      We do not promise that the metadata is refreshed on its own. Nothing on our side establishes that, so do not plan your rotation as if it were.

      What we do: a daily job reads the signing certificate's expiry out of the metadata and e-mails the organisation's owner before it lapses.

      What you do: after your provider 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.

      Metadata URLRe-read every time the connection is saved
      Pasted metadata XMLReplaced by hand, never refreshed for you
      Expiry warningA daily job reads the certificate expiry and e-mails the organisation's owner before it lapses
      After a rotationSave the connection again, or paste the new document

      In Microsoft Entra ID the federation metadata URL sits in the SAML Certificates section of the application's single sign-on page. In Okta it is the identity provider metadata URL published on the application.

    5. A connection has four states, and two of them refuse sign-ins

      A connection is draft, testing, active or disabled.

      While it is testing, ordinary sign-ins through it are refused with SSO_CONNECTION_TESTING.

      When it is disabled they are refused with SSO_PROVIDER_DISABLED. Those are two different states with two different messages, and your service desk should not read them as the same outage.

      Editing an active connection's metadata puts it back into testing. Treat a metadata edit as a change window, because until the test passes again your people cannot sign in through that connection.

      draftBeing built, not reachable
      testingOnly the test flow passes, everyone else gets SSO_CONNECTION_TESTING
      activeOpen to your verified domains
      disabledTurned off, sign-ins refused with SSO_PROVIDER_DISABLED
    6. The test that has to pass before a connection goes live

      The owner clicks the test button on the connection in the organisation console. The console opens your identity provider in a new browser tab, and the owner signs in there.

      That sign-in creates a twin account: a second, separate CCTVplanner account at the owner's own address, held by the identity provider rather than by a password. It occupies no seat, because Supabase never links an SSO identity to an existing password account.

      The test tab confirms the result, signs that twin account out again, and hands the outcome back to the original console tab, which restores the owner's own session.

      Only after the test passes can the connection be switched on. There is no way to open a connection to your people without it.

      Run the test on your own account before you tell anyone else the connection exists, and run it again after any metadata edit, because that edit has already put the connection back into testing.

    7. Tokens, sessions and the twenty-four hour cap

      Access tokens live fifteen minutes.

      A session ends after twenty-four hours by default, whatever your identity provider says in the assertion, and you can shorten that for your organisation.

      Microsoft Entra ID does not send SessionNotOnOrAfter, so for Entra customers the cap is the only session limit that applies. Microsoft's own sample token carries an AuthnStatement with AuthnInstant alone.

      Access token lifetimefifteen minutes
      Maximum session lengthtwenty-four hours by default, shortenable per organisation
      Refusal when a session runs outSSO_SESSION_EXPIRED, or SSO_SESSION_IDLE if the session sat idle
    8. Deprovisioning, and why fifteen minutes is the ceiling

      Deactivating someone in your directory suspends the account, ends the sessions and bans the login, and that part happens on the SCIM call itself. A later attempt is refused with SSO_ACCOUNT_SUSPENDED.

      An access token already sitting in a browser keeps working until it expires.

      Fifteen minutes is therefore the ceiling, and zero is not.

      The seat stays occupied and the projects stay with your organisation, so nothing disappears when somebody changes team.

    9. What a refused sign-in shows

      A refused sign-in carries one of a fixed set of error classes, each tied to a setting you control. Your service desk can act on the class without calling us.

      SSO_PROVIDER_UNKNOWNNo connection is bound to that address's domain
      SSO_PROVIDER_DISABLEDThe connection is disabled
      SSO_CONNECTION_TESTINGThe connection is in testing and is not open to ordinary sign-ins yet
      SSO_EMAIL_OUTSIDE_DOMAINThe assertion carried an address outside your verified domains, raised at sign-in and again at every token refresh
      SSO_ACCOUNT_SUSPENDEDThe account is suspended, which is what a directory deactivation does
      SSO_SESSION_EXPIREDThe session passed its maximum length
      SSO_SESSION_IDLEThe session sat idle too long
      SSO_REQUIREDPassword sign-in was attempted at a domain where the mode is set to required
      SSO_OWNER_MFA_REQUIREDThe owner is keeping a password under a required policy without a verified second factor
      SSO_OWNER_MFA_INCOMPLETEThe owner began enrolling a second factor and did not finish it
      SSO_SUBSCRIPTION_INACTIVEThe organisation's subscription is not active
      SSO_JIT_DISABLEDThe person does not exist in CCTVplanner and just-in-time provisioning is off
      SSO_NO_SEATSJust-in-time provisioning would have created the account and no seat was free
      SSO_ACS_FAILEDThe assertion did not complete at our assertion consumer service

      The class is the stable part. The sentence a person reads is translated and can change, so map your runbook to the class.

    10. The audit log, what it records and who can change it

      Every sign-in policy decision, domain claim and verification, connection change, provisioning write, session reset, audit export and account move writes a row. Each row carries who did it, who it was done to, the source IP address, the browser, and whether the attempt succeeded or was refused.

      The owner exports the whole log as CSV from the console at any time. The export is itself logged.

      The table is append-only. Rows can be inserted and read; the permission to update, delete or truncate is revoked from the application role and from the service role alike, so neither an administrator at your company nor our own server code can quietly rewrite history through the app.

      Rows are kept for a year by default. An organization can set anything from ninety days to ten years, and a scheduled job enforces it rather than a promise to tidy up.

      We hold the database the log lives in, so the integrity guarantee above is a guarantee against a customer administrator and against ordinary mistakes, not against us. If your controls need an independently held copy, export on a schedule into storage you control, and raise it during the purchase, because we do not provide one.

    11. No SIEM streaming, no IP allow list

      There is no event stream to your SIEM. CSV export is the only way out today, and a webhook for it is not built.

      There is no IP allow list.

      Plan on a scheduled pull of the CSV if you need authentication events in your own store, and enforce network conditions at your identity provider, which sees every sign-in before we do.

    12. Support access, and the five things only we can do

      There is no impersonation feature. Nobody at CCTVplanner can sign in as one of your users, and we are not adding one for support convenience.

      Five situations need us: an owner locked out of an organization that requires single sign-on, an identity provider outage, a platform-wide failure that needs the kill switch, a change of owner after somebody leaves the company, and a directory deleting people the customer did not expect.

      Each of those requires two independent checks that the person asking is who they say they are, at least one of them from a short list that a stranger cannot satisfy, and each writes a row into your own audit log naming what was done and which checks were used.

      The procedure is written down rather than improvised, and we will send it to you on request.

      We will not change an owner e-mail address on request, remove an owner two-factor factor, or turn a required policy off without telling the organization.

    13. IdP-initiated sign-in cannot be refused

      We accept IdP-initiated sign-in and it cannot be switched off, which is a property of the platform rather than a choice we made.

      Two things limit it. The redirect target must be on our allow list, and a browser that receives a session it did not ask for shows a confirmation screen naming the account before anything is used.

      A per-organisation switch to refuse unsolicited assertions is not built.

      Restrict who can launch the tile at your identity provider, which is the control that actually bites.

    14. Secrets, SCIM tokens and the owner two-factor exception

      SCIM bearer tokens are shown once at creation and stored as a SHA-256 hash. Two may live at once so you can rotate without a gap, and each expires after a year.

      TLS protects everything in transit. We do not run our own key management and we do not offer customer-managed keys.

      Under a required policy the owner may keep a password, but only with a verified two-factor factor. Without one the sign-in is refused with SSO_OWNER_MFA_REQUIRED, and part-way through enrolment with SSO_OWNER_MFA_INCOMPLETE.

      That exception exists so a broken identity provider cannot lock the buyer out of their own tenant, and removing it would mean we hold the only key to your account.

    15. Assurance we do not have

      No uptime SLA, no published service level objective and no credits.

      No SOC 2, no ISO 27001 and no third-party penetration test report.

      If your process cannot proceed without one of those, tell us during the purchase and not after.

      We will answer a questionnaire in writing, send the architecture and the subprocessor list, and let you talk to the person who wrote the code.

    What we read out of the assertion

    E-mail, mandatoryTried in this order: urn:oid:0.9.2342.19200300.100.1.3, then http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress, then mail, then email. The NameID is the fallback and is used only when none of those arrives, so a wrong NameID on its own does not break a connection that maps an e-mail attribute.
    First name, optionalhttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname, then urn:oid:2.5.4.42, then givenName, firstName, first_name
    Last name, optionalhttp://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname, then urn:oid:2.5.4.4, then sn, surname, lastName, last_name
    Groups, optional, read but not usedhttp://schemas.microsoft.com/ws/2008/06/identity/claims/groups, then groups, memberOf, multi-valued, no role mapping
    NameID formaturn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
    Anything else in the assertionnot read

    What a security reviewer asks

    The questionThe short answerIf you need more
    How long do you keep the audit log, and can it be altered?A year by default, settable from ninety days to ten years. Append-only: update and delete are revoked from both the application role and the service role.Export to your own storage on a schedule if you need a copy you hold. We do not offer an independently held one.
    Can your staff access our tenant or sign in as our users?There is no impersonation. Five break-glass operations exist, each needs two independent identity checks, and each leaves a row in your audit log.Ask for the break-glass procedure and we will send it before you sign.
    Can we make single sign-on mandatory for everyone, with no exceptions?Required mode stops password sign-in for everyone at your verified domains, with one exception: the owner may keep a password only with a verified two-factor factor.We will describe the policy and the point at which it is enforced, and write the exception into the contract so it is not a surprise at audit time.
    Do you support OpenID Connect?No. SAML 2.0 is the only federation protocol we support.If OIDC is a hard requirement, say so before you buy. There is no date we are willing to give you.
    How quickly is a leaver cut off?The account is suspended, the sessions are ended and the login is banned on the SCIM call. An access token already issued lives at most fifteen minutes.Ask us to walk the SCIM deactivation path with you against a test account on your own tenant.
    Can we restrict sign-in to our office or VPN ranges?No. There is no IP allow list.Apply the condition at your identity provider, which evaluates every sign-in before the assertion reaches us.
    Can you stream authentication events to our SIEM?No. CSV export from the organisation console is the only way out today.We will document the CSV columns so you can schedule a pull into your own store. A webhook is not built.
    How long do you keep the audit log, and can a row ever be changed?This page does not answer either question, because we will not publish a retention number or an immutability claim we have not checked against the schema.Ask during the purchase and we will answer both in writing. If you need a copy held outside our database, say so then, because we do not provide one.
    Can your staff sign in as one of our users?Support access is not documented on this page, and we would rather say so than publish a control statement you would hold us to.Ask during the purchase. We will answer in writing, against the code, and put whatever we answer into the contract.
    What happens when our identity provider rotates its signing certificate?Nothing automatic. A daily job e-mails your owner before the certificate lapses, and the owner then saves the connection again so the metadata URL is re-read, or pastes the new XML.Give us an owner address that a rota reads, not a person who may be on leave the week the certificate turns over.
    Can we refuse IdP-initiated sign-in?No, and that is a platform property rather than a setting we hid. The redirect target must be on our allow list, and an unsolicited session shows a confirmation screen naming the account before it is used.Restrict who can launch the tile at your identity provider. Tell us if a switch on our side would unblock your review, so it is weighed against other work.
    Are you SOC 2 or ISO 27001 certified, and can you send a penetration test report?None of the three, and there is no uptime SLA either.We will complete your questionnaire in writing, name our subprocessors, describe the architecture and put a security appendix in the contract. If a certificate is mandatory, stop here rather than after the invoice.
    What exactly do our people see when a policy blocks them?One of fourteen error classes, each tied to a setting you control. They are listed with their meanings in the refusal table above.We will map each class to the console setting that produces it and to the wording the user sees, so your service desk can answer without calling us.
    Who can turn a connection on, and can it be switched on untested?No. The owner runs the test from the console, and only a passing test lets the connection be switched on. Editing an active connection's metadata puts it back into testing.Schedule metadata edits as change windows, because between the edit and the passing re-test your people are refused with SSO_CONNECTION_TESTING.

    Worth knowing

    • Subprocessors touched by single sign-on: Supabase sees the account, the assertion and the session, our DNS resolver sees the domain name while we read your TXT record, and your identity provider sees what it already sees. Payments, mail and hosting are in the privacy policy and are unchanged by single sign-on.
    • An SSO identity is never silently merged with an existing password account at the same address, which is the same platform behaviour that produces the owner's twin account during the connection test. After the first SSO sign-in the person is shown what would move and chooses. Accepting moves projects, offers, price lists, portal links and files, then blocks the old sign-in, while billing history and any personal subscription stay with the old account.
    • Just-in-time provisioning is optional. With it on, a first sign-in from a verified domain creates the account at a role you pick, if a seat is free. With it off, people must exist before they can sign in, added by hand or by SCIM.
    • SCIM covers Users only. Groups are readable and always an empty list, on purpose, because roles are set in CCTVplanner. Filtering supports eq on userName, externalId, id and the work e-mail. PATCH works, bulk and sort do not.
    • The Entra claim about SessionNotOnOrAfter is checked against Microsoft's own SAML token reference at https://learn.microsoft.com/en-us/entra/identity-platform/reference-saml-tokens, whose sample token carries an AuthnStatement with AuthnInstant alone.
    • The fifteen minute deprovisioning ceiling measures our side only. It starts when your directory sends the deactivation, and we do not measure how often your directory syncs.
    • SSO_SESSION_IDLE is one of the refusal classes, but we have not documented an owner-settable idle timeout in the console. Ask us what value is in force before you write it into a control.
    • We have not certified SCIM against any specific directory. It follows SCIM 2.0, and we will not claim a test we have not run.
    • This page does not state the encryption-at-rest posture or who holds the keys. We do not run our own key management and we do not offer customer-managed keys, and we confirm the rest in writing.
    • The service provider entity id, the assertion consumer service URL and the SCIM base URL are not printed on this page. Read the first two from the console. If your egress rules need the SCIM host in advance, ask and we will send it in writing.
    • Okta's own documentation for the SAML app wizard did not load when we checked this page, so we name Okta settings, for example the identity provider metadata URL, rather than giving a click path that may already be out of date.
    • The hosting region is a contractual commitment rather than a line on a page we can edit. We name it in writing, against a date, so you can hold us to that version rather than to whatever the page says next quarter.

    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.