AuthTrace › Guides

Fix "InResponseTo does not match" and unsolicited SAML responses

The user signs in at the identity provider (IdP), is sent back to the application, and the application refuses the response with something like InResponseTo does not match the ID of the AuthnRequest, invalid_in_response_to, Unsolicited response received or Response is not a response to any known request. The IdP logs show a successful sign-in, which makes this one confusing: nothing is wrong with the user or the IdP.

What it means

In a service-provider-initiated sign-in, the application (SP) creates an AuthnRequest with a random ID, remembers that ID, and sends the browser to the IdP. The IdP copies the ID into the response:

<samlp:AuthnRequest ID="_8e1c4a…" AssertionConsumerServiceURL="https://app.example.com/saml/acs" …>

<samlp:Response InResponseTo="_8e1c4a…" …>
  …<saml:SubjectConfirmationData InResponseTo="_8e1c4a…" Recipient="https://app.example.com/saml/acs" …/>

When the response arrives, the SP looks up the ID it remembered and compares. If it can't find one, or finds a different one, it rejects the response. This check stops an attacker from injecting a response the SP never asked for. So the error almost never means the IdP got the ID wrong - it means the SP forgot what it asked for, or never asked.

The six usual causes

1. The session cookie was not sent with the POST back

This is the most common cause in modern browsers. The SAML response comes back as a form POST from the IdP's domain to the app's ACS URL - a cross-site POST. Cookies marked SameSite=Lax, which is also what Chrome assumes when a cookie has no SameSite attribute at all, are not sent on a cross-site POST. If the SP stored the request ID in a session tied to such a cookie, the session looks empty when the response lands.

Fix: give the cookie that carries the SP's pre-login state SameSite=None; Secure. Most SAML libraries and frameworks have a setting for exactly this. Only that cookie needs it; the app's main session cookie can stay Lax if it is re-issued after sign-in.

2. Several servers, no shared session

The AuthnRequest was created on server A, the response was posted to server B behind the same load balancer, and B has no record of the ID. It fails some of the time, roughly in proportion to how many nodes there are. Fix: keep SAML request state in a shared store (database, Redis) or turn on session affinity for the ACS path.

3. The app restarted in between

Request IDs kept in process memory disappear on a deploy or crash. Anyone mid-sign-in during the restart gets the error once. Same fix as above.

4. Two sign-ins in flight, or an old one replayed

The user opened the app in two tabs, so the second AuthnRequest replaced the first ID in the session; or they bookmarked the IdP's sign-in page (with an old SAMLRequest in the URL); or they pressed Back after signing in and the browser re-posted the response. Ask how they got there. Fix: allow more than one outstanding request ID per session, and tell users to bookmark the app, not the IdP page.

5. The sign-in started at the IdP

When the user clicks a tile in the IdP's app portal, the IdP sends a response nobody asked for (IdP-initiated SSO). It has no InResponseTo at all. SPs that only allow SP-initiated sign-in reject it as unsolicited. Fix one of two ways:

6. The response was posted to a different host

The user started on https://www.example.com but the ACS URL configured in the IdP is https://example.com/saml/acs (or http://, or an old hostname). A host-only cookie set on one is never sent to the other. Fix: make the ACS URL in the IdP use the same scheme and host the user signs in from, and redirect everything else to the canonical host before the sign-in starts.

Prove which one you have

  1. Open DevTools on the app tab before you sign in, and choose the AuthTrace panel.
  2. Reproduce the failure. AuthTrace pairs the AuthnRequest with the response. If the IDs differ you get InResponseTo does not match the request with both values; if the response has none you get Missing InResponseTo - that is cause 5.
  3. If the IDs match but the app still complains, the SP lost its state (causes 1-4 or 6). Switch to the Network panel, select the POST to the ACS URL, and open its Cookies tab with show filtered out request cookies ticked. A session cookie listed there as blocked, with a SameSite reason, is cause 1.
  4. Compare the host in the AuthnRequest's AssertionConsumerServiceURL with the host in the address bar when the sign-in started - a difference is cause 6.
If two people need to look at it, AuthTrace Pro can diff a working and a failing sign-in side by side: a missing cookie or a changed ACS host stands out at once.

More guides