How SAML works

Category >

Absolutely. The easiest way to understand SAML 2.0 is to think of it as:

β€œA trusted Identity Provider tells an application: I authenticated this user, and here is a cryptographically signed statement proving it.”

The application never needs to see the user’s password.


1. The three main SAML components

There are normally three participants:

          β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ USER β”‚
β”‚ Browser β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
redirects / POSTs
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚
β–Ό β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SP β”‚ β”‚ IdP β”‚
β”‚ Service β”‚ β”‚ Identity β”‚
β”‚ Provider β”‚ β”‚ Provider β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ Application β”‚ β”‚ Entra ID β”‚
β”‚ VPN β”‚ β”‚ ADFS β”‚
β”‚ Salesforce β”‚ β”‚ Okta β”‚
β”‚ etc. β”‚ β”‚ Ping etc. β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

SP β€” Service Provider

The SP is the application you are trying to access.

Examples:

  • Salesforce
  • ServiceNow
  • Cisco VPN
  • SolarWinds
  • AWS application
  • some internal web application

The SP basically says:

“I don’t want to authenticate user myself. I’ll trust the IdP to do it.”


IdP β€” Identity Provider

The IdP authenticates the user.

Examples:

  • Microsoft Entra ID
  • ADFS
  • Okta
  • PingFederate
  • Duo SSO
  • Cisco Duo IAM

The IdP might authenticate using:

Username/password
+
MFA
+
Conditional Access
+
AD / LDAP / Cloud directory

Once successful, it creates a SAML Assertion.


User Agent

Usually this is simply the web browser.

This is important:

The browser carries most of the SAML messages between the SP and IdP.

It is not normally:

SP ─────────────► IdP

Instead it is commonly:

SP
β”‚
β”‚ redirect
β–Ό
Browser
β”‚
β”‚ redirect
β–Ό
IdP

IdP
β”‚
β”‚ HTML POST
β–Ό
Browser
β”‚
β”‚ POST
β–Ό
SP

This concept explains a huge amount of SAML troubleshooting.


2. The basic SAML login

Suppose you want to access:

https://app.company.com

Your company uses:

Microsoft Entra ID

for authentication.

The overall process looks like this:

 USER              SERVICE PROVIDER              IDENTITY PROVIDER
Browser (SP) (IdP)
β”‚ β”‚ β”‚
β”‚ GET application β”‚ β”‚
│─────────────────────►│ β”‚
β”‚ β”‚ β”‚
β”‚ No session β”‚ β”‚
β”‚ β”‚ β”‚
β”‚ 302 Redirect β”‚ β”‚
β”‚ + SAMLRequest β”‚ β”‚
│◄─────────────────────│ β”‚
β”‚ β”‚
β”‚ GET IdP + SAMLRequest β”‚
│────────────────────────────────────────────────────►│
β”‚ β”‚
β”‚ Authenticate user β”‚
│◄───────────────────────────────────────────────────►│
β”‚ β”‚
β”‚ SAML Response β”‚
│◄────────────────────────────────────────────────────│
β”‚ β”‚
β”‚ POST SAMLResponse β”‚
│─────────────────────►│ β”‚
β”‚ β”‚ β”‚
β”‚ Validate assertion β”‚
β”‚ β”‚ β”‚
β”‚ Create SP session β”‚
β”‚ β”‚ β”‚
β”‚ Application page β”‚ β”‚
│◄─────────────────────│ β”‚

Now let’s break that down properly.


3. Step 1 β€” User accesses the application

The browser goes to:

https://app.company.com

The SP checks for its own application session cookie.

For example:

Browser
β”‚
β”‚ GET /
β”‚ Cookie: SESSION=???
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Service Provider β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

If there is no valid application session, the SP decides:

User needs authentication.

But because SAML is configured, it doesn’t display its own login page.

Instead, it creates a SAML AuthnRequest.


4. Step 2 β€” SP creates an AuthnRequest

Conceptually the message says:

Hello Identity Provider.

I am app.company.com.

