Active Directory usage in WCF Windows authentication - c#

We have a WCF service that uses Windows authentication (also with option AllowNtlm=true). The documentation says that Windows authentication uses Active Directory to authenticate the user but doesn't describe how, which I need to figure out. How does WCF uses Active Directory?
Here's the binding configuration we're using:
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="Windows" establishSecurityContext="false" />
</security>

If anyone interested, this is what I've found.
If you set your client credentials type to Windows, WCF uses something called Windows SSPI for Windows authentication.
Windows SSPI makes either Kerberos or CLDAP requests to domain controller. Example:
Kerberos: AS-REQ request
CLDAP:
searchRequest(..) "<ROOT>"
(&(&(&(&(&(&(DnsDomain=...)(Host=...))(User=...))(AAC=...))(DomainGuid=...))(NtVer=...))(DnsHostName=...))
Both can be observed using Wireshark (look for Kerberos5 or CLDAP protocol requests)

Related

Forwarding adfs login to Dynamics AX

I've created a new asp.net web application where I authenticate using adfs. I am then using this web application to talk to Dynamics AX.
Inside Dynamics Ax I've created classes and services and published them as "inbound ports" inside Dynamics AX to IIS.
I can add a service reference inside Visual Studio to the published service (through https and require domain credentials to use).
The Service Reference works fine and I can talk to Dynamics AX with my application using the following:
ServiceTestClient client = new ServiceTestClient();
client.ChannelFactory.Credentials.UserName.UserName = #"domain\user";
client.ChannelFactory.Credentials.UserName.Password = #"password";
Everything works just fine like this, I can read and write to/from AX.
But I would of course like to use the credentials I have already entered when I logged into the application through the adfs.
But my problem is that I don't really know how to do that. How can I forward the claims or tokens I've obtained to Dynamics AX?
I'm pretty sure I have to change the binding and clientCredentialtype I'm currently using inside AX.
Once I add a service reference inside Visual Studio I get the following inside web.config:
<basicHttpBinding>
<binding name="serviceEndpoint">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
<binding name="BasicHttpBinding_ServiceTest">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
So the question is, what type of binding and clientcredentialtype should I be using inside AX?
And how do I add the adfs token/credentials to the client I create?
Perhaps I'm completely misunderstanding what to do, if so I'll happily accept pointers in the right direction.
If anyone ever needs an answer, I created an intermediate user in AD/DAX which has the rights to talk to the https binding, but has no access into DAX. I then set the call context to the user obtained from the adfs token.
So the intermediate user's / pass is stored in web.config and the user which authenticates through adfs is the one performing actions inside Dax.

basic authentication in IIS with basichttpBinding WCF issue

I have just put my webservice onto IIS 7 and I need to use basic authentication, I have set this up in IIS 7 by enabling it, however I am getting the common error:
the http request is unauthorized with client authentication scheme
'basic' the authentcation header received from the server was 'basic
realm' = "server address"
In my client I am using
binding.Security.Mode = ServiceModel.BasicHttpSecurityMode.TransportCredentialOnly
binding.Security.Transport.ClientCredentialType = ServiceModel.HttpClientCredentialType.Basic
With the same settings in the service
<basicHttpBinding>
<binding name="binding1">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" />
</security>
/binding>
</basicHttpBinding>
I see that a lot of solutions to this is to use a different security mode like transport which uses HTTPS and a certificate instead of HTTP. I dont want this, so is there anyway of solving this without HTTPS?
Thanks

Windows WCF Service using HTTPS

I have a working WCF service that I am trying to add SSL security too. I followed tutorials for creating the dev certificates and I think i got all that set up; however, when I install and try to start my service, its failing without an error. I am using the installutil [servicename.exe] and the service gets installed. Then I try to start the service and it wont start. The only changes I made in the previously working app config are below:
I added Transport Security via the following:
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None" realm="" />
</security>
I changed the base address from "http://localhost/service" to "https://localhost/service"
and I added a service behavior to allow httpsGets via the following:
<serviceMetadata httpsGetEnabled="true" />
I wish I had more details on the error but basically it just says the windows service cannot be started, and that makes it really hard to troubleshoot. Any advice or tips would be helpful.
Thanks in advance!!!

WCF client with proxy settings set to "Use automatic configuration script"

