Back to Guides

What is a SAML ACS URL and how do I use it?

Usually engineers ask us some variant of what is a SAML ACS URL when they need to set up enterprise single sign-on for the first time. That's a totally reasonable ask. It's remarkably hard to find clear guides explaining the multitude of confusing authentication and user management terms.

Here, I'll try to clear up one: the SAML ACS URL. Bear with me -- I'd like to start with some context first.


The SAML ACS URL: foundational context

To make any sense of the SAML ACS, you really need to back up a little bit. You need to first understand the SAML protocol -- at least at a general, intuitive level. I highly recommend that you skim through these articles before going deeper:

  1. A gentle introduction to SAML: a minimally technical practitioner's guide to the SAML protocol. For instance, it covers why people want SAML and -- at a high level -- how SAML works.

  2. Identity providers vs. service providers: you also need to understand the different roles of identity providers (IDPs) and service providers (SPs). Your life gets a lot easier if you're comfortable with this stuff.

  3. Auth for B2B SaaS: it's not like auth for consumer software: it's also probably helpful to ground yourself in a broader intuition for B2B authentication and user management. This will make the SAML ACS make sense as part of a broader system.


What is the SAML ACS URL?

Recapping the entities involved in SAML SSO

At the risk of repeating content laid out in the links above, I'd like to recap the entities involved in SAML here. You really have three entities to think about:

  1. An end user. This is someone trying to log in. For example, this might be Sheryl from the Topeka regional office.

  2. An identity provider. This is a corporate software system responsible for keeping track of employees for a given company and their access privileges for certain software applications. Major examples of such systems will include Okta and Microsoft Entra.

  3. A service provider. This is a software application that an end user wants to access. It could be mostly anything; I often encourage people to imagine a pretty banal business software application like Slack or Zoom. You can imagine that Sheryl from the Tokepa regional office would want to use such an application.

Recapping the SAML flow

SAML SSO can work in a few different ways. Most commonly, end users will experience the service provider (SP) initiated flow. Roughly speaking, here's how it works:

  1. Sheryl from the Topeka regional office opens up a Zoom meeting. She's not logged in, so Zoom presents her with a standard login page. It looks like this:

sp-initiated-flow-zoom-login-page

  1. Sheryl knows her company uses SSO with Zoom, so she clicks the SSO button. This takes her to another Zoom page that asks for her company's domain. In essence, Zoom is asking for the company that she works for. She'll enter Megacorp and click Continue to move on.

sp-initiated-saml-flow-zoom-domain-discovery

  1. Zoom will look up Megacorp's pre-configured SAML settings and realize that it needs to redirect Sheryl to Megacorp's identity provider. Let's just imagine that Megacorp uses Okta. Sheryl will land on an Okta login page and enter her credentials.

  2. Once Sheryl logs in with Okta, she'll get sent back to a specific endpoint managed by Zoom. There's a bundle of data wrapped up in a SAML assertion that Okta wants to send to this endpoint. Zoom needs to process that SAML assertion in a few particular ways before it actually uses the data.

As it turns out, this specific endpoint is the ACS! More on this in a moment.


The SAML ACS URL: what it does

SAML Assertions, an example

SAML requires the identity provider to pass a big bundle of data to the service provider. We call this bundle a SAML assertion. Don't expect it to make sense right away, but here's what an example looks like:

<?xml version="1.0" encoding="UTF-8"?>
<saml2p:Response Destination="https://auth.ssoready.com/v1/saml/saml_conn_63ywr7ku0si9bkxqzcyubkm9k/acs" ID="id1368470320766678213853911" InResponseTo="saml_flow_a7pm91k7li2mi7891vxx602ep" IssueInstant="2024-11-26T23:09:22.419Z" Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
    <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
        http://www.okta.com/exklfk8v1xSAIYnI75d7
    </saml2:Issuer>
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
            <ds:Reference URI="#id1368470320766678213853911">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                <ds:DigestValue>
                    MUDF9rzi0H0uR6zscbe2PjgjK6K3AqSUrkccxMmHSzs=
                </ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>
            kjCEKS22D/7zlkuSh4Ihwjik+UAU1g19heaDrhVY5YwzeL0Ok+JpbYt4E4h5VmZP9hOYx05C4bOJTv2CneplCOdl9nOdsUeIc2IpZP8lBEZZUZMVwxancch9EtmyBhj060rmpfuDqg5aUyH+WZ/qGreIQZt23ejXtX8dKQ4wDkrkiHwggIZq+cUb0xYcJJSO+7onBwaOO4X6vXqemLU1In61xwubBAwI+6+lEXeGe2oMH+OMa2/nPkKR/wVNlZQ4Fp1SXEMW9RFkOKUcmmutNdw3M73epeNvdMnQnNUOeg4rXTgr+67I9WopqwKSkSe387tS+pAlqcEusE0KHYi23g==
        </ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>
                    MIIDqDCCApCgAwIBAgIGAZNqlA8/MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYDVQQGEwJVUzETMBEG
A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU
MBIGA1UECwwLU1NPUHJvdmlkZXIxFTATBgNVBAMMDGRldi0wOTE3ODI2MTEcMBoGCSqGSIb3DQEJ
ARYNaW5mb0Bva3RhLmNvbTAeFw0yNDExMjYyMjI0MDhaFw0zNDExMjYyMjI1MDhaMIGUMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsG
A1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxFTATBgNVBAMMDGRldi0wOTE3ODI2MTEc
MBoGCSqGSIb3DQEJARYNaW5mb0Bva3RhLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAMb1uengBvHZ0T8Ck+za/YmIpvjtpSzjWJorsgJDtd1ySQCjpOy66RHkWM74nYXuL++4a6Fp
WVau5Gwx74yUyumMBvwZgMNe7np0XoIWllPdRFtdnzlJU98uZI2rTCHiQ70r7t4Yyd/RIoR7u/in
lbY6m1bAsRoRkGPdxKpxXd3JymvSyi5917UMsnQYxZHuxN7ZsR7F/JIzv2IbzSp4h8Ro+7KzqTiy
8jBK6nLo9Ztn1WllEJE4qt7Bh7RWNXamQ1Y52RoAc+BMp1bELrmICrKRq31HfYlYwp3J3LV7YvPQ
weTZ3k3Rr0CQe6JwITMFzrR27NKImHRa/eYmqIlIDrUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA
tJPzfwmy2OoFuZDihid3ftigntV0thAnfICMlDfS90Ob/AWKeqHffeZPAQiMdEk4+c5gUVpgoGtc
QzppNZ4SGKqGrr+DKhsQZv+KdNFa1HB6v4n+6yZFzJBMnmyzS2IoVeAFeZajkULu6+jZ3plr3GS8
4xY5+os3qThdYYGtcSBxdNjQT0++beBNNMaewvUQmuNECPUTYADwlqszPhdKrW9w1WHz6AwD6raJ
lB01jQKI+48unjtkredhcRO7lOMtGZrrbqybVkh+PsoIFYF4SoT/wLdEfi+QWn/w6IXPvamgruni
WVeUvfdHsUn909Kjihsaa9wv7oMEHgKhbgjqVA==
                </ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </ds:Signature>
    <saml2p:Status xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol">
        <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
    </saml2p:Status>
    <saml2:Assertion ID="id13684703210387932078601572" IssueInstant="2024-11-26T23:09:22.419Z" Version="2.0" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
        <saml2:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
            http://www.okta.com/exklfk8v1xSAIYnI75d7
        </saml2:Issuer>
        <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
            <ds:SignedInfo>
                <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
                <ds:Reference URI="#id13684703210387932078601572">
                    <ds:Transforms>
                        <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                        <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                    </ds:Transforms>
                    <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
                    <ds:DigestValue>
                        WCbox/ACjyClXtPRapGVNhuWHG5QpS8XvQV+FyG2rOo=
                    </ds:DigestValue>
                </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>
                cjZVMiLb2K+MUcx6jd4tqrDypNKMjvhbJt1iJazGvn0nCeMIFgd2We8gy2b0ZWL/sS2LnfGDiY/lTyCsE6fVTz1jNr4tUOapsSxWLutYHZGID9ejpaZSnpA0oPr4zNKBPVo9PWzuDPfDLjz7Ajpe2MPaWuQbegnlzoIzzlvUu1MQT2YxqhfTX82yiyTx+QeWJCSj+WuZEtpHVVbOBWrTJlNEfquNisp2hWIji4+qmbzPURj49q4GKZNCsGRubHSsTwmOhxjCWWWnY44LeLjA/+Rg+Gp26qv1QuhDXV1BhNez96sUPekA0JXDgEDtUlxNvbDmktseMUsuhsDb0cN1qA==
            </ds:SignatureValue>
            <ds:KeyInfo>
                <ds:X509Data>
                    <ds:X509Certificate>
                        MIIDqDCCApCgAwIBAgIGAZNqlA8/MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYDVQQGEwJVUzETMBEG
A1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsGA1UECgwET2t0YTEU
MBIGA1UECwwLU1NPUHJvdmlkZXIxFTATBgNVBAMMDGRldi0wOTE3ODI2MTEcMBoGCSqGSIb3DQEJ
ARYNaW5mb0Bva3RhLmNvbTAeFw0yNDExMjYyMjI0MDhaFw0zNDExMjYyMjI1MDhaMIGUMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzENMAsG
A1UECgwET2t0YTEUMBIGA1UECwwLU1NPUHJvdmlkZXIxFTATBgNVBAMMDGRldi0wOTE3ODI2MTEc
MBoGCSqGSIb3DQEJARYNaW5mb0Bva3RhLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAMb1uengBvHZ0T8Ck+za/YmIpvjtpSzjWJorsgJDtd1ySQCjpOy66RHkWM74nYXuL++4a6Fp
WVau5Gwx74yUyumMBvwZgMNe7np0XoIWllPdRFtdnzlJU98uZI2rTCHiQ70r7t4Yyd/RIoR7u/in
lbY6m1bAsRoRkGPdxKpxXd3JymvSyi5917UMsnQYxZHuxN7ZsR7F/JIzv2IbzSp4h8Ro+7KzqTiy
8jBK6nLo9Ztn1WllEJE4qt7Bh7RWNXamQ1Y52RoAc+BMp1bELrmICrKRq31HfYlYwp3J3LV7YvPQ
weTZ3k3Rr0CQe6JwITMFzrR27NKImHRa/eYmqIlIDrUCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEA
tJPzfwmy2OoFuZDihid3ftigntV0thAnfICMlDfS90Ob/AWKeqHffeZPAQiMdEk4+c5gUVpgoGtc
QzppNZ4SGKqGrr+DKhsQZv+KdNFa1HB6v4n+6yZFzJBMnmyzS2IoVeAFeZajkULu6+jZ3plr3GS8
4xY5+os3qThdYYGtcSBxdNjQT0++beBNNMaewvUQmuNECPUTYADwlqszPhdKrW9w1WHz6AwD6raJ
lB01jQKI+48unjtkredhcRO7lOMtGZrrbqybVkh+PsoIFYF4SoT/wLdEfi+QWn/w6IXPvamgruni
WVeUvfdHsUn909Kjihsaa9wv7oMEHgKhbgjqVA==
                    </ds:X509Certificate>
                </ds:X509Data>
            </ds:KeyInfo>
        </ds:Signature>
        <saml2:Subject xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
            <saml2:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">
                ned.oleary@ssoready.com
            </saml2:NameID>
            <saml2:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml2:SubjectConfirmationData InResponseTo="saml_flow_a7pm91k7li2mi7891vxx602ep" NotOnOrAfter="2024-11-26T23:14:22.420Z" Recipient="https://auth.ssoready.com/v1/saml/saml_conn_63ywr7ku0si9bkxqzcyubkm9k/acs"/>
            </saml2:SubjectConfirmation>
        </saml2:Subject>
        <saml2:Conditions NotBefore="2024-11-26T23:04:22.420Z" NotOnOrAfter="2024-11-26T23:14:22.420Z" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
            <saml2:AudienceRestriction>
                <saml2:Audience>
                    https://auth.ssoready.com/v1/saml/saml_conn_63ywr7ku0si9bkxqzcyubkm9k
                </saml2:Audience>
            </saml2:AudienceRestriction>
        </saml2:Conditions>
        <saml2:AuthnStatement AuthnInstant="2024-11-26T23:09:22.419Z" SessionIndex="saml_flow_a7pm91k7li2mi7891vxx602ep" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">
            <saml2:AuthnContext>
                <saml2:AuthnContextClassRef>
                    urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
                </saml2:AuthnContextClassRef>
            </saml2:AuthnContext>
        </saml2:AuthnStatement>
    </saml2:Assertion>
</saml2p:Response>

For our purposes, it's essential to observe three characteristics of the SAML assertion:

  • It uses a multi-level nested document structure (this is XML). The structure of the document itself conveys meaning.
  • It contains claims about data. For example, it claims that the user's email address is ned.oleary@ssoready.com.
  • It includes digital signatures that prove the authenticity of the document. That is, they prove that the document of claims is a genuine artifact produced by the identity provider. This is made possible by pretty standard public key cryptography. (Note that XML signatures are really weird, though, even if the underlying cryptography is pretty reasonable.)

What the ACS URL does

So far I have intentionally not mentioned what ACS stands for. I wanted to cover what an assertion in SAML is first. That's because ACS stands for Assertion Consumer Service. It's a service that consumes SAML assertions. (Sorry.)

The Assertion Consumer Service is an endpoint (uniquely identified by its URL) that processes SAML assertions. The exact mechanics are a little out-of-scope, but you can imagine that it unfurls the complex nested structure of a SAML assertion, extracts claims, and verifies their content against the included digital signatures.

In many cases, it makes sense for the ACS also to establish a session for the user.

For an example, check out this simplified SAML SP implementation in JavaScript.

Please be aware that a SAML Assertion Consumer Service is extremely sensitive code. It is very, very easy to ship an unsafe implementation. I highly advise against doing this work yourself unless you are very experienced and willing to invest considerable effort.


How to set up a SAML ACS in the real world

Most people should not be setting up SAML single sign-on themselves. It's best in most cases to use a commercial auth vendor or an established, open source SAML server. I highly advise against building your own SAML implementation in nearly all cases.

Fortunately, there exist open source vendors that combine the convenience of a managed service with the flexibility and transparency you'd expect from an open source project. In particular, Tesseral is open source auth infrastructure specialized in serving B2B SaaS applications. When you use a tool like Tesseral, you actually don't even have to set up a SAML ACS. It just comes built-in. There's no need to even understand how SAML works under the hood; it's taken care of for you.

About the Author
Ned O'Leary
Ned O'Leary
Cofounder and CEO, Tesseral
Ned is the cofounder and CEO of Tesseral. Previously he worked at Gem and the Boston Consulting Group. He writes about product design, identity, and access management. You can often find him at Baker Beach in San Francisco with his puppy, Fred.
Newsletter
Resources
Company
Social