Please authenticate this user.

When you have finished,
send the result to:

https://app.company.com/saml/acs

The actual XML looks roughly like:

<samlp:AuthnRequest
ID="_abc123"
Version="2.0"
Destination="https://idp.company.com/saml"
AssertionConsumerServiceURL=
"https://app.company.com/saml/acs">

<saml:Issuer>
https://app.company.com
</saml:Issuer>

</samlp:AuthnRequest>

There are two very important URLs here.

IdP SSO URL

Where the SP sends the browser:

https://idp.company.com/saml

ACS URL

Where the IdP eventually sends the SAML response:

https://app.company.com/saml/acs

ACS means:

Assertion Consumer Service.

Remember that term. It appears constantly in SAML configuration and troubleshooting.


5. The browser gets redirected to the IdP

The SP might send:

HTTP/1.1 302 Found

Location:
https://idp.company.com/saml?
SAMLRequest=xxxxxxxxxxxx
&RelayState=yyyyyyyy

The flow becomes:

                   SAMLRequest
β”‚
β–Ό

Browser ───────────────────────────────► IdP
https://idp...?SAMLRequest=...

The SAMLRequest is usually:

XML
↓
DEFLATE compression
↓
Base64
↓
URL encoding

when using the HTTP Redirect Binding.


6. What is RelayState?

You’ll often see:

SAMLRequest=....
RelayState=....

RelayState is basically:

“After authentication, where was this user originally trying to go?”

For example, the user may have requested:

https://app.company.com/reports/network

Instead of simply:

https://app.company.com/

RelayState lets the application remember that.

Conceptually:

User originally requests:

/reports/network

β”‚
β–Ό

SAML authentication

β”‚
β–Ό

Successful

β”‚
β–Ό

RelayState tells SP:

Send them back to:

/reports/network

7. Step 3 β€” IdP authenticates the user

The browser now arrives at the IdP.

For example:

login.microsoftonline.com

or:

adfs.company.com

The IdP now determines:

Who is this user?

Authentication could involve:

              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ IdP β”‚
β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚ β”‚
β–Ό β–Ό β–Ό
Password MFA Certificate
β”‚
β–Ό
AD / LDAP

SAML itself does not define how the IdP must authenticate the user.

It only says:

Once authentication has happened, this is how the IdP tells the SP about it.

So the IdP could use:

  • password
  • MFA
  • FIDO2
  • Windows Integrated Authentication
  • certificate authentication
  • smart card
  • biometrics
  • Conditional Access

SAML doesn’t really care.


8. The IdP may already know who you are

This is where SSO becomes important.

Suppose earlier that morning you logged into:

Application A

using Entra ID.

The IdP may have already issued an IdP session cookie.

So later:

Application B
β”‚
β–Ό
Entra ID

can see:

This browser already authenticated User.

Therefore you may not see another login screen.

The flow could be:

Application A
β”‚
β–Ό
IdP
β”‚
β”œβ”€β”€ Authenticate user
β”‚
└── Create IdP session

Later...

Application B
β”‚
β–Ό
IdP
β”‚
└── Existing session found
β”‚
β–Ό
No password required

That’s the Single Sign-On part.


9. Step 4 β€” IdP creates a SAML Assertion

Once authentication succeeds, the IdP generates something called a:

SAML Assertion

Think of an assertion as a digitally signed statement saying:

I, Entra ID,
confirm that:

User = user@company.com

authenticated successfully

at 23:15

using MFA

for application:

app.company.com

A simplified assertion might look like:

<saml:Assertion>

<saml:Issuer>
https://idp.company.com
</saml:Issuer>

<saml:Subject>

<saml:NameID>
user@company.com
</saml:NameID>

</saml:Subject>

<saml:Conditions>

<saml:AudienceRestriction>

<saml:Audience>
https://app.company.com
</saml:Audience>

</saml:AudienceRestriction>

</saml:Conditions>

<saml:AuthnStatement>
Authentication successful
</saml:AuthnStatement>

