I have been writing some blogs entries (and even a Microsoft KB) about c2WTS, but the subject never exhausts. I was helping two different customers to troubleshoot issues with SharePoint Excel Services. In one of the cases the problem happened randomly and the error message was saying that the request to the external data (SQL) had failed because the request did not include a valid Kerberos header, but no reference to c2WTS in the ULS logs.
The other case was that some users could access Excel Services while others could not, this time there was an error in ULS logs pointing to access denied in c2WTS. Without explaining the internals of these two cases, one can say that in both cases c2WTS was working as expected but some other factor was impairing its use with SharePoint.
Before pointing at c2WTS as culprit of some SharePoint access error, look for these three tags in the ULS logs: g8g7, fvx8 or bz7l in Claims Authentication category (Medium).
This ULS entry would look like this:
07/14/2011 14:33:34.03 w3wp.exe (0x1144)0x1960 SharePoint Foundation Claims Authentication bz7l Medium SPSecurityContext.WindowsIdentity: Could not retrieve a valid windows identity for NTName='CONTOSO\jdoed', UPNemail@example.com'. UPN is required when Kerberos constrained delegation is used. Exception: System.ServiceModel.Security.SecurityAccessDeniedException: Access is denied. Server stack trace: at System.ServiceModel.Channels.ServiceChannel.ThrowIfFaultUnderstood(Message reply, MessageFault fault, String action, MessageVersion version, FaultConverter faultConverter) at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object ins, Object outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message) Exception rethrown at : at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at Microsoft.IdentityModel.WindowsTokenService.S4UClient.IS4UService_dup.UpnLogon(String upn, Int32 pid) at Microsoft.IdentityModel.WindowsTokenService.S4UClient.<>c__DisplayClass1.<UpnLogon>b__0(IS4UService_dup channel) at Microsoft.IdentityModel.WindowsTokenService.S4UClient.CallService(Func`2 contractOperation) at Microsoft.SharePoint.SPSecurityContext.GetWindowsIdentity().
SharePoint uses c2WTS to transform a claim identity into a valid Windows Identity Token. You cannot (for now) send a request to SQL Server or other data sources passing the claim. So, for internal users in Active Directory the claim will be mapped to a Windows Identity Token and that token will be used to access the resource. Since c2WTS only requires the UPN to generate a token, by default no one can access the service. To allow access you have to edit the .config file to add the groups and users to the allowed callers section.
SharePoint installs c2WTS as part of its pre-requisites as c2WTS is actually part of Windows Identity Foundation SDK. The configuration happens when you add the correspondent service in the farm. If everything is alright the service will be configured to start automatically (read my previous post on dependencies) under SYSTEM\NT AUTHORITY and will add the SharePoint local group WSS_WPG to the list of allowed groups in c2WTS. When adding SharePoint Excel Services, the domain account provided needs to be able to create Windows tokens in the c2WTS machine (the service only works with local requests) and it will be added automatically to WSS_WPG by SharePoint (you don’t have to do this). All this actions are necessary since once accessing the service you can impersonate a user by simply supplying the UPN claim. The input is the UPN string. The return is the (limited) Windows Token or an error.
Testing c2WTS configuration is not possible without some code. You have to be logged (or impersonating) an account that has rights to c2WTS. I suggest the account you used for Excel Services. To test using the same method that SharePoint does, you only need to call this static class in c2WTS:
WindowsIdentity wi = S4UClient.UpnLogon("firstname.lastname@example.org");
This static method will use WCF net.pipe (only local) to communicate with the real c2WTS service (I blogged about net.pipe and real pipes in a previous post). The full test of the complete configuration is a bit more complex. I have put together a sample application to perform all tests I could remember. The App looks like:
Start the Application as Administrator. If you want to impersonate Excel Account, change “User Login” to enable the Password field. By default the user will be the account running the application. If you want to continue with the interactive user, you will not need to enter password. For UPN you can enter any valid UPN claim (normally user@domain), if you want to test your own account you can choose to get UPN from logged user. If you want to impersonate another user or test if the current user can obtain tokens, please enter the UPN manually.
Testing Service c2WTS +- Service c2WTS found +- Service c2WTS is running +- Path of service: C:\Program Files\Windows Identity Foundation\v3.5\c2wtshost.exe +- Config File: C:\Program Files\Windows Identity Foundation\v3.5\c2wtshost.exe.config +- Service Logon: SYSTEM\NT AUTHORITY ----- start of config file ---- <?xml version="1.0"?> <configuration> <configSections> <section name="windowsTokenService" type="Microsoft.IdentityModel.WindowsTokenService.Configuration.WindowsTokenServiceSection, Microsoft.IdentityModel.WindowsTokenService, Version=184.108.40.206, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </configSections> <startup> <supportedRuntime version="v4.0" /> <supportedRuntime version="v2.0.50727" /> </startup> <windowsTokenService> <!-- By default no callers are allowed to use the Windows Identity Foundation Claims To NT Token Service. Add the identities you wish to allow below. --> <allowedCallers> <clear /> <add value="WSS_WPG" /> </allowedCallers> </windowsTokenService> </configuration> ----- end of config file ---- Retrieving security groups/users allowed to use the service from config file +- WSS_WPG Trying to login ......... Using current Windows Credentials c2WTS Service provided a valid Windows Token for: CONTOSO\cpajaro Now Verifying if user CONTOSO\rviana has rights on c2WTS +- User CONTOSO\rviana has access rights per group/user WSS_WPG. Other groups will not be checked *** Analysis Complete ***
You can download source and EXE here:
Please notice that since this is supposed to mimic SharePoint 2010, the App is 64-bits. Also be aware this application is provided “AS IS” with no guarantees. You need to accept the license to use it.