0
votes

I'm setting up a SAML2 STS using Thinktecture IdentityServer and a WCF Service. The idea is to have Thinktecture supply the Assertions that are then used in the WCF Service.

Now, I have it running all fine with SAML 11 Assertions - urn:oasis:names:tc:SAML:1.0:assertion

The assertions are something like this:

<saml:Assertion MajorVersion="1" MinorVersion="1" AssertionID="_4e06770b-7fa0-425f-a4f3-263710f135d7" Issuer="https://localhost:123" IssueInstant="2014-01-18T16:16:38.099Z" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">
- <saml:Conditions NotBefore="2014-01-18T16:16:37.662Z" NotOnOrAfter="2014-01-18T16:26:37.662Z">
- <saml:AudienceRestrictionCondition>
  <saml:Audience>https://localhost:44300/</saml:Audience> 
  </saml:AudienceRestrictionCondition>
  </saml:Conditions>
- <saml:AttributeStatement>
- <saml:Subject>
- <saml:SubjectConfirmation>
  <saml:ConfirmationMethod>urn:oasis:names:tc:SAML:1.0:cm:bearer</saml:ConfirmationMethod> 
  </saml:SubjectConfirmation>...

Now, the requirement is to use SAML2, not the previous version. So changing the Token type in Thinktecture is simple and the new Assertion generates fine and get's picked by the client just fine.

New SAML2 Assertion:

<Assertion ID="_f9c48402-857a-4cc3-8525-1af307ef3a01" IssueInstant="2014-01-18T16:32:18.038Z" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
  <Issuer>https://localhost:123</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/2001/04/xmldsig-more#rsa-sha256" /> 
- <Reference URI="#_f9c48402-857a-4cc3-8525-1af307ef3a01">
- <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/2001/04/xmlenc#sha256" /> 
  <DigestValue>Nib1Bs9jy13unYShm08EcncqFsOS5IwVuWQ4tGoe4Pg=</DigestValue> 
  </Reference>
  </SignedInfo> ...

But when we then try to consume the WCF by passing the new asertion we get the exception:

  • XmlException: Cannot read the token from the 'Assertion' element with the 'urn:oasis:names:tc:SAML:2.0:assertion' namespace for BinarySecretSecurityToken, with a '' ValueType. If this element is expected to be valid, ensure that security is configured to consume tokens with the name, namespace and value type specified

Here's an excerpt of WCF web.config:

    ...
    <services>
          <service name="testsys.RFD.FormManager.RFDFormManagerService" behaviorConfiguration="testsys.RFD.FormManagerBehavior">
            <endpoint address="" binding="ws2007FederationHttpBinding" bindingConfiguration="ws2007FederationHttpBinding" contract="FormManager_PortType" />
          </service>
        </services>
        <protocolMapping>
          <!--<add scheme="http" binding="ws2007FederationHttpBinding" />
          <add scheme="http" binding="ws2007FederationHttpBinding" />-->
          <add binding="ws2007FederationHttpBinding" scheme="https" />
          <add binding="wsHttpBinding" scheme="https" />
        </protocolMapping>
        <bindings>
          <basicHttpBinding>
            <binding name="BasicHttpBinding_ILoggerService" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="524288" maxBufferSize="65536" maxReceivedMessageSize="65536" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true" messageEncoding="Text">
              <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
              <security mode="None">
                <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
                <message clientCredentialType="UserName" algorithmSuite="Default" />
              </security>
            </binding>
          </basicHttpBinding>
          <ws2007FederationHttpBinding>
            <binding name="ws2007FederationHttpBinding">
              <security mode="TransportWithMessageCredential">
                <message establishSecurityContext="false" issuedKeyType="BearerKey">
                  <!-- issuedTokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"-->
                  <issuerMetadata address="https://localhost:123/adfs/services/trust/mex" />
                </message>
              </security>
            </binding>
            <binding name="">
              <security mode="TransportWithMessageCredential">
                <message>
                  <issuerMetadata address="https://localhost:123/adfs/services/trust/mex" />
                </message>
              </security>
            </binding>
          </ws2007FederationHttpBinding>
          <wsHttpBinding>
            <binding name="RFD_Binding_HTTP" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00" bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true" allowCookies="false">
              <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
              <reliableSession ordered="true" inactivityTimeout="00:10:00" enabled="false" />
              <security mode="None">
                <transport clientCredentialType="None" proxyCredentialType="None">
                  <extendedProtectionPolicy policyEnforcement="Never" />
                </transport>
                <message negotiateServiceCredential="false" establishSecurityContext="false" />
              </security>
            </binding>
            <binding name="wsHttpBinding_IRFDFormManager" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
              <security mode="Transport">
                <transport clientCredentialType="None" />
              </security>
            </binding>
            <binding name="HttpBinding_IRFDFormManager" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647">
              <security mode="None" />
            </binding>
            <binding name="WSHttpBinding_IRESTFormManager">
              <security mode="None" />
            </binding>
          </wsHttpBinding>
    ...
        <behavior name="testsys.RFD.FormManagerBehavior">
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" httpsGetUrl="https://localhost:44300/RFDFormManager.svc" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <useRequestHeadersForMetadataAddress />
          <serviceCredentials>
            <serviceCertificate findValue="65A34BC197C2E1334D971613521D53D3B5B807FF" storeLocation="LocalMachine" storeName="My" x509FindType="FindByThumbprint" />
            <issuedTokenAuthentication certificateValidationMode="None">
              <!-- The X.509 certificate CN=localhost chain building failed. The certificate that was used has a trust chain that cannot be verified. Replace the certificate or change the certificateValidationMode. A certificate chain processed, but terminated in a root certificate which is not trusted by the trust provider -->
              <allowedAudienceUris>
                <add allowedAudienceUri="https://localhost:44300/" />
              </allowedAudienceUris>
            </issuedTokenAuthentication>
            <clientCertificate>
              <authentication certificateValidationMode="None" />
            </clientCertificate>
          </serviceCredentials>
          <serviceAuthorization principalPermissionMode="Always" />
          <serviceSecurityAudit auditLogLocation="Application" suppressAuditFailure="true" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="Failure" />
        </behavior>
