I cannot seem to authorize service contract operations based on the credentials of the user who is calling my WCF service.
Service Web.Config
<system.serviceModel>
<services>
<service name="WCFService.Service" behaviorConfiguration="DefaultServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8080/WCFService"/>
</baseAddresses>
</host>
<!-- Net.Tcp EndPoints-->
<endpoint address=""
binding="netTcpBinding"
contract="WCFService.IService"
bindingConfiguration="NetTcp_Secured"/>
<endpoint address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange" />
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="NetTcp_Secured">
<security mode="Transport">
<message clientCredentialType="Windows" />
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="DefaultServiceBehavior">
<serviceMetadata httpGetEnabled="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Client Web.Config
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="DefaultClientBehavior">
<clientCredentials>
<windows allowNtlm="true"
allowedImpersonationLevel="Delegation" />
<httpDigest impersonationLevel="Impersonation"/>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="NetTcpBinding">
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint
address="net.tcp://localhost:8080/WCFService/Service.svc"
binding="netTcpBinding"
bindingConfiguration="NetTcpBinding"
behaviorConfiguration="DefaultClientBehavior"
contract="TestWcfService.IService"
name="NetTcpBinding_IService">
</endpoint>
</client>
</system.serviceModel>
Service Code...
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public string GetCurrentPrinciple()
{
return "Windows Identity: " + WindowsIdentity.GetCurrent().Name + " \\ " +
"Thread Identity: " + System.Threading.Thread.CurrentPrincipal.Identity.Name;
}
I believe this is the reason why this attribute causes a security exception...
[PrincipalPermission(SecurityAction.Demand, Name = @"DOMAIN_NAME\User")]
The method can be called just fine across the service which makes me think that the security settings are ok. However, the above code, which runs in the service, always returns the name of the App Pool identity and not the identity of the user who called the service.
Doing the following in the immediate window of the service in a break point gives the following...
? WindowsIdentity.GetCurrent()
{System.Security.Principal.WindowsIdentity}
AuthenticationType: "Negotiate"
Groups: {System.Security.Principal.IdentityReferenceCollection}
ImpersonationLevel: Impersonation
IsAnonymous: false
IsAuthenticated: true
IsGuest: false
IsSystem: false
Name: "IIS APPPOOL\\DefaultAppPool"
Owner: {S-1-5-SAME-AS-BELOW-}
Token: 2300
User: {S-1-5-SAME-AS-ABOVE-}
So I am authenticated - I just don't have the callers name!
Both service and client are set to Windows Authentication. If I do this in the client...
protected void Page_Load(object sender, EventArgs e)
{
lblCurrentUser.Text =
"Current Website User: " + HttpContext.Current.User.Identity.Name;
}
... it returns the correct domain and and username so I know the client has correctly ascertained my Windows credentials via the browser.
I am just not sure what I am missing here as to why the service does not report the client credentials.