</saml:Assertion>

The real XML is obviously considerably more complex.


10. Assertion versus SAML Response

This is something that causes confusion.

There is usually a:

SAML Response

containing a:

SAML Assertion

Think of it like an envelope.

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SAML Response β”‚
β”‚ β”‚
β”‚ Status: Success β”‚
β”‚ β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ SAML Assertion β”‚ β”‚
β”‚ β”‚ β”‚ β”‚
β”‚ β”‚ User β”‚ β”‚
β”‚ β”‚ Authentication information β”‚ β”‚
β”‚ β”‚ Attributes β”‚ β”‚
β”‚ β”‚ Conditions β”‚ β”‚
β”‚ β”‚ Audience β”‚ β”‚
β”‚ β”‚ Time restrictions β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β”‚ β”‚
β”‚ Signature β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Depending on the implementation:

  • Response may be signed
  • Assertion may be signed
  • both may be signed
  • Assertion may additionally be encrypted

11. Step 5 β€” IdP sends SAMLResponse to browser

This is usually done using:

HTTP POST Binding

The IdP sends an HTML page containing something like:

<form method="POST"
action="https://app.company.com/saml/acs">

<input type="hidden"
name="SAMLResponse"
value="PHNhbWxwOlJlc3BvbnNl...">

<input type="hidden"
name="RelayState"
value="xyz">

</form>

JavaScript automatically submits the form.

So the flow is:

              IdP
β”‚
β”‚ HTML form
β”‚ containing
β”‚ SAMLResponse
β–Ό
Browser
β”‚
β”‚ HTTP POST
β–Ό
https://app.company.com/saml/acs

Again:

The browser carries the SAML response.

The IdP normally does not establish some special back-end TCP session directly to the SP to deliver the assertion.


12. The SAML Response reaches the ACS

The browser performs something like:

POST /saml/acs HTTP/1.1
Host: app.company.com

SAMLResponse=PHNhbWxwOlJlc3BvbnNl...
RelayState=xyz

The SP receives it at:

ACS

or:

Assertion Consumer Service

Diagram:

IdP
β”‚
β”‚ Creates signed assertion
β–Ό
Browser
β”‚
β”‚ POST
β”‚ SAMLResponse
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SP β”‚
β”‚ β”‚
β”‚ Assertion Consumer Service β”‚
β”‚ /saml/acs β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Now the really important security checks happen.


13. How does the SP know the assertion is genuine?

Suppose an attacker creates:

User = administrator@company.com
Authentication = successful

and sends it to the ACS.

Why wouldn’t the SP accept it?

Because SAML assertions are digitally signed.

The IdP possesses:

Private Key

and the SP knows the corresponding:

Public Key / Certificate

Conceptually:

              Identity Provider

SAML Assertion
β”‚
β–Ό
Hash the XML
β”‚
β–Ό
Sign using
IdP Private Key
β”‚
β–Ό
Signed SAML Assertion
β”‚
β–Ό
Browser
β”‚
β–Ό
Service Provider
β”‚
β–Ό
Verify signature using
IdP Public Certificate

The private key stays at the IdP.


14. SAML trust

This is one of the most important parts of SAML.

The SP has to trust the IdP.

Usually this information comes from SAML Metadata.

The SP might know:

IdP Entity ID:
https://idp.company.com

IdP SSO URL:
https://idp.company.com/saml

IdP signing certificate:
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----

Now:

                  TRUST

IdP Private Key
β”‚
β”‚ signs
β–Ό
SAML Assertion
β”‚
β–Ό
SP
β”‚
β”‚ verifies using
β–Ό
IdP Public Certificate

This certificate relationship is critical.


15. What the SP actually validates

A good SAML implementation doesn’t simply say:

Signature valid = allow user

It performs several checks.

Conceptually:

                 SAML Response
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Signature valid? β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ Yes
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Correct issuer? β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Correct audience? β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Not expired? β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Correct ACS? β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Request matches? β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
ACCEPT

Typical checks include:

Signature

Was it signed by the expected IdP certificate?

Issuer

For example:

<Issuer>
https://idp.company.com
</Issuer>

Does that match the configured IdP?

Audience

The assertion might say:

<Audience>
https://app.company.com
</Audience>

This prevents a SAML assertion intended for Application A from simply being used against Application B.


16. SAML time restrictions

Assertions normally have a short validity period.

You might see:

<Conditions
NotBefore="2026-08-16T23:18:00Z"
NotOnOrAfter="2026-08-16T23:23:00Z">

Meaning:

23:18                 23:23
β”‚ β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
VALID WINDOW

Before:

NotBefore

β†’ reject.

After:

NotOnOrAfter

β†’ reject.

This is why clock synchronisation/NTP can cause SAML problems.

For example:

IdP time = 23:20

SP time = 23:27

SP might say:

Assertion expired.

even though it was generated seconds ago.


17. InResponseTo

Suppose the SP generated:

AuthnRequest ID:

_REQ98765

The response can contain:

InResponseTo="_REQ98765"

The SP can therefore check:

I sent:
_REQ98765

I received response for:
_REQ98765

Match = Yes

This helps prevent various replay or unsolicited-response problems.


18. NameID

The assertion needs to tell the SP who authenticated.

One common mechanism is:

<NameID>
user@company.com
</NameID>

NameID could be:

user@company.com

or:

user.lastname

or some persistent unique identifier.

This is extremely important.

If the SP expects:

username

but the IdP sends:

email address

authentication can succeed at the IdP but the SP might say:

User not found.

For example:

IdP sends

user@company.com

β”‚
β–Ό

SP expects

First.Lastname

β”‚
β–Ό

No matching local account

19. SAML attributes

Assertions can contain much more than the username.

For example:

<Attribute Name="email">
user@company.com
</Attribute>

<Attribute Name="department">
Network Operations
</Attribute>

<Attribute Name="role">
NetworkAdministrator
</Attribute>

<Attribute Name="group">
VPN-Users
</Attribute>

Conceptually:

Identity Provider

User:
user

Groups:
β”œβ”€β”€ Network-Engineering
β”œβ”€β”€ VPN-Users
└── Administrators
β”‚
β”‚ SAML attributes
β–Ό
Service Provider
β”‚
β”œβ”€β”€ Allow login
β”‚
└── Assign permissions

This means SAML can be involved in both:

Authentication
+
User attribute delivery

Although the SP ultimately decides authorization.


20. Authentication versus authorization

Very important distinction.

SAML primarily proves:

WHO ARE YOU?

That’s authentication.

Example:

User successfully authenticated.

It doesn’t inherently mean:

User is an administrator.

Authorization could come from attributes:

User
β”‚
β–Ό
SAML Assertion
β”‚
β”œβ”€β”€ Name = User
β”‚
β”œβ”€β”€ Group = Network-Team
β”‚
└── Role = Administrator
β”‚
β–Ό
Application
β”‚
β–Ό
Authorization

The application decides what those values mean.


21. The SP creates its own session

Another critical concept:

The SAML assertion normally isn’t used for every subsequent HTTP request.

Once authentication succeeds:

SAML authentication
β”‚
β–Ό
SP validates assertion
β”‚
β–Ό
SP creates application session
β”‚
β–Ό
Browser receives cookie

Example:

Set-Cookie:
APPSESSION=a8f92bc839...

From that point:

Browser
β”‚
β”‚ Cookie: APPSESSION=...
β–Ό
Application

The application knows who you are from its own session.

So there can be two separate sessions:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Browser β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”Œβ”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”
β”‚ β”‚
β–Ό β–Ό
IdP Session SP Session
Cookie Cookie

login session application
with IdP session

This becomes very important with logout.


22. Full SP-initiated SAML flow

This is the most common flow.

 Browser                    SP                         IdP
β”‚ β”‚ β”‚
β”‚ GET /dashboard β”‚ β”‚
│───────────────────────►│ β”‚
β”‚ β”‚ β”‚
β”‚ β”‚ No local session β”‚
β”‚ β”‚ β”‚
β”‚ 302 Redirect β”‚ β”‚
β”‚ SAMLRequest β”‚ β”‚
│◄───────────────────────│ β”‚
β”‚ β”‚
β”‚ GET /sso?SAMLRequest=... β”‚
│──────────────────────────────────────────────────►│
β”‚ β”‚
β”‚ Check IdP session β”‚
β”‚ β”‚
β”‚ Authenticate / MFA β”‚
│◄─────────────────────────────────────────────────►│
β”‚ β”‚
β”‚ Generate SAML Assertion β”‚
β”‚ Sign assertion β”‚
β”‚ β”‚
β”‚ HTML form containing β”‚
β”‚ SAMLResponse β”‚
│◄──────────────────────────────────────────────────│
β”‚ β”‚
β”‚ POST /saml/acs β”‚
β”‚ SAMLResponse β”‚ β”‚
│──────────────────────►│ β”‚
β”‚ β”‚ β”‚
β”‚ β”‚ Verify signature β”‚
β”‚ β”‚ Verify issuer β”‚
β”‚ β”‚ Verify audience β”‚
β”‚ β”‚ Verify timestamps β”‚
β”‚ β”‚ Verify InResponseTo β”‚
β”‚ β”‚ Extract NameID β”‚
β”‚ β”‚ Extract attributes β”‚
β”‚ β”‚ β”‚
β”‚ β”‚ Create local session β”‚
β”‚ β”‚ β”‚
β”‚ Set-Cookie β”‚ β”‚
β”‚ APPSESSION=xyz β”‚ β”‚
│◄──────────────────────│ β”‚
β”‚ β”‚ β”‚
β”‚ GET /dashboard β”‚ β”‚
│──────────────────────►│ β”‚
β”‚ β”‚ β”‚
β”‚ Dashboard β”‚ β”‚
│◄──────────────────────│ β”‚

That’s essentially SAML Web SSO.


23. SP-initiated versus IdP-initiated

There are two common ways to start SAML.

SP-initiated

User starts at:

Application

Flow:

User
β”‚
β–Ό
SP
β”‚
β”‚ AuthnRequest
β–Ό
IdP
β”‚
β”‚ SAMLResponse
β–Ό
SP

This is generally preferable because the SP knows which authentication request it is responding to.


IdP-initiated

User starts at the IdP portal.

For example:

Microsoft My Apps
Okta Dashboard

Flow:

User
β”‚
β–Ό
IdP portal
β”‚
β”‚ Click Application
β”‚
β–Ό
Generate assertion
β”‚
β–Ό
SP ACS

There might not be an original:

AuthnRequest

from the SP.

So:

SP initiated:

SP ───Request───► IdP
SP ◄──Response─── IdP


IdP initiated:

IdP
β”‚
β”‚ Response
β–Ό
SP

SP-initiated authentication generally provides better request/response correlation.


24. SAML Metadata

Instead of manually configuring dozens of settings, systems usually exchange:

Metadata XML

IdP metadata might contain:

Entity ID
SSO URL
SLO URL
Signing Certificate
Supported bindings

SP metadata might contain:

Entity ID
ACS URL
Logout URL
Signing Certificate
Encryption Certificate

Conceptually:

      SP Metadata                    IdP Metadata

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Entity ID β”‚ β”‚ Entity ID β”‚
β”‚ ACS URL β”‚ β”‚ SSO URL β”‚
β”‚ Signing cert β”‚ β”‚ Signing cert β”‚
β”‚ Encryption cert β”‚ β”‚ Logout URL β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
Establish trust

25. Signing versus encryption

These are different concepts.

Signing

Answers:

“Did this really come from the IdP, and has anyone modified it?”

Assertion
β”‚
β–Ό
IdP Private Key
β”‚
β–Ό
SIGNATURE

SP uses the IdP public certificate to validate it.


Encryption

Answers:

“Can someone carrying this message read its contents?”

Assertion
β”‚
β–Ό
Encrypt using
SP public key
β”‚
β–Ό
Encrypted Assertion
β”‚
β–Ό
SP decrypts using
SP private key

So:

SIGNATURE
= integrity + authenticity

ENCRYPTION
= confidentiality

HTTPS is still normally used even when assertion encryption is enabled.


26. Certificate usage can get confusing

You might have:

IdP Signing Certificate

and:

SP Encryption Certificate

They have completely different purposes.

                  SIGNING

IdP Private Key
β”‚
β–Ό
SAML Assertion
β”‚
β–Ό
SP validates using
IdP public certificate


ENCRYPTION

IdP
β”‚
β”‚ Encrypts using
β–Ό
SP public certificate
β”‚
β–Ό
Encrypted assertion
β”‚
β–Ό
SP decrypts using
SP private key

This distinction is very useful when troubleshooting certificate errors.


27. Why HTTPS certificate and SAML certificate aren’t necessarily the same

Another common misunderstanding.

You may have:

https://idp.company.com

The web server uses a TLS certificate.

Separately, the IdP may have:

SAML signing certificate

These can be completely different certificates.

                IdP

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
HTTPS ──►│ TLS cert β”‚
β”‚ β”‚
SAML ───►│ Signing cert β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The TLS certificate protects the HTTPS connection.

The SAML signing certificate signs the SAML message.


28. Why certificate expiry/rotation matters

Suppose the SP has:

IdP Certificate A

configured.

Then the IdP rotates to:

Certificate B

and starts signing assertions with B.

The SP receives:

SAML Response
signed by Cert B

but only trusts:

Cert A

Result:

Authentication at IdP
SUCCESS

β”‚

SAML signature validation
FAILED

From the user’s perspective this often looks strange:

Password accepted
MFA accepted
Then application login fails

The authentication itself was successful; the SAML trust validation failed afterward.


29. Common SAML problems

Most real SAML issues fall into a relatively small set of categories.

SAML Failure
β”‚
β”œβ”€β”€ Wrong Entity ID
β”‚
β”œβ”€β”€ Wrong ACS URL
β”‚
β”œβ”€β”€ Wrong IdP URL
β”‚
β”œβ”€β”€ Signing certificate mismatch
β”‚
β”œβ”€β”€ Expired signing certificate
β”‚
β”œβ”€β”€ Incorrect NameID
β”‚
β”œβ”€β”€ Missing attribute
β”‚
β”œβ”€β”€ Wrong group/role claim
β”‚
β”œβ”€β”€ Clock skew
β”‚
β”œβ”€β”€ Audience mismatch
β”‚
β”œβ”€β”€ Recipient mismatch
β”‚
β”œβ”€β”€ Signature validation failure
β”‚
└── User exists at IdP but not SP

30. A particularly useful troubleshooting model

When troubleshooting SAML, divide the process into four stages:

        1
SP REQUEST
β”‚
β–Ό
2
IdP AUTHENTICATION
β”‚
β–Ό
3
SAML ASSERTION
β”‚
β–Ό
4
SP SESSION

Ask:

Stage 1 β€” Did the browser reach the IdP?

If no:

SP configuration
DNS
redirect
Entity ID
SSO URL
browser

Stage 2 β€” Did IdP authentication succeed?

If no:

credentials
MFA
Conditional Access
user account
IdP policy

Stage 3 β€” Did the SP accept the assertion?

If no:

Think:

certificate
signature
audience
ACS
NameID
attributes
timestamps
issuer

Stage 4 β€” Did the SP create a session?

If no:

Think:

local user mapping
authorization
group mapping
cookies
application configuration

This approach makes SAML troubleshooting much easier.


31. The browser’s view

If you capture the login using browser developer tools, you will often see something like:

GET https://application.company.com

302

GET https://idp.company.com/...
?SAMLRequest=...

200

POST https://application.company.com/saml/acs

SAMLResponse=...
RelayState=...

302

GET https://application.company.com/dashboard

