Troubleshooting SAML Connections - HL Vanilla Community
<main> <article class="userContent"> <p>When setting up single sign-on (SSO) using Vanilla's <strong>Security Assertion Markup Language</strong> (<strong>SAML</strong>) SSO plugin against your own authentication provider or a third-party authentication provider, you may encounter several possible points of failure. SAML is a very secure authentication method that requires a precise configuration, and is not necessarily easy to troubleshoot. This article discusses these pain points, and what can be done about them.</p><h2 data-id="saml-overview">SAML overview</h2><p>SAML is a protocol for exchanging user data securely between a <strong>Service Provider</strong> (in our case, Vanilla) and an <strong>Identity Provider</strong> (either your authentication server or a third-party server). SAML delivers the data in an XML document containing <strong>Assertions</strong>,<strong><em> </em></strong>which are claims, or data, about the user being authenticated.</p><h2 data-id="the-basic-saml-2.0-flow">The basic SAML 2.0 flow</h2><ol><li>In a Vanilla community, a user clicks the 'Sign In' prompt. Their browser is redirected to the sign in page of the Identity Provider that you have configured in the SAML addon in the Vanilla Dashboard with the GET variable <code class="code codeInline" spellcheck="false" tabindex="0">SAML Request</code>. The <code class="code codeInline" spellcheck="false" tabindex="0">SAML Request</code> is a compressed, base64-encoded XML document that tells the Identity Provider which Service Provider is making the request.</li><li>The Identity Provider presents the user with a Sign In form. Once the user has been authenticated, the Identity Provider POSTs back the Response to the ReturnURL. The <code class="code codeInline" spellcheck="false" tabindex="0">SAML Response</code>, like the <code class="code codeInline" spellcheck="false" tabindex="0">SAML Request</code>, is a compressed, base64-encoded, signed XML document with either an error message or, if successful, all the 'Assertions' (also known as 'Claims' or user data) for the user. </li><li>The Service Provider (Vanilla) will decode the <code class="code codeInline" spellcheck="false" tabindex="0">SAML Response</code>, read the Assertions, verify the signature, and translate the Assertions into useable data for either starting a session for an existing user (by matching the UniqueID or, if there isn't one, the Email in the Assertions with an existing user), or creating a new user.</li></ol><p>For more information on how to configure your Vanilla SAML SSO connection, see<a href="https://success.vanillaforums.com/kb/articles/32-saml-sso" rel="nofollow noreferrer ugc"> this article.</a></p><h2 data-id="troubleshooting">Troubleshooting</h2><p>You may want to ask Vanilla Support to turn on the <strong>DB Logger</strong> addon so that you can see the Event Logs. If you find there are too many logs, try filtering the Event Logs on <code class="code codeInline" spellcheck="false" tabindex="0">saml_response</code>.</p><h2 data-id="saml-request">SAML Request</h2><p>Your identity provider (IdP) will receive a SAML Request from Vanilla when a user initiates a log in from your Vanilla community. It will be <a href="https://www.php.net/manual/en/function.base64-encode.php" rel="nofollow noreferrer ugc">base64_encoded</a> and <a href="https://www.php.net/manual/en/function.gzdeflate.php" rel="nofollow noreferrer ugc">gzdeflated</a> without compression. Here is a, example of what we send:</p><pre class="code codeBlock" spellcheck="false" tabindex="0"><samlp:AuthnRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="$id" Version="2.0" IssueInstant="$issueInstant" Destination="$destination" IsPassive="false" ProtocolBinding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" AssertionConsumerServiceURL="$returnURL"> <saml:Issuer>$issuer</saml:Issuer> <samlp:NameIDPolicy Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" AllowCreate="true"></samlp:NameIDPolicy> <samlp:RequestedAuthnContext Comparison="exact"> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef> </samlp:RequestedAuthnContext> </samlp:AuthnRequest> </pre><p>In the above example:</p><ul><li><code class="code codeInline" spellcheck="false" tabindex="0">$id</code> is a randomly generated string</li><li><code class="code codeInline" spellcheck="false" tabindex="0">$issueInstant</code> is the timestamp (e.g., now)</li><li><code class="code codeInline" spellcheck="false" tabindex="0">$destination</code> is the Sign In URL on your IdP as configured in the forum Dashboard.</li><li><code class="code codeInline" spellcheck="false" tabindex="0">$returnURL</code> is the entry point in the Vanilla community where the SAML Response will be sent (e.g., https://forum.mydomain.com/entry/connect/saml?authKey=my_saml_connection)</li><li><code class="code codeInline" spellcheck="false" tabindex="0">$issuer</code> is the EntityID from the community Dashboard (applicationID).</li></ul><h2 data-id="saml-response">SAML Response</h2><p>To see what SAML Response your IdP is sending to your community, view the <strong>Event Log</strong> in the Vanilla Dashboard and filter on <code class="code codeInline" spellcheck="false" tabindex="0">saml_response_received</code>. Below is an example of a SAML response that is structured in a way that our system can parse and use:</p><pre class="code codeBlock" spellcheck="false" tabindex="0"><samlp:Response Destination="https://forum.mydomain.com/entry/connect/saml?authKey=my_saml_connection" ID="_3d8468fe676f01fe3ff3" InResponseTo="vf-16c181a13aa765aeca8bdf5f97901f702659aff4" IssueInstant="2020-04-10T03:43:47.667Z" Version="2.0" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">urn:mysamlapp.auth0.com</saml:Issuer> <samlp:Status> <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/> </samlp:Status> <saml:Assertion ID="_sgBT9hCKhQGiSpAbAc8dqeeEjw927PG1" IssueInstant="2020-04-10T03:43:47.635Z" Version="2.0" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"> <saml:Issuer>urn:mysamlapp.auth0.com</saml:Issuer> <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/> <Reference URI="#_sgBT9hCKhQGiSpAbAc8dqeeEjw927PG1"> <Transforms> <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/> <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/> <DigestValue>0LUaOC5zG5e9637598cdb0k6U=</DigestValue> </Reference> </SignedInfo> <SignatureValue>ZuUPV1EsWzg5Xl3/... ....fbOPyh0bidNFCT04aHEw==</SignatureValue> <KeyInfo> <X509Data> <X509Certificate>MIIDEzC.... .....4d7OM/4=</X509Certificate> </X509Data> </KeyInfo> </Signature> <saml:Subject> <saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">auth0|5604072ba0a9b7fd3c2c2939</saml:NameID> <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"> <saml:SubjectConfirmationData InResponseTo="vf-16c181a13aa765aeca8bdf5f97901f702659aff4" NotOnOrAfter="2020-04-10T04:43:47.635Z" Recipient="https://dev.vanilla.localhost/entry/connect/saml?authKey=saml"/> </saml:SubjectConfirmation> </saml:Subject> <saml:Conditions NotBefore="2020-04-10T03:43:47.635Z" NotOnOrAfter="2020-04-10T04:43:47.635Z"> <saml:AudienceRestriction> <saml:Audience>5e96388a49473</saml:Audience> </saml:AudienceRestriction> </saml:Conditions> <saml:AuthnStatement AuthnInstant="2020-04-10T03:43:47.635Z" SessionIndex="_MDo2sNieG_1LNk6n0n-jZ09XrZV1Vpe6"> <saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef> </saml:AuthnContext> </saml:AuthnStatement> <saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">auth0|5604072ba0a9b7fd3c2c2939</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">john.doe@gmail.com</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">John Doe</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">john.doe@gmail.com</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.auth0.com/identities/default/provider" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">auth0</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.auth0.com/identities/default/connection" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">Username-Password-Authentication</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.auth0.com/identities/default/isSocial" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:boolean">false</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.auth0.com/picture" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">https://cdn.myprofilepic.png</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.auth0.com/nickname" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">JohnnyBoy</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.auth0.com/sid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">NWU5NjM4NDJiOWM1ZQ</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.auth0.com/email_verified" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:boolean">false</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.auth0.com/clientID" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">5e96388a49473</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.auth0.com/updated_at" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:anyType">Fri Apr 10 2020 03:43:47 GMT+0000 (Coordinated Universal Time)</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.auth0.com/created_at" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:anyType">Thu Sep 24 2015 14:22:35 GMT+0000 (Coordinated Universal Time)</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </saml:Assertion> </samlp:Response> </pre><h2 data-id="common-error-messages">Common error messages</h2><h4 data-id="%22the-saml-response-was-not-valid.%22">"The SAML response was not valid."</h4><p>This is a generic error that covers multiple possible points of failure. It could be:</p><ul><li>The signature could not be located in the Response.</li><li>No References node was found in the Response. The Response node is expected to be found as a child of the SignedInfo node.</li><li>Your Response has more than one set of Assertions. Vanilla expects everything to be the child of one Assertion node.</li><li>Timing issues. SAML Responses MUST have <code class="code codeInline" spellcheck="false" tabindex="0">NotBefore</code> and <code class="code codeInline" spellcheck="false" tabindex="0">NotOnOrAfter</code> values that protect from replay attacks. It could be that your server's clocks are not properly synchronized.</li></ul><h4 data-id="%22you-are-not-allowed-to-get.%22">"You are not allowed to GET."</h4><ul><li>Your SAML Response should be POSTed to the entry endpoint. Any response sent using the GET protocol will be rejected.</li></ul><h4 data-id="%22the-samlrequest-signature-was-not-valid.%22">"The SAMLRequest signature was not valid."</h4><ul><li>The most common cause of this error is an invalid certificate configured in your Vanilla Dashboard. See <a href="https://success.vanillaforums.com/kb/articles/130-troubleshooting-saml-connections#invalid-certificate" rel="nofollow noreferrer ugc">Invalid Certificate</a>.</li></ul><h2 data-id="invalid-certificate">Invalid certificate</h2><p>The IdP Certificate configured in the SAML addon in the Dashboard MUST be a valid x509 Certificate. If your connections are failing, you can test your certificate using OpenSSL's command line utility. If your certificate is called <code class="code codeInline" spellcheck="false" tabindex="0">certificate.crt</code>, perform the following command: </p><pre class="code codeBlock" spellcheck="false" tabindex="0">openssl x509 -in certificate.crt -text -noout </pre><h2 data-id="missing-email-or-name">Missing Email or Name</h2><p>You may be passing the Email or Name in your SAML response, and yet users are still prompted to enter and Email or a Name to identify themselves in the community. </p><p>In the Dashboard's left-hand menu, click the <strong>Event Log</strong> link under <strong>Technical </strong>(if you don't see it, contact Vanilla Support). </p><ul><li>Filter on "saml_response_received" to see what is being passed. </li><li>Make sure the saml:Attribute Names are mapped properly in the SAML addon. </li><li>The Name attribute has to be an exact match. </li></ul><p>If this is what is being passed:</p><pre class="code codeBlock" spellcheck="false" tabindex="0"><saml:AttributeStatement xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/photo" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string"></saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">johndoe@gmail.com</saml:AttributeValue> </saml:Attribute> <saml:Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"> <saml:AttributeValue xsi:type="xs:string">JohnDoe</saml:AttributeValue> </saml:Attribute> </saml:AttributeStatement> </pre><p>Then, in the SAML addon, map the names like this:</p><div class="embedExternal embedImage display-large float-none"> <div class="embedExternal-content"> <a class="embedImage-link" href="https://us.v-cdn.net/6030677/uploads/311/CF9FJZW4G21J.png" rel="nofollow noreferrer noopener ugc" target="_blank"> <img class="embedImage-img" src="https://us.v-cdn.net/6030677/uploads/311/CF9FJZW4G21J.png" alt="Screen Shot 2020-04-08 at 12.33.31 PM.png" height="418" width="1958" loading="lazy" data-display-size="large" data-float="none"></img></a> </div> </div> <p><br></p> </article> </main>