3

I have to create a Single Sign-On (SSO) for Salesforce. For authorization, I will be using user's mobile number with OTP. I have to only create a SAML response using Go once the OTP is verified.

I can see that there are a couple of libraries for that go-saml, gosaml, go-oauth and goauth for the Go Programming Language, but even after a couple of hours of searching, I couldn't decide which one is suitable for me. I don't have to implement complete IDP, I only have to dynamically create a SAML response.

I found the XML response template which I need to create from https://www.samltool.com/generic_sso_res.php. So I have to create SAML response like below:-

<?xml version="1.0" encoding="UTF-8"?>
<saml1p:Response xmlns:saml1p="urn:oasis:names:tc:SAML:1.0:protocol" IssueInstant="2020-02-26T17:32:05.200Z" MajorVersion="1" MinorVersion="1" Recipient="https://im--partial.my.salesforce.com" ResponseID="_34ae7ce8-5f7fbd4d">
    <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
        <ds:SignedInfo>
            <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
            <ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#dsa-sha1"/>
            <ds:Reference URI="#_34ae7ce8-5f7fbd4d">
                <ds:Transforms>
                    <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
                    <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
                </ds:Transforms>
                <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
                <ds:DigestValue>fxk4drd6yhVQrJCtdfvYOyYYGAM=</ds:DigestValue>
            </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>EsjQYhFsL+Xvcgg59AkZja....8INZrTwyfLmo4+NMyYViDX6Q==</ds:SignatureValue>
        <ds:KeyInfo>
            <ds:X509Data>
                <ds:X509Certificate>MIID0zCCA5GgAwIBAgIEF...XWlGzJ3SdBlgRsdFgKyFtcxE=</ds:X509Certificate>
            </ds:X509Data>
        </ds:KeyInfo>
    </ds:Signature>
    <saml1p:Status>
        <saml1p:StatusCode Value="saml1p:Success"/>
    </saml1p:Status>
    <saml1:Assertion xmlns:saml1="urn:oasis:names:tc:SAML:1.0:assertion" AssertionID="_7f959448-5dbf311f" IssueInstant="2020-02-26T17:32:05.200Z" Issuer="AXIOM" MajorVersion="1" MinorVersion="1">
        <saml1:Conditions NotBefore="2020-02-26T17:32:05.199Z" NotOnOrAfter="2020-02-26T17:33:05.199Z">
            <saml1:AudienceRestrictionCondition>
                <saml1:Audience>https://saml.salesforce.com</saml1:Audience>
            </saml1:AudienceRestrictionCondition>
        </saml1:Conditions>
        <saml1:AuthenticationStatement AuthenticationInstant="2020-02-26T17:32:05.199Z" AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:unspecified">
            <saml1:Subject>
                <saml1:NameIdentifier>rahul.satal@xyz.com</saml1:NameIdentifier>
                <saml1:SubjectConfirmation>
                    <saml1:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml1:ConfirmationMethod>
                </saml1:SubjectConfirmation>
            </saml1:Subject>
        </saml1:AuthenticationStatement>
    </saml1:Assertion>
</saml1p:Response>

Wherein I only need to update a couple of parameters like Assertion_Id, Issuer, Audience, Recipient, Subject, Not before/After date, Attribute Statement, etc. I am not sure if I need any library for this or can get a single script.

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Rahul Satal
  • 2,107
  • 3
  • 32
  • 53
  • I think, you not only need to update fields but also sign updated document. For that reason I would go for a library, as signing is not easy task - it requres number of steps (including well-known serialization method). But if you have library for signing XML documents and it is compatible with SAML, you could consiter composing document with some templating and then sign it with that library. I can not recomend any library. – Codringher Feb 27 '20 at 16:39
  • I have tried writing a script for generating a SAML response, but I was getting multiple errors while signing. So, I think using a library will be better in this case. – Rahul Satal Mar 01 '20 at 09:22

1 Answers1

1

This library appears to be a simple SAML library for Go that takes care of SAML Response generation as well as signing that Response.

I've also seen this done using "templates", where no SAML processing was actually done. A prepared block of text, with placeholders was opened, the placeholders replaced with the required text and the response sent.

saml1p:Response

could be a template with IssueInstant and ResponseID created at run time. e.g pseudo code would be:

String samlTemplate = loadSAMLTemplate()
  .gsub("__IssueInstant__", "2020-02-26T17:32:05.200Z")
  .gsub("__ResponseID__", "9421878f98")
  .gsub( ... and so on ...)

it's possible to do it that way, if not ideal and it only works if you only ever have a single Assertion.

You would use the above template and replace the substituable parts with placeholders, e.g.

<saml1p:Response
  xmlns:saml1p="urn:oasis:names:tc:SAML:1.0:protocol"
  IssueInstant="__IssueInstant__"
  MajorVersion="1"
  MinorVersion="1"
  Recipient="https://im--partial.my.salesforce.com"
  ResponseID="__ResponseID__">

to build up an XML SAML Response. You would have placeholders for AssertionID etc. Anything that needs to be unique per SAML Response would need a placeholder, with its content replaced at run time.

You then need to sign that Response. You can't do that by replacing stuff. You can only do it by digitally signing using XML Signature. You could use this library to do that. It's still coding the Response but you only have to work with the signature and not the entire SAML process.

So the workflow would be:

  • Create reusable SAML Response as a text template with PlaceHolders for each replaceable text.
  • Load the template, replace all the bits you need to replace. This is your SAML Response.
  • Use the XML Signature library to sign the SAML Response. This is what you send to the SP.
codebrane
  • 4,290
  • 2
  • 18
  • 27
  • Thanks @codebrane for the reply. As per your suggestion, I have created a template of the XML response and replacing the placeholders from it every time. The script is working fine and I am getting the SAML Response. But when I am validating the SAML XML response on the Salesforce XML validator then I am getting error - `The Signature in the response is not Valid`. You can check the Go code here - https://play.golang.org/p/tuwlGU9KeeT . I may be missing some steps or creating the signature from the wrong template. – Rahul Satal Mar 08 '20 at 07:47
  • that's well written, clear to follow code. I see you're signing the SignedInfo but that should be added by the signing library itself. You should only need to sign an element in the XML and the library will do the rest. This is how I start the signing in Java https://github.com/guanxi/guanxi-idp/blob/8e2dd6ca4fe69720bdec5c760d86353d28ff7391/src/main/java/org/guanxi/idp/service/saml2/WebBrowserSSO.java#L337 and then do the actual signing https://github.com/guanxi/guanxi-common/blob/0ea1fe644ca41a3dae0ab1be26f4ef80780acec6/src/org/guanxi/common/security/SecUtils.java#L127 – codebrane Mar 08 '20 at 09:22
  • Forgot to say, you don't include the ds:Signature block in the template. The signature library should add that during the signing process – codebrane Mar 09 '20 at 10:29