200

Which visually is:

Application
β”‚
β”‚ 302
β–Ό
IdP
β”‚
β”‚ Login / MFA
β”‚
β”‚ POST SAMLResponse
β–Ό
Application ACS
β”‚
β”‚ 302
β–Ό
Application

Tools such as browser developer tools and SAML browser-tracer extensions can therefore be extremely useful.


32. One very important point about passwords

The SP normally never receives this:

Username: User
Password: MyPassword

Instead:

                         Password
β”‚
β–Ό
User ─────────────────────► IdP
β”‚
β”‚ authenticate
β–Ό
successful
β”‚
β–Ό
Signed assertion
β”‚
β–Ό
SP

The SP receives essentially:

"The IdP confirms this user authenticated."

not the password itself.

This is one of the major benefits of federated identity.


33. Why this is called federation

There are two separate security domains.

Company Identity System

Entra ID
β”‚
β”‚ Federation trust
β–Ό

External Application

Salesforce

Salesforce doesn’t have to authenticate against your Active Directory directly.

Instead:

Salesforce trusts Entra ID.

That trust relationship is identity federation.


34. SAML compared with LDAP

They’re very different.

With LDAP authentication:

Application
β”‚
β”‚ username/password
β–Ό
LDAP / Active Directory
β”‚
β–Ό
Authentication result

The application may handle the user’s credentials.

With SAML:

Application
β”‚
β”‚ redirect browser
β–Ό
Identity Provider
β”‚
β”‚ authenticates user
β–Ό
Signed assertion
β”‚
β–Ό
Application

The SP doesn’t need the password.


35. SAML compared with OAuth / OpenID Connect

A useful simplified comparison:

ProtocolPrimary purpose
SAMLFederation / authentication
OAuth 2.0Authorization / API access
OpenID ConnectAuthentication on top of OAuth 2.0

SAML commonly uses:

XML
SAML Assertion
HTTP Redirect
HTTP POST

OIDC commonly uses:

JSON
JWT
Authorization Code
Access Token
ID Token

So conceptually:

SAML

IdP
β”‚
β”‚ XML Assertion
β–Ό
SP


OIDC

Identity Provider
β”‚
β”‚ ID Token / JWT
β–Ό
Application

OIDC is extremely common for modern web/mobile applications, while SAML remains very common for enterprise SSO.


36. The whole thing in one diagram

This is the diagram I would remember:

                    SAML 2.0 SP-INITIATED LOGIN


β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ USER β”‚
β”‚ Browser β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
1. Access App
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Service Provider β”‚
β”‚ SP β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
2. Create AuthnRequest
β”‚
302 browser redirect
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Identity Provider β”‚
β”‚ IdP β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
3. Authenticate user
β”‚
Password / MFA etc.
β”‚
β–Ό
4. Create Assertion
β”‚
Sign using
IdP private key
β”‚
β–Ό
Browser
β”‚
5. POST SAMLResponse
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ SP ACS endpoint β”‚
β”‚ β”‚
β”‚ Verify signature β”‚
β”‚ Verify audience β”‚
β”‚ Verify issuer β”‚
β”‚ Verify timestamp β”‚
β”‚ Extract NameID β”‚
β”‚ Read attributes β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
6. Valid assertion
β”‚
β–Ό
Create SP session
β”‚
β–Ό
Set Cookie
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ USER β”‚
β”‚ Logged In β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

The five things I would remember most

If you remember nothing else, remember these:

  1. SP = application; IdP = authenticates the user.
  2. The browser normally carries SAML messages between them.
  3. SP sends an AuthnRequest; IdP returns a signed SAMLResponse/Assertion.
  4. The SP trusts the IdP because it has the IdP’s signing certificate and validates the signature, issuer, audience, ACS, timestamps, etc.
  5. After validating SAML, the SP normally creates its own application session cookie.

Once those five ideas are clear, most of the rest of SAML becomes much easier to understand.


Leave a Reply

Your email address will not be published. Required fields are marked *