This article is the third in a series of MSDN articles on creating a claims-aware web service and consuming it from SharePoint Business Connectivity Services (BCS). In this article, you are going to enable federated HTTP binding for the web service and establish trust between the WCF Web service and the SharePoint 2010 Security Token Service (STS). The series consists of the following articles:
This blog is inactive.New blog: EricWhite.com/blogBlog TOC
Getting Started Building a WCF Web Service
Shows how to create a very simple web service using WCF. Shows how to host this web service using IIS.
Determining Caller Identity within a WCF Web Service
Enhances the example so that the Web service can authoritatively report on the identity of its caller.
Establishing Trust between a WCF Web Service and the SharePoint 2010 Security Token Service (This post)
Configures the example developed in the previous article so that it uses a self-signed certificate to support a secure connection.
Consuming a Claims-Enabled WCF Web Service as an SharePoint 2010 External Content Type
Walks through the procedure for consuming a claims-enabled web service as a SharePoint 2010 External Content Type.
These articles were written by Saji Varkey, and Bin Zhang, and me. They will be published on MSDN sometime in the near future. After they are published, I will update these posts to point to the MSDN articles. Juan Balmori Labra was the program manager behind these articles.
Every SharePoint server installation has a built-in security token service. While it is possible to establish trust relationships to security token services that are not part of a SharePoint installation, by far the most common scenario is where you establish a trust relationship with the SharePoint STS, so this article focuses on that scenario.
To follow the procedures in this article, you need to have two servers set up. One of the servers needs to be running the WCF Web service that you developed in the first two articles in this series. The other server needs to have an installed, running instance of SharePoint 2010 server. I tested these procedures on a freshly installed instance of SharePoint 2010 server.
The following diagram shows the various actors in this scenario. The user connects to the web front end (WFE), which talks to the BDC Runtime. The BDC runtime calls to the SharePoint Security Token Service (STS) and the web service.
First, you need to create a self-signed certificate. This is an activity that you’ll regularly do as a developer, but when you actually deploy live, you will use a certificate issued by a certificate authority.
Note: If you already have a valid certificate issued by a certificate authority, then you can use that certificate instead of creating a self-signed certificate.
1. Start Internet Information Services (IIS) Manager. Click Start => Administrative Tools => Internet Information Services (IIS) Manager.
2. Select the machine in the Connections pane. Double-click Server Certificates.
3. Click Create Self-Signed Certificate.
4. The wizard will ask you to specify a friendly name. It is useful to give it a name that indicates the machine the certificate came from. In my case, I gave it the computer name for the computer that the Web service is hosted on.
1. In Information Services (IIS) Manager, right-click on the site containing the Web service application, and click Edit Bindings…
2. If you followed the procedures in this series, and started with a freshly installed operating system, you will see that there is no https binding. Click Add.
3. In the Add Site Binding dialog box, select https from the Type drop down.
4. Then select the SSL certificate that you just created.
5. Click the View… button to view details about the certificate. In particular, we are interested in the Subject property. Note the value of the Subject field, as you will require that value when connecting to the service using Microsoft SharePoint Designer 2010. You will need this value in step 9 of the procedure in Consuming a Claims-Enabled WCF Web Service as a SharePoint 2010 External Content Type.
6. Click OK, and then click Close.
Next, we need to establish trust between the computer consuming the web service (the SharePoint 2010 server), and the computer hosting the WCF Web service. To do this, you export the certificate you just created, copy it to the consuming computer (the SharePoint 2010 server), and import the certificate using a PowerShell cmdlet.
Procedure: Export the Self-Signed Certificate
Now that you have exported the self-signed certificate, you need to copy this certificate to the computer running SharePoint 2010 server, and import it into SharePoint.
Procedure: Establish Trust between the Web Service and the SharePoint Server
Note: you need to perform this procedure only if you are using a self-signed certificate. If you are using a certificate that is issued by certificate authority, you don’t need to follow the steps in this procedure. This procedure enables certificate validation when BCS calls to the web service using Https.
1. Copy the certificate file from the computer that hosts the web service to the computer that contains SharePoint server 2010.
2. The following steps need to be performed on the SharePoint server computer.Start a SharePoint 2010 Management Shell. Run as administrator.
3. Change directory to where you placed the certificate when you copied it from the Web service computer to the SharePoint server computer.
4. Read the certificate into a PowerShell variable, and then submit the certificate to the SharePoint trusted root authority. Enter the following into the PowerShell console, replacing ericwhit209.cer with the name that you gave the certificate when you exported it and copied it.$cert = Get-PfxCertificate .\ericwhit209.cerNew-SPTrustedRootAuthority -Certificate $cert -Name ericwhit209
After the certificate is submitted, the cmdlet will output something along the lines of the following.
You can see the issuer, its range of validity, and more.
Now that https has been bound, you can update the Web.config for the WCF Web Service to use it. But before you can update the Web.config, you need to determine the thumbprint of the SharePoint Security Token Service certificate on the SharePoint Server computer.
Procedure: Determine thumbprint of the SharePoint Security Token Service certificate.
This procedure and the procedure following this procedure are what actually establishes trust between the SharePoint STS and the web service.
3. The certificate that we’re interested in is the top one that is issued to SharePoint Security Token Service. Double-click on it.
4. In the next step, you need to copy the thumbprint of the certificate to the clipboard. There is a tricky part to this step. If you copy the first apparent ‘space’ in the text box, you will be copying an invisible byte order mark (BOM) to the clipboard at that location in the string. You must be careful to select the string of hex digits without selecting that first character.
Copy the thumbprint from the Certificate dialog box to the clipboard.
Copy and save this thumbprint so that you can paste it into the Web.config for the Web service.
Procedure: Replace Web.config for the Web service
Open the project for the Web service in Visual Studio. Replace Web.config with the contents of the following listing. There are four values that you will need to update values in this Web.config.
1. Update the endpoint URL for the SharePoint Security Token Service. You need to update only the machine name. Given the machine name, the endpoint URL for the SharePoint security service is well-known.
2. Update the metadata discovery URL for the SharePoint security service. As with the endpoint URL, you need to update only the machine name.
3. Update the thumbprint for the SharePoint security service with the value that you determined earlier in this article.
4. Update the name of the issuer token. This name needs to be unique among the trusted issuers in the issuer name registry. For the purposes of this article, use the machine name of the computer that is hosting the WCF web service.
Download a Clipboard Friendly Version of this Web.config
xmlversion="1.0"?> <configuration> <configSections> <sectionname="microsoft.identityModel" type="Microsoft.IdentityModel.Configuration.MicrosoftIdentityModelSection, Microsoft.IdentityModel, Version=184.108.40.206, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </configSections> <system.serviceModel> <diagnostics> <messageLogginglogEntireMessage="true" logMalformedMessages="true" logMessagesAtTransportLevel="true" /> </diagnostics> <services> <servicebehaviorConfiguration="CustomersService.Service1Behavior" name="CustomersService.Customers"> <endpointaddress="" binding="ws2007FederationHttpBinding" contract="CustomersService.ICustomers" bindingConfiguration="Customers_ws2007FedHttpBinding"> <identity> <dnsvalue="localhost" /> </identity> </endpoint> <endpointaddress="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> </service> </services> <behaviors> <serviceBehaviors> <behaviorname="CustomersService.Service1Behavior"> <federatedServiceHostConfigurationname="CustomersService.Customers"/> <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --> <serviceMetadatahttpGetEnabled="true"/> <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> <serviceDebugincludeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <bindings> <customBinding> <bindingname="AsymmetricWindowsHttpBinding"> <securitydefaultAlgorithmSuite="Basic256Sha256" authenticationMode="SspiNegotiated" requireDerivedKeys="true" securityHeaderLayout="Strict" includeTimestamp="true" keyEntropyMode="CombinedEntropy" messageProtectionOrder="SignBeforeEncryptAndEncryptSignature" messageSecurityVersion="WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10" requireSecurityContextCancellation="true" requireSignatureConfirmation="false"> <localClientSettingscacheCookies="true" detectReplays="true" replayCacheSize="900000" maxClockSkew="00:05:00" maxCookieCachingTime="Infinite" replayWindow="00:05:00" sessionKeyRenewalInterval="10:00:00" sessionKeyRolloverInterval="00:05:00" reconnectTransportOnFailure="true" timestampValidityDuration="00:05:00" cookieRenewalThresholdPercentage="60" /> <localServiceSettingsdetectReplays="true" issuedCookieLifetime="10:00:00" maxStatefulNegotiations="128" replayCacheSize="900000" maxClockSkew="00:05:00" negotiationTimeout="00:01:00" replayWindow="00:05:00" inactivityTimeout="00:02:00" sessionKeyRenewalInterval="15:00:00" sessionKeyRolloverInterval="00:05:00" reconnectTransportOnFailure="true" maxPendingSessions="128" maxCachedCookies="1000" timestampValidityDuration="00:05:00" /> <secureConversationBootstrap /> </security> <binaryMessageEncodingmaxReadPoolSize="64" maxWritePoolSize="16" maxSessionSize="2048"> <readerQuotasmaxDepth="32" maxStringContentLength="8192" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" /> </binaryMessageEncoding> <httpTransportmanualAddressing="false" maxBufferPoolSize="524288" maxReceivedMessageSize="65536" allowCookies="false" authenticationScheme="Anonymous" bypassProxyOnLocal="false" decompressionEnabled="true" hostNameComparisonMode="StrongWildcard" keepAliveEnabled="true" maxBufferSize="65536" proxyAuthenticationScheme="Anonymous" realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false" useDefaultWebProxy="true" /> </binding> <bindingname="AsymmetricCookieHttpsBinding"> <securityauthenticationMode="IssuedTokenOverTransport" defaultAlgorithmSuite="Basic256Sha256" messageSecurityVersion="WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12"/> <binaryMessageEncoding> <readerQuotasmaxStringContentLength="1048576" maxArrayLength="2097152"/> </binaryMessageEncoding> <httpsTransportmaxReceivedMessageSize="2162688" authenticationScheme="Anonymous" useDefaultWebProxy="false"/> </binding> </customBinding> <ws2007FederationHttpBinding> <bindingname="Customers_ws2007FedHttpBinding"> <securitymode="TransportWithMessageCredential"> <messageissuedKeyType="AsymmetricKey"> <!-- UPDATE: the URL for the SharePoint security service --> <issueraddress="http://ericwhit210/_vti_bin/sts/spsecuritytokenservice.svc/windows" binding="customBinding" bindingConfiguration="AsymmetricWindowsHttpBinding"/> <!-- UPDATE: the metadata URL for the SharePoint security service --> <issuerMetadataaddress="http://ericwhit210/_vti_bin/sts/spsecuritytokenservice.svc?wsdl"/> </message> </security> </binding> </ws2007FederationHttpBinding> </bindings> <extensions> <behaviorExtensions> <addname="federatedServiceHostConfiguration" type="Microsoft.IdentityModel.Configuration.ConfigureServiceHostBehaviorExtensionElement, Microsoft.IdentityModel, Version=220.127.116.11, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/> </behaviorExtensions> </extensions> </system.serviceModel> <microsoft.identityModel> <servicename="CustomersService.Customers"> <certificateValidationcertificateValidationMode="None"/> <audienceUrismode="Never"/> <issuerNameRegistrytype="Microsoft.IdentityModel.Tokens.ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, Version=18.104.22.168, Culture=neutral, PublicKeyToken=31bf3856ad364e35"> <trustedIssuers> <!-- UPDATE: the thumbprint that was issued by SharePoint Security Token Service --> <!-- UPDATE: the name of the issuer token --> <addthumbprint="ddbe98f4c2dbe6d78cec14d0d00ab890d15308f6" name="ericwhit210 "/> </trustedIssuers> </issuerNameRegistry> </service> </microsoft.identityModel></configuration>Download a Clipboard Friendly Version of this Web.config
At this point, the Web service is configured properly. In the next article, you will use SharePoint Designer 2010 to consume the Web service as an External Content Type.