Problems logging in with Azure SSO in Jira
Problem
You can't log in to the mobile app when using the SAML authentication. The following error is written in the logs:
[c.a.p.a.i.web.filter.ErrorHandlingFilter] Received invalid SAML response: The Response has an InResponseTo attribute: ONELOGIN_69459a17-0211-427e-9f0f-9c7a1779009e while no InResponseTo was expected
Details
What is SAML and how it works
Security Assertion Markup Language (SAML) is an open standard that allows identity providers (IdP) to pass authorization credentials to service providers (SP). SAML transactions use Extensible Markup Language (XML) for standardized communications between the identity provider and service providers.
Respectively, there are various authentication process types:
SP-initiated SSO using Redirect Binding to pass the <AuthnRequest> message from an SP to an IdP, and by using POST Binding to pass the <Response> message from an IdP to an SP;
SP-initiated SSO using POST Binding for the <AuthnRequest> message and the Artifact Binding to transfer the <Response> message;
IDP-initiated SSO using POST Binding to transfer the <Response> message from an IdP to an SP; <AuthnRequest> is not used at all.
Finally, let’s have a look at the SSO authentication process between Jira and Azure SSO by using the SP-Initiated SSO: Redirect/POST Bindings
- A user tries to access Jira by using a particular URL. They have no active login session (e.g., security context). The Service Provider will save the URL requested by the user.
- The application finds the Identity Provider to authenticate the user.
The Service Provider returns a request to the user's browser with the 302 or 303 redirect code. The
HTTP Location
header will include the SSO service URL, and the URL-variableSAMLRequest
will pass the<AuthnRequest>
request body. Here's an example:<samlp:AuthnRequest xmlns="urn:oasis:names:tc:SAML:2.0:metadata" ID="id6c1c178c166d486687be4aaf5e482730" Version="2.0" IssueInstant="2013-03-18T03:28:54.1839884Z" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">https://www.example.com</Issuer> </samlp:AuthnRequest>
The browser will then handle the received redirect and issue HTTP GET to the Identity Provider URL, passing the
SAMLRequest
.- The SSO service checks if the user has an active login session which needs to comply with the authentication type requested as it passed in the
AuthnRequest
from the Service Provider (Jira). If this session isn't found, the user has to authenticate on the Identity Provider with their login and password. As a result, the user is authenticated on the Identity Provider, where a security context is created for them. The Identity Provider's SSO service generates a SAML
<Response>
which includes an assert with this user's security context. TheSAMLResponse
body is transferred in the base64 encoding in the<samlp:Response>
element. A response to a successful sign-on attempt looks similar to the following example:<samlp:Response ID="_a4958bfd-e107-4e67-b06d-0d85ade2e76a" Version="2.0" IssueInstant="2013-03-18T07:38:15.144Z" Destination="https://example.com/identity/inboundsso.aspx" InResponseTo="id758d0ef385634593a77bdf7e632984b6" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion"> https://login.microsoftonline.com/82869000-6ad1-48f0-8171-272ed18796e9/</Issuer> <ds:Signature xmlns:ds="https://www.w3.org/2000/09/xmldsig#"> ... </ds:Signature> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /> </samlp:Status> <Assertion ID="_bf9c623d-cc20-407a-9a59-c2d0aee84d12" IssueInstant="2013-03-18T07:38:15.144Z" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion"> <Issuer>https://login.microsoftonline.com/82869000-6ad1-48f0-8171-272ed18796e9/</Issuer> <ds:Signature xmlns:ds="https://www.w3.org/2000/09/xmldsig#"> ... </ds:Signature> <Subject> <NameID>Uz2Pqz1X7pxe4XLWxV9KJQ+n59d573SepSAkuYKSde8=</NameID> <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <SubjectConfirmationData InResponseTo="id758d0ef385634593a77bdf7e632984b6" NotOnOrAfter="2013-03-18T07:43:15.144Z" Recipient="https://example.com/identity/inboundsso.aspx" /> </SubjectConfirmation> </Subject> <Conditions NotBefore="2013-03-18T07:38:15.128Z" NotOnOrAfter="2013-03-18T08:48:15.128Z"> <AudienceRestriction> <Audience>https://www.example.com</Audience> </AudienceRestriction> </Conditions> <AttributeStatement> <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name"> <AttributeValue>testuser@example.com</AttributeValue> </Attribute> <Attribute Name="http://schemas.microsoft.com/identity/claims/objectidentifier"> <AttributeValue>3F2504E0-4F89-11D3-9A0C-0305E82C3301</AttributeValue> </Attribute> ... </AttributeStatement> <AuthnStatement AuthnInstant="2013-03-18T07:33:56.000Z" SessionIndex="_bf9c623d-cc20-407a-9a59-c2d0aee84d12"> <AuthnContext> <AuthnContextClassRef> urn:oasis:names:tc:SAML:2.0:ac:classes:Password</AuthnContextClassRef> </AuthnContext> </AuthnStatement> </Assertion> </samlp:Response>
- The browser will issue a POST request to the Service Provider (Jira) passing the
SAMLResponse
. The Service Provider will check the<Response>
content and create a new local security for this user.
What is session affinity
The cookie-based session affinity feature is useful when you want to keep a user session on the same server. Azure Application Gateway uses gateway-managed cookies for maintaining user sessions. When a user sends the first request to Application Gateway, it sets an affinity cookie in the response with a hash value which contains the session details, so that the subsequent requests carrying the affinity cookie will be routed to the same backend server for maintaining stickiness.
When enabled, Azure Application Gateway does the following:
When a client makes its first request, Azure Application Gateway sets an ApplicationGatewayAffinity and ApplicationGatewayAffinityCORS cookie. The cookie encodes the origin to which the request will be forwarded.
Subsequent requests with the same cookie are forwarded to that origin for the duration of the cookie and as long as the origin server remains healthy.
The Chromium browser v80 update brought a mandate where HTTP cookies without SameSite attribute have to be treated as SameSite=Lax. In the case of CORS (Cross-Origin Resource Sharing) requests, if the cookie has to be sent in a third-party context, it has to use SameSite=None; Secure attributes and it should be sent over HTTPS only.
To support this change, starting February 17, 2020, Application Gateway (all the SKU types) will inject another cookie called ApplicationGatewayAffinityCORS in addition to the existing ApplicationGatewayAffinity cookie. The ApplicationGatewayAffinityCORS cookie has two more attributes added to it ("SameSite=None; Secure") so that sticky session are maintained even for cross-origin requests.
Cause
- This problem occurs because the load balancer redirects the SAML Response to a different node that doesn't have the ID attribute stored in the local session. When the SP sends
SAMLRequest
(step 2 above), it also saves the ID attribute of the Request in the local session. When SP receives the SAML Response (step 6 above), it verifies that theInResponseTo
attribute is equal to the ID that it has saved. Since it doesn't have the ID attribute saved in the session, it can't check that the IDs are the same. This results in the exception written in the logs.- You can enable debugging level for the packages below to confirm the SAML session is being created in one node and the response being sent to the other.
- com.onelogin
- com.atlassian.plugins.authentication
- You can enable debugging level for the packages below to confirm the SAML session is being created in one node and the response being sent to the other.
- The bug JRASERVER-69598 - Getting issue details... STATUS can also be the cause for this issue. This happens when the user account contains specials characters (including hex codes not visible on UIs, such as no-break space " ").
- The SSO plugin is out of date.
- Custom JavaScript code injected in the DOM, via the announcement banner, custom fields descriptions or other ways, can also cause this issue.
Solution
Cause 1
Here are possible reasons for this problem:
Your firewall or proxy deletes the ApplicationGatewayAffinityCORS cookie that is used by Azure Application Gateway to determine which node should process the request.
- Missing HTTPS address (ApplicationGatewayAffinityCORS can be sent over HTTPS only). That's either because of a misconfiguration (e.g. absence of HTTP-to-HTTPS redirection) or users entering an HTTP address.
- Missing session affinity.
- Other reason that might prevent ApplicationGatewayAffinityCORS from being sent.
- The SameSite cookie issue described here is happening.
Cause 2
Remove special characters from the affecter user name, you might need to collect a HAR file to analyze the SAMLResponse, which should show you the user name and any invalid characters.
Cause 3
Upgrade the SSO plugin.
Since this plugin is used by multiple products (Jira, Confluence, Bitbucket, etc.), install / upgrade the SSO for Atlassian Server and Data Center plugin to version 3.2.5/4.0.8/4.1.5 or higher depending on what version of the plugin your Atlassian product supports. If the app was bundled with your installation, then you do not need to update the app unless specifically directed to by Atlassian Support.