SAML Assertion Error

Hi,
While connecting Intacct I am getting the error “Signature must be in the SAML Response Assertion”, I am using componentspace saml 2.0 for creating saml response and calling intacct sso_response.phtml, but unable to connect , can anybody know what is the reason or issue ?


Below is the C# code

private SAMLResponse CreateSAMLResponse() {
Trace.Write(“IdP”, “Creating SAML response”);

SAMLResponse samlResponse = new SAMLResponse();
//samlResponse.Destination = Configuration.AssertionConsumerServiceURL;
samlResponse.Destination = “<a href=“https://trial.intacct.com/ia/acct/sso_response.phtml";">https://trial.intacct.com/ia/acct/sso_response.phtml”;

Issuer issuer = new Issuer(”<a href=“https://localhost/“);”>https://localhost/”);
samlResponse.Issuer = issuer;

samlResponse.Status = new Status(SAMLIdentifiers.PrimaryStatusCodes.Success, null);

SAMLAssertion samlAssertion = new SAMLAssertion();
samlAssertion.Issuer = issuer;

Subject subject = new Subject(new NameID(User.Identity.Name));
//Subject subject = new Subject(new NameID(“rajneesh.gosavi@gmail.com”));
SubjectConfirmation subjectConfirmation = new SubjectConfirmation(SAMLIdentifiers.SubjectConfirmationMethods.Bearer);
SubjectConfirmationData subjectConfirmationData = new SubjectConfirmationData();
//subjectConfirmationData.Recipient = Configuration.AssertionConsumerServiceURL;
subjectConfirmationData.Recipient = "<a href=“https://trial.intacct.com/ia/acct/sso_response.phtml";">https://trial.intacct.com/ia/acct/sso_response.phtml”;
subjectConfirmation.SubjectConfirmationData = subjectConfirmationData;
subject.SubjectConfirmations.Add(subjectConfirmation);
samlAssertion.Subject = subject;




AuthnStatement authnStatement = new AuthnStatement();
authnStatement.AuthnContext = new AuthnContext();

authnStatement.AuthnContext.AuthnContextClassRef = new AuthnContextClassRef(SAMLIdentifiers.AuthnContextClasses.Password);

samlAssertion.Statements.Add(authnStatement);
AttributeStatement attributeStatement = new AttributeStatement();
//syncbase
//attributeStatement.Attributes.Add(new SAMLAttribute(“employee_id”, SAMLIdentifiers.AttributeNameFormats.Basic, null, “HR-21530”));
attributeStatement.Attributes.Add(new SAMLAttribute(“Company Name”, SAMLIdentifiers.AttributeNameFormats.Basic, null, “Sample cnnxhtf”));
attributeStatement.Attributes.Add(new SAMLAttribute(“name”, SAMLIdentifiers.AttributeNameFormats.Basic, null, “innominds”));
samlAssertion.Statements.Add(attributeStatement);

samlResponse.Assertions.Add(samlAssertion);

Trace.Write(“IdP”, “Created SAML response”);

return samlResponse;
}


// Send the SAML response to the SP.
private void SendSAMLResponse(SAMLResponse samlResponse, string relayState) {
Trace.Write(“IdP”, “Sending SAML response”);

// Serialize the SAML response for transmission.

XmlElement samlResponseXml = samlResponse.ToXml();

// Sign the SAML response.
X509Certificate2 x509Certificate = (X509Certificate2)Application[Global.IdPX509Certificate];

SAMLMessageSignature.Generate(samlResponseXml, x509Certificate.PrivateKey, x509Certificate);

IdentityProvider.SendSAMLResponseByHTTPPost(Response, "<a href=“https://trial.intacct.com/ia/acct/sso_response.phtml",">https://trial.intacct.com/ia/acct/sso_response.phtml”, samlResponseXml,null);

Trace.Write(“IdP”, “Sent SAML response”);
}

protected void Page_Load(object sender, EventArgs e) {
try {
Trace.Write(“IdP”, “SSO service”);

string targetURL = “”;// Request.QueryString[targetQueryParameter];

//if (string.IsNullOrEmpty(targetURL)) {
// return;
//}

Trace.Write(“IdP”, "Target URL: " + targetURL);

// Create a SAML response with the user’s local identity.
SAMLResponse samlResponse = CreateSAMLResponse();

// Send the SAML response to the service provider.
SendSAMLResponse(samlResponse, “”);

}

I follow the steps above to connect Intacct using LOWLevel (IdpInitiated to connect SP), but i am getting error “Signature must be in the SAML Response Assertion”

can anybody know what is the exact issue ?

From the error message it sounds like the service provider is expecting the SAML assertion to be signed rather than the SAML response. In your code you are signing the SAML response.
Which version of the ComponentSpace SAML2 product are you using?
http://www.componentspace.com/Forums/31/Determining-the-Component-Version-and-License
If you have a version from the last couple of years then you have the option of using the high-level SAML API which makes supporting SAML SSO much easier as a lot less application code has to be written.
If you use the low-level SAML API (what you’re currently using) then you need code similar to the following to sign the SAMl assertion.

// Serialize to the SAML assertion to XML for XML signature generation.
XmlElement samlAssertionElement =samlAssertion.ToXml();

// Sign the SAML assertion using your private key.
X509Certificate2 x509Certificate = newX509Certificate2(“idp.pfx”, “password”, X509KeyStorageFlags.MachineKeySet);
SAMLAssertionSignature.Generate(samlAssertionElement, x509Certificate.PrivateKey, x509Certificate);

// Add the signed SAML assertion to the SAMLresponse.
SAMLResponse samlReponse = new SAMLResponse();
samlReponse.Assertions.Add(samlAssertionElement);





Thanks for reply,

can you please provide complete steps so that i can work out on this, because if i use above code it is not working for me, may be i am missing some code.

Regards ,
Rajneesh.

Continue to below post, I required low-level api connect because i don’t want to use saml.config file as i my application is multi tenant , so i want to create dynamically saml.config using low level api code which component space saml 2.0 provided. Please let us know exact step and procedure using c#.net

Regards,
Rajneesh.

You can use the SAML high-level API in a multi-tenanted environment.
http://www.componentspace.com/Forums/51/SAML-MultiTenancy-Applications

The example code will need to be modified as required for your application.
The key points are that you have to serialize the SAML assertion to XML by calling the ToXml method.
You then sign the SAML assertion XML by calling SAMLAssertionSignature.Generate.
The signed SAML assertion XML is then added to the SAML response by calling Assertions.Add.
If you’re still having issues please let me know as well as the specifics of what’s going wrong. Please include your updated code.

Please find my C#.net code and correct it where ever required, so that i can test the application. I am using Componenspace saml 2.0 version , downloaded the sample code from developer site.

// Create a SAML response with the user’s local identity.
private SAMLResponse CreateSAMLResponse() {
Trace.Write(“IdP”, “Creating SAML response”);

SAMLResponse samlResponse = new SAMLResponse();
//samlResponse.Destination = Configuration.AssertionConsumerServiceURL;
samlResponse.Destination = “<a href=“https://trial.intacct.com/ia/acct/sso_response.phtml";">https://trial.intacct.com/ia/acct/sso_response.phtml”;

Issuer issuer = new Issuer(”<a href=“https://localhost/“);”>https://localhost/”);
samlResponse.Issuer = issuer;

samlResponse.Status = new Status(SAMLIdentifiers.PrimaryStatusCodes.Success, null);

SAMLAssertion samlAssertion = new SAMLAssertion();
samlAssertion.Issuer = issuer;





Subject subject = new Subject(new NameID(“rajneesh.gosavi@gmail.com”));
SubjectConfirmation subjectConfirmation = new SubjectConfirmation(SAMLIdentifiers.SubjectConfirmationMethods.Bearer);
SubjectConfirmationData subjectConfirmationData = new SubjectConfirmationData();
//subjectConfirmationData.Recipient = Configuration.AssertionConsumerServiceURL;
subjectConfirmationData.Recipient = "<a href=“https://trial.intacct.com/ia/acct/sso_response.phtml";">https://trial.intacct.com/ia/acct/sso_response.phtml”;
subjectConfirmation.SubjectConfirmationData = subjectConfirmationData;
subject.SubjectConfirmations.Add(subjectConfirmation);
samlAssertion.Subject = subject;




AuthnStatement authnStatement = new AuthnStatement();
authnStatement.AuthnContext = new AuthnContext();

authnStatement.AuthnContext.AuthnContextClassRef = new AuthnContextClassRef(SAMLIdentifiers.AuthnContextClasses.Password);

samlAssertion.Statements.Add(authnStatement);
AttributeStatement attributeStatement = new AttributeStatement();
//syncbase
//attributeStatement.Attributes.Add(new SAMLAttribute(“employee_id”, SAMLIdentifiers.AttributeNameFormats.Basic, null, “HR-21530”));
attributeStatement.Attributes.Add(new SAMLAttribute(“Company Name”, SAMLIdentifiers.AttributeNameFormats.Basic, null, “Sample cnnxhtf”));
attributeStatement.Attributes.Add(new SAMLAttribute(“name”, SAMLIdentifiers.AttributeNameFormats.Basic, null, “innominds”));
samlAssertion.Statements.Add(attributeStatement);



samlResponse.Assertions.Add(samlAssertion);

Trace.Write(“IdP”, “Created SAML response”);

return samlResponse;
}

// Send the SAML response to the SP.
private void SendSAMLResponse(SAMLResponse samlResponse, string relayState) {
Trace.Write(“IdP”, “Sending SAML response”);

// Serialize the SAML response for transmission.

XmlElement samlResponseXml = samlResponse.ToXml();


// Sign the SAML response.
X509Certificate2 x509Certificate = (X509Certificate2)Application[Global.IdPX509Certificate];

SAMLMessageSignature.Generate(samlResponseXml, x509Certificate.PrivateKey, x509Certificate);
IdentityProvider.SendSAMLResponseByHTTPPost(Response, "<a href=“https://trial.intacct.com/ia/acct/sso_response.phtml",">https://trial.intacct.com/ia/acct/sso_response.phtml”, samlResponseXml,null);

Trace.Write(“IdP”, “Sent SAML response”);
}

protected void Page_Load(object sender, EventArgs e) {
try {
Trace.Write(“IdP”, “SSO service”);

string targetURL = “”;// Request.QueryString[targetQueryParameter];

//if (string.IsNullOrEmpty(targetURL)) {
// return;
//}

Trace.Write(“IdP”, "Target URL: " + targetURL);

// Create a SAML response with the user’s local identity.
SAMLResponse samlResponse = CreateSAMLResponse();

// Send the SAML response to the service provider.
SendSAMLResponse(samlResponse, “”);

}

catch (Exception exception) {
Trace.Write(“IdP”, “Error in SSO service”, exception);
}
}

I’ve updated the code below.
However, I encourage you to take a look at the SAML high-level API. The code could then be reduce to a few lines plus some configuration.


// Create a SAML response with the user’s local identity.
private SAMLResponse CreateSAMLResponse() {
Trace.Write(“IdP”, “Creating SAML response”);

SAMLResponse samlResponse = new SAMLResponse();
//samlResponse.Destination = Configuration.AssertionConsumerServiceURL;
samlResponse.Destination = “https://trial.intacct.com/ia/acct/sso_response.phtml”;

Issuer issuer = new Issuer(“https://localhost/”);
samlResponse.Issuer = issuer;

samlResponse.Status = new Status(SAMLIdentifiers.PrimaryStatusCodes.Success, null);

SAMLAssertion samlAssertion = new SAMLAssertion();
samlAssertion.Issuer = issuer;

Subject subject = new Subject(new NameID(“rajneesh.gosavi@gmail.com”));
SubjectConfirmation subjectConfirmation = new SubjectConfirmation(SAMLIdentifiers.SubjectConfirmationMethods.Bearer);
SubjectConfirmationData subjectConfirmationData = new SubjectConfirmationData();
//subjectConfirmationData.Recipient = Configuration.AssertionConsumerServiceURL;
subjectConfirmationData.Recipient = “https://trial.intacct.com/ia/acct/sso_response.phtml”;
subjectConfirmation.SubjectConfirmationData = subjectConfirmationData;
subject.SubjectConfirmations.Add(subjectConfirmation);
samlAssertion.Subject = subject;



AuthnStatement authnStatement = new AuthnStatement();
authnStatement.AuthnContext = new AuthnContext();

authnStatement.AuthnContext.AuthnContextClassRef = new AuthnContextClassRef(SAMLIdentifiers.AuthnContextClasses.Password);

samlAssertion.Statements.Add(authnStatement);
AttributeStatement attributeStatement = new AttributeStatement();
//syncbase
//attributeStatement.Attributes.Add(new SAMLAttribute(“employee_id”, SAMLIdentifiers.AttributeNameFormats.Basic, null, “HR-21530”));
attributeStatement.Attributes.Add(new SAMLAttribute(“Company Name”, SAMLIdentifiers.AttributeNameFormats.Basic, null, “Sample cnnxhtf”));
attributeStatement.Attributes.Add(new SAMLAttribute(“name”, SAMLIdentifiers.AttributeNameFormats.Basic, null, “innominds”));
samlAssertion.Statements.Add(attributeStatement);


// Sign the SAML assertion.
XmlElement samlAssertionXml = samlAssertion.ToXml();

X509Certificate2 x509Certificate = (X509Certificate2)Application[Global.IdPX509Certificate];

SAMLAssertionSignature.Generate(samlAssertionXml, x509Certificate.PrivateKey, x509Certificate);

samlResponse.Assertions.Add(samlAssertionXml);

Trace.Write(“IdP”, “Created SAML response”);

return samlResponse;
}

// Send the SAML response to the SP.
private void SendSAMLResponse(SAMLResponse samlResponse, string relayState) {
Trace.Write(“IdP”, “Sending SAML response”);

// Serialize the SAML response for transmission.

XmlElement samlResponseXml = samlResponse.ToXml();


IdentityProvider.SendSAMLResponseByHTTPPost(Response, “https://trial.intacct.com/ia/acct/sso_response.phtml”, samlResponseXml, null);

Trace.Write(“IdP”, “Sent SAML response”);
}

protected void Page_Load(object sender, EventArgs e) {
try {
Trace.Write(“IdP”, “SSO service”);

string targetURL = “”;// Request.QueryString[targetQueryParameter];

//if (string.IsNullOrEmpty(targetURL)) {
// return;
//}

Trace.Write(“IdP”, "Target URL: " + targetURL);

// Create a SAML response with the user’s local identity.
SAMLResponse samlResponse = CreateSAMLResponse();

// Send the SAML response to the service provider.
SendSAMLResponse(samlResponse, “”);

}

catch (Exception exception) {
Trace.Write(“IdP”, “Error in SSO service”, exception);
}
}



Hi ,

Thanks for reply and modifying the code, Finally it is working for me . Once again thank you so much buddy.

Regards,
Rajneesh.