Using Microsoft integrated windows authentication with WCF but without IIS - wcf

Is there a way to get the behavior of Microsoft Integrated Windows Authentication w/o having to deploy using IIS? We have our own standalone C#/WCF WebServer and we would like to add this functionality. We cannot use IIS as part of our deployment.

WCF is "self hosting". That's mean, you don't have to have an IIS in order to run it on the server (Depending on your implementations of of course). You can even run it on client's computers.
Look at this article for more information about WCF authentications:
Authentication and Authorization in WCF Services
And an example in this article:
Authenticate with a User Name and Password

You can set the ClientCredentialType
WebHttpBinding whb = ... ;
whb.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
and later get the WindowsIdentity with
WindowsIdentity identity = ServiceSecurityContext.Current.WindowsIdentity;

Related

Authenticate with Kerberos in .NET Web API

I need to implement solution Desktop Client + Application server (Web Service) in .NET.
The Client shall Authenticate against Active Directory (Kerberos Single Sign On) and forward its verified Active Directory identity to Web Service (NET Web API or WCF).
Web-service should verify that the Client is signed against Active Directory. Both computers (Client and server) are running in one AD domain.
I suppose that this can be implemented using WCF (see code here), but today NET Web API is preferred over Windows Communication Foundation. It is possible to implement it in ASP Web API as well?
Similar question not answered is here.
Yes, it is possible. The answer is here: https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/integrated-windows-authentication
The API can use Windows authentication. The authentication is handled by IIS, as long as you have your web.config setup right, as described in that article.
From your application, you just need to tell it to pass the Windows credentials by using the UseDefaultCredentials property:
HttpClientHandler handler = new HttpClientHandler() {
UseDefaultCredentials = true
};
HttpClient client = new HttpClient(handler);

Is delegation required to pass credentials between applications on the SAME server?

I have a Web API application and an MVC4 client application on the same web server. They are both configured for Windows Authentication. The client application has impersonation enabled.
When I run the client in Visual Studio, it successfully passes my windows credentials to the Web API.
When I hit the client on the web server, the Web API receives "NT AUTHORITY\NETWORK SERVICE" which I guess is coming from the application pool the client app is running in.
Client passes credentials as follows:
HttpClientHandler handler = new HttpClientHandler()
{
PreAuthenticate = true,
UseDefaultCredentials = true
};
HttpClient client = new HttpClient(handler);
So my question is...do I need delegation here?
The web server is not configured for this in Active Directory - but I thought as the applications are on the same server, that impersonation would be sufficient. I would turn delegation on but I need a system admin to do that - and have all sorts of hoops to jump through - so want to be sure that's what I need.
OK, in short, no - delegation was not required.
It turned out to be an impersonation issue. From what I'd read it sounded like that was what should be required since the applications are on the same server, but even though I thought I had configured it correctly, I was missing a crucial part. I needed to change two settings in aspnet.config:
<legacyImpersonationPolicy enabled="false"/>
<alwaysFlowImpersonationPolicy enabled="true"/>
More details here:
https://stackoverflow.com/a/10311823/1230905

WCF Data Services with Integrated Authentication issue

I have a web project that has Anonymous access and Integrated Windows authentication enabled. I built a WCF Data Service and since it allows only one authentication, I enabled Integrated authentication on the service. I am able to view the service in browser. However when I try to query the service for any Entity, it gives me Forbidden error. I tried to enable Anonymous access on service too, but it does not work.
Do I need to give it some other access or it is not possible to enable one authentication on the service itself keeping the project virtual directory as Anonymous and Integrated.
Update: I do no have any operations in my Data Service. For the entities, I have already set the "All" permission on all entities.
Only one authentication method is permitted on a WCF Data Service.
If you choose to go the Integrated Security route then you need to set the credentials after constructing the DataServiceContext.
Something like this would work for using the current user's Windows identity.
employeeEntities = new EmployeeDataService.EmployeeEntities(new Uri("http://.../employeedata.svc"));
employeeEntities.Credentials = CredentialCache.DefaultCredentials;

WCF -> IIS 7.0 Partial Trust Hosting (.svc) -> BasicHttpBinding -> Authentication (UserName / Password) - > ASP.NET Membership Provider -> No SSL

