If you are trying so set up Single Sign-On using Vanilla's SAML SSO plugin against your own authentication provider or a third-party authentication provider you will find that there are a many possible points of failure. SAML is a very secure method of authentication and, as such, requires a very precise configuration and is not necessarily easy to troubleshoot. This document tries to expose the sources of the pain points, and what can be done.
SAML Overview
SAML is an acronym for Security Assertion Markup Language. It is a protocol for exchanging user data securely between a Service Provider (in our case Vanilla) and an Identity Provider (either your authentication server or a third-party server that you are using). SAML delivers the data in XML document containing Assertions. Assertions are claims, or data, concerning the user being authenticated.
The Basic SAML 2.0 Flow
ONE: On a Vanilla site a user will click on the 'Sign In' prompt. The browser will be instantly 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 "SAML Request". The SAML Request is a compressed, base64encoded XML document that tells the Identity Provider which Service Provider is making the request.
TWO: 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 SAML Response, like the SAML Request, is a compressed, base64encoded, signed XML document with either an error message or, if successful, all the 'Assertions' (also known as 'Claims' or user data) for the user.
THREE: The Service Provider (Vanilla) will decode the SAML Response, read the Assertions, verify the signature and translate the Assertions into useable data for either starting a session for an existing (by matching the UniqueID or, if there isn't one, the Email in the Assertions with an existing user), or creating a new user.
For more information on how to configure your Vanilla SAML Single Sign On connection you should read this article.
Troubleshooting
You may want to ask your Customer Success Manager to turn on the DB Logger addon so that you can see the Event Logs. If you find there are too many logs, try filtering the Event Logs on saml_response
.
SAML Request
Your IDP will receive a SAML Request from us when a user initiates a log in from your Vanilla forum. It will be base64_encoded and gzdeflated without compression. Here is a sample of what we send:
<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>
In the above example:
- $id is a randomly generated string.
- $issueInstant is the timestamp (i.e. now).
- $destination is Sign In URL on your IDP as configured in the forum Dashboard.
- $returnURL is the entry point on the forum where the SAML Response will be sent (e.g. https://forum.mydomain.com/entry/connect/saml?authKey=my_saml_connection)
- $issuer is the EntityID from the forum Dashboard (applicationID).
SAML Response
To see what SAML Response your IDP is sending to your forum, go into the Event Log in the forum Dashboard and filter on "saml_response_received". Below is an example of a SAML response that is structured in a way that our system can parse and use:
<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>
Common Error Messages
"The SAML response was not valid."
This is a generic error that covers multiple possible points of failure. It could be:
- The signature could not be located in the Response.
- No References node was found in the Response. The Response node is expected to be found as a child of the SignedInfo node.
- Your Response has more than one set of Assertions. Vanilla expects everything to be the child of one Assertion node.
- Timing issues. SAML Responses MUST have 'NotBefore' and 'NotOnOrAfter' values that protect from replay attacks. Possibly your server's clocks are not properly synchronized.
"You are not allowed to GET."
- Your SAML Response should be POSTed to the entry endpoint. Any response sent using the GET protocol will be rejected.
"The SAMLRequest signature was not valid."
- The most common cause of this error is an invalid certificate configured in your forum Dashboard. See to verify your certificate see Invalid Certificate.
Invalid Certificate
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 certificate.crt
perform the following command:
openssl x509 -in cert.txt -text -noout
Missing Email or Name
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 on the forum.
Click on the Event Log link under Technical in the Dashboard's left hand menu (if you don't have one, contact support). Filter on "saml_response_received" to see what is being passed. Make sure the saml:Attribute Names are mapped properly in the SAML Addon. The Name attribute has to be an exact match. If this is what is being passed:
<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>
Then in the SAML Addon you would have to map the names like this: