Monday, December 14, 2009

Troubleshooting Certificate Issues

For the past few days, we’ve been working on SAML 2.0 interoperability with OIOSAML and had to dig pretty deep to troubleshoot some issues we were running into. OIOSAML is an implementation of a SAML 2.0 compliant service provider for Java and J2EE applications which runs on Apache Tomcat. The issue wasn’t rocket science; however if we could not resolve it, federated authentication couldn’t be enabled for this application. The only error on the SP was:

Stack Trace:

Caused by: dk.itst.oiosaml.sp.model.validation.ValidationException: The response is not signed correctly

at com.sf.sfv4.authentication.saml2.extend.SFSAML2Response.validateResponse(SFSAML2Response.java:97)

at com.sf.sfv4.authentication.saml2.SFSAML2AssertionConsumerHandler.handleSAMLResponse(SFSAML2AssertionConsumerHandler.java:392)

... 45 more

A Google search on the error provided some possible leads to what the problem could be. However, one would immediately assume the issue was within the signing certificate due to the error. Yes, but you’d have to prove it.

When the SP consumes the SAMLResponse from an issuing IDP, the SP checks the IDP metadata file for a valid issuer; or Entity Id. This value should is stored in the local .xml of an STS within the EntityDescriptor element under the Entity ID attribute. For example, when publishing federation metadata in ADFSv2, these values are within the first element:

+ <EntityDescriptor wsu:Id="8e0d3ee9-0865-49c7-9c05-c8c64399757f" entityID="https://xxx.xxxx.com/Trust" xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">

Understanding what happens under the hood helps extremely in troubleshooting problems. When an SP (RP-STS) consumes an incoming SAMLResponse, it checks its policy store for a valid entity id, which then tells the token issuance service which certificate to validate the authenticity of the message by digital signature within the response or assertion sections of the SAML token.

However, in my scenario we never exchanged federation metadata other than manually providing parameters because the delivery method was IdP-initiated POST binding; therefore we had to prove the signature was bad. To do so, we basically wrote an application and published it as an RP to our IP-STS. The core functionality of signing an XML document can be referenced in Rebecca Croft’s blog, Apollo Jack using the System.Security.Cryptography namespace and System.Security.Cryptography.XML.

The SAMLResponse you consume can be displayed in a simple web form which you can write code to validate the SAML formatting and digital signature. The message will be encoded in Base64, therefore you’d need to decode it then check the signature.

To decode the message, you can use this method:

   1: public static String decodeMessage(string samlResponse)
   2:         {          
   3:             byte[] encodedDataAsBytes = System.Convert.FromBase64String(samlResponse);
   4:             string decodedSAMLResponse = System.Text.Encoding.UTF8.GetString(encodedDataAsBytes);
   5:             return decodedSAMLResponse;
   6:         }



To check a signature, you’d use the public key portion of the signing certificate and the SignedXml.CheckSignature method. From there, you can be insured your signing certificates should be validated on the RP side.

Sunday, December 13, 2009

Troubleshooting the MSIS7012

This summary is not available. Please click here to view the post.

Visualizing WS-Federation and SAML Profiles

SAML and WS-Federation within ADFSv2 may (or may not) introduce new concepts to the AD administrator. The immediate reaction may be, “I’m not a developer!” However, understanding the technology and how to implement it in the enterprise is no different than understanding Kerberos authentication protocols used by Active Directory. Travis Spencer published a very good slide deck which covers all the dance steps for both WS-Federation and SAML profiles. This is really good and helps visualize what happens behind all the federation acronyms and terms.

Animated Explanation of SAML

Friday, December 4, 2009

Implementing Single Sign-on with SalesForce.com

Getting single sign-on to work with Salesforce.com is pretty straightforward. They support both SAML 1.1 and now 2.0 formats using IdP-initiated POST Bindings. ADFSv2 Beta 2 currently does not support IdP-initiated SSO; although, from what I’ve heard will in RTM. So do get this working, you can do this through a custom STS.

All SalesForce.com requires is the Username or Federation ID to be passed as an assertion within the SAML token. This can be presented in either the Subject or as an Attribute value. The simplest method is to do it through the subject. On the Saleforce.com side, the federation single sign-on using SAML settings should be:

  1. SAML Enabled: yes
  2. SAML User ID Type: Username
  3. SAML User ID Location: Subject
  4. SAML Version: 2.0
  5. The public key of your Token Signing Certificate needs to be uploaded for validating token authenticity

Salesforce.com provides a validation tool to compare your generated SAML Response against the SSO settings on their server. This is pretty helpful in working through errors.

Getting a properly formatted SAML Response is probably the most important key for federated authentication to work. If there is something not standard or funky in the token, the STS that attempts to consume it will likely throw an error.

Below is a working SAML 2.0 token we’re using for Salesforce.com (note that I’ve removed my signature information):

<?xml version="1.0" encoding="UTF-8"?>
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" Destination=
https://login.salesforce.com ID="fhlaclpimfkgkjpbdijjcjahbhbldojhekcojnog" IssueInstant="2009-12-04T09:52:35Z" Version="2.0"><Signature xmlns="http://www.w3.org/2000/09/xmldsig#">……</Signature>
<saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">mycompany.com</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="baofcgcmpmmekakjkkbomfbefcfdljgbkbdifohm" IssueInstant="2009-12-04T09:52:35Z" Version="2.0">
<saml:Issuer>mycompany.com</saml:Issuer>
<saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified">ccalderon@mycompany.com</saml:NameID>
<saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
<saml:SubjectConfirmationData NotOnOrAfter="2009-12-05T09:52:35Z" Recipient=
https://login.salesforce.com />
</saml:SubjectConfirmation>
</saml:Subject>
<saml:Conditions NotBefore="2009-12-04T01:52:22Z" NotOnOrAfter="2009-12-05T09:52:35Z">
<saml:AudienceRestriction>
<saml:Audience>
https://saml.salesforce.com</saml:Audience>
</saml:AudienceRestriction>
</saml:Conditions>
<saml:AuthnStatement AuthnInstant="2009-12-04T09:52:35Z">
<saml:AuthnContext> <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef>
</saml:AuthnContext>
</saml:AuthnStatement>
<saml:AttributeStatement>
<saml:Attribute Name="ssoStartPage" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xmlns:xs="
http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">https://localhost/SalesForce.SSO/SSOLogin.aspx</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="logoutURL" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified">
<saml:AttributeValue xmlns:xs="
http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="xs:string">https://www.salesforce.com</saml:AttributeValue>
</saml:Attribute>
</saml:AttributeStatement>
</saml:Assertion>
</samlp:Response>