...
<system.identityModel>
    <identityConfiguration saveBootstrapContext="true">
      <securityTokenHandlers>
        <add type="System.IdentityModel.Tokens.Saml2SecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
      </securityTokenHandlers>
      <audienceUris>
        <!-- <add value="https://localhost:44300/" />-->
        <add value="https://localhost:44300/" />
      </audienceUris>
      <!--Commented by Identity and Access VS Package-->
      <!--<issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry"><authority name="https://localhost:123"><keys><add thumbprint="7C399B2EA330F507902C81280E77407242FF6916" /></keys><validIssuers><add name="https://localhost:123" /></validIssuers></authority></issuerNameRegistry>-->
      <!--certificationValidationMode set to "None" by the the Identity and Access Tool for Visual Studio. For development purposes.-->
      <!--<certificateValidation certificateValidationMode="None" />-->
      <issuerNameRegistry type="System.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
        <trustedIssuers>
          <!--<add thumbprint="7C399B2EA330F507902C81280E77407242FF6916" name="https://localhost:123" />-->
          <add thumbprint="65A34BC197C2E1334D971613521D53D3B5B807FF" name="https://localhost:123" />
          <add thumbprint="15abb1aef64def860ca543f54fc8dee222d49b86" name="https://localhost:123" />
        </trustedIssuers>
      </issuerNameRegistry>
      <!--certificationValidationMode set to "None" by the the Identity and Access Tool for Visual Studio. For development purposes.-->
      <certificateValidation certificateValidationMode="None" revocationMode="NoCheck" />
      <!--revocationMode="NoCheck" should not be used to prod.-->
    </identityConfiguration>
  </system.identityModel>
  <system.identityModel.services>
    <federationConfiguration>
      <cookieHandler requireSsl="true" />
      <!--<wsFederation passiveRedirectEnabled="true" issuer="https://localhost:123/issue/wsfed" realm="https://localhost:44300" reply="https://localhost:44300" requireHttps="false" />-->
      <wsFederation passiveRedirectEnabled="true" issuer="https://localhost:123/issue/wsfed" realm="https://localhost:44300/" reply="https://localhost:44300/" requireHttps="true" />
    </federationConfiguration>
  </system.identityModel.services>
  ...

So what we're doing wrong ?

1

1 Answers

0
votes

I can't be bothered to go through your WCF configuration - especially since most of it is not related to the question.

You don't need to do anything "special" in WCF to consume SAML2 tokens - follows this simple sample - and then re-integrate into your application:

http://leastprivilege.com/2012/11/16/wcf-and-identity-in-net-4-5-external-authentication-with-ws-trust/