Basically my requirement is:
WCF Service Application Hosted on IIS 7.0 with Partial Trust
Endpoint exposed with BasicHttpBinding
Would like to enable basic Authentication (UserName / Password)
Would like to use ASP.NET membership for User Authentication
I don't want to setup SSL
I have seen some tutorials but they are talking about first enabling the SSL. I am able to create my sample WCF Service and Host is on IIS 7.0 with Partial Trust without any problem. Its just the Authentication part that I am struggling with.
Can anyone provide any assistance or point me to the place where relevant information can be found?
If you are using username / password over basichttpbinding without ssl, then the password is going over the network unencrypted.
I would recomend that you use SSL in this situation.
Yes you can use basic authenication with an asp.net membership provider, see:
http://custombasicauth.codeplex.com/
Actually, I have struggled with this setup over the last 3 months. Turns out this combination will not actually work. Most sites/blogs on the topic deal with making the connection to asp memebership for login and creation of the user context. This does work fine; even over SSL. But when you try to use wcf services with permission attributes and communicate witht them over basicHTTPBinding, it doesn't work. The user context is not sent with the method call. Most people i've talked to have pointed me towards using REST style services instead of WCF.
check out this article.
http://www.learn-silverlight-tutorial.com/SecuringSilverlightApplications.cfm

Identity of thread in self hosted WCF service when called from Web Application

I have a Windows Service that is self hosting a Wcf service, this Wcf service has a tcpBinding with default settings. The Windows service is running as LocalSystem.
The Wcf Service is referenced (default settings) by a Web application that is running in IIS 7.5 integrated pipeline within it's own application pool with its own identity.
Both are running on the same machine.
All is working fine, except that when in the Wcf Service when I check the identity of the current thread with:
Thread.CurrentPrincipal.Identity.Name
It returns the user of the Application Pool of the Web Application.. this is not what I expect. It looks like some sort of impersonation is going on in the Wcf service.
Is this standard behavior? I can't find any documentation on this.
And does it mean that when I try to access a database in the Wcf service i'm introducing a identity hop?
Edit, the config on service side:
Type serviceType = typeof(WcfService);
host = new ServiceHost(serviceType);
Binding tcpBinding = new NetTcpBinding( );
Uri tcpBaseAddress = new Uri("net.tcp://localhost:8001/Test");
host.AddServiceEndpoint(typeof (WcfService), tcpBinding, tcpBaseAddress);
host.Open();
On the client side:
NetTcpBinding tcpBinding = new NetTcpBinding(SecurityMode.Transport);
windowsService = new WindowsService.WcfServiceClient(tcpBinding, new EndpointAddress("net.tcp://localhost:8001/Test"));
I'm reading from Learning WCF by Michele Bustamante. I have used WCF for an application that I've refactored and we're interested in using WCF in new applications for the flexibility it offers. One of the downsides of WCF is that it can be tricky to use the .net attributes or .config files to get the settings just right. I have spent days tracking down issues with the WCF settings. I've even created automated tests that will check that my service runs the way it's supposed to.
In response to your question, Michele says very specifically in Chapter Seven that NetTcpBinding is secure by default, meaning that callers must provide Windows credentials for authentication. I believe that would explain why the thread appears to be running as the identity of the web service. This is to protect your service from being called by an unauthorized user.
I believe that the following quotation from pp. 419-420 will answer your question concisely. "If you are familiar with traditional .NET role-based security, you know that there is a security principal attached to each executing thread. That security principal holds the caller's identity, which may be tied to a Windows account or a custom database credential, and its roles."
That seems to state plainly that yes, this is standard behavior.
I believe that you can change the behavior through attributes and .config files. I recommend you get a good book on the subject. I spun my wheels in the sand a long time trying to get bits and pieces of information about WCF from the web.
To clearify:
I was checking the wrong property here. Because code would be executed under the WindowsIdentity.GetCurrent() identity.
By default this is NOT the same as the caller (which is in Thread.CurrentPrincipal.Identity). If you want this behaviour you can control this with:
host.Authorization.ImpersonateCallerForAllOperations = true;
and
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
We actually have integrated security set at the website, and then any calls from the website to the WCF service we wrap in:
using (((WindowsIdentity)HttpContext.Current.User.Identity).Impersonate())
{
That makes sure the credentials of the logged in user are passed through, rather than the IIS app pool credentials.
Works like magic!
More information is needed, but I'm guessing that it's somewhere in the configuration for the binding on either the server side or the client side that impersonation is enabled. When adding service references, svcutil.exe is VERY aggressive in setting EVERY possible binding property in configuration.
If you could provide more information for the configuration on the server and client side, it would be appreciated.