I'm currently developing an application that needs to communicate with a webservice on the internet. Internet explorer is until know the only application that is connecting to the internet through a proxy server.
The proxy settings are setup to "Use automatic configuration script".
I have kept the default setting
<binding useDefaultWebProxy="true" />
And additionally set
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" proxyCredentialType="Basic"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
But no luck. I keep getting "(407) Proxy Authentication Required."
I have done some Google-ing, but the solutions do not seem to fit my situation.
Short update:
The application should run with the default user credentials, and use those credentials
through NTLM to authenticate with the proxy. But even when I set the client to do that it doesn't seem to help.
Keep the <binding useDefaultWebProxy="true" /> setting, and make sure useDefaultCredentials is set to true in your app.config file (this setting is false by default):
<system.net>
<defaultProxy useDefaultCredentials="true"/>
</system.net>
For more information, see my blog post "Using HTTP Proxy Servers".
I can't give you any background on why but setting:
<binding useDefaultWebProxy="false" />
Works for me in my current environment when getting your exact error.
Everyting in Windows seems to use the IE-configurable internet settings which include the default proxy. Internet explorer fixes this up for you neatly when running but if you try to retrieve the service wsdl or so using Firefox I´m guessing you would end up having a user login prompt.
In any case, try to false the default proxy.
Remember that kerberos authentication does not work very well across different firewalls. Many organizations have setup up their proxy to use AD for authentication and will only allow the proxy to access internet sites. This setup does not work well for web services and I suspect this is your problem.

Using WCF to consume service and receieving varying errors depending on binding configuration

I am attempting to consume an intranet web service with WCF. I added reference to the service via the Add Service Reference feature in VS2008. In doing so I was prompted for network credentials to access the service which I provided and the service reference was added.
I then wrote some code that I would expect to fail as it doesn't pass credentials along with the call of the service:
FooServiceClient proxy = new FooServiceClient();
bool isValid = proxy.ValidateBar(baz);
When I use this code I receieve the exception:The HTTP request is unauthorized with client authentication scheme 'Negotiate'.The authentication header received from the server was 'Basic realm="Kerberos"'.Which is the same error I receieve when using either of the two code examples below.
FooServiceClient proxy = new FooServiceClient();
proxy.ClientCredentials.UserName.UserName = "USERNAME";
proxy.ClientCredentials.UserName.Password = "PASSWORD";
bool isValid = proxy.ValidateBar(baz);
or
FooServiceClient proxy = new FooServiceClient();
NetworkCredential creds = new NetworkCredential("USERNAME", "PASSWORD");
proxy.ClientCredentials.Windows.AllowedImpersonationLevel =
TokenImpersonationLevel.Identification;
proxy.ClientCredentials.Windows.AllowNtlm = false;
proxy.ClientCredentials.Windows.ClientCredential = creds;
bool isValid = proxy.ValidateBar(baz);
My gut tells me that I have the security mode configured incorrectly. According to the server manager the end point that I am attempting to bind to is looking for a Basic Http Credential via SSL. Which after reading about WCF-BasicHttp Transport Properties lead me to believe that I should use this configuration:
<security mode="Transport">
<transport clientCredentialType="Windows" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
Unfortunately, I continued to receive the same error.
Again, I am sure my troubles have to do with a configuration issue on my part as I've previously consumed this service in other projects with the outdated Add Web Reference.
You have to really understand what the endpoint on the other end is configured under. If it is self hosted and running under SSL then it should be Transport, but if its running under IIS with SSL then it could possibly be TransportWithMessageCredentials and the Transport credentials might be "None".
It is very tricky to get this to bind correctly.
As far as the Exception you are getting
The provided URI scheme 'https' is
invalid; expected 'http'. Parameter
name:
When you use TransportCredentialOnly you have to use HTTP binding rather than HTTPS, and I am sure you didn't change your endpoint address to HTTP because that's not what the service reference is.
What binding are you using for your intranet scenario? The recommended best practice would be NetTCP with transport security and Windows credentials (assuming all your callers are intranet-clients with an account in your corporate Active Directory)
That would avoid any of the http/https mess.
However, to host netTcp, you either needs WAS (Windows Process Activation Server) which is part of IIS7 and that only runs on Windows Server 2008 (Vista Server) or 2008 R2 (Win7 Server). Or you need to host your service yourself in a e.g. NT Service.
Lots of information still missing! Please update your question accordingly. Thanks!
The below WCF binding configuration ended up being the solution.
<security mode="Transport">
<transport clientCredentialType="Basic" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>

Categories