WCF Authentication using basicHttpBinding and custom UserNamePasswordValidator - wcf

My first question is, is it even possible to use a custom UserNamePasswordValidor with basicHttpBinding?
I have a asp.net web site using Forms authentication and a custom membership provider. I realise that I could use the built in System.Web.ApplicationServices.AuthenticationService to authenticate my client (a WPF app) but I don't want two service calls (one for auth service, one for logic).
So it seems that a custom UserNamePasswordValidator would be perfect for the job. In my client I can then have:
var service = new MyServiceClient();
service.ClientCredentials.UserName.UserName = "username";
service.ClientCredentials.UserName.Password = "password";
MessageBox.Show(service.SayHello());
I've seen this working with wsHttpBinding but ideally would like to test without an SSL certificate.
Alternatively, is it possible to make use of the AuthenticationService from within another WCF service?
To clarify what I mean above regarding authentication service, I don't want to have 2 service calls i.e:
if (authService.Login("username", "password"))
// then call my service
I know this a minor thing but the external developer of the client app is expecting just one service that takes the credentials and returns the required data.
Thanks,
Ben

check ClearUserName binding: http://webservices20.blogspot.com/2008/11/introducing-wcf-clearusernamebinding.html It should solve your problem.

I use UserNamePasswordValidator over basicHttpBinding on a couple of my current projects. It works great; however, like Brett Robi mentioned in the comments, you need to have your Security mode set to Message or TransportWithMessageCredentials in order for the validator to be called. These security modes require SSL through.
So in short - Yes you can over basicHttpBinding; however, only with SSL. Removing the security mode and SSL removes the credential validations from being called.

Related

Form Authentication on NetTcpBinding in WCF service

I am using WCF service, which have two endpoint WsHttpBinding and NetTcpBinding and the service is using Forms Authentication. Service is hosted on IIS 7.
This works perfectly with WsHttpBinding, but fails for NetTcpBinding.
It fails on below statement:
FormsAuthentication.SetAuthCookie("COOKIENAME", false);
And the exception is :
Object reference not set to an instance of an object.
Please share your ideas on this.
Forms Authentication requires cookies/session which is not supported by protocol itself.
So, Forms authentication can not implemented on NetTcpBinding of WCF service.
Option 1:
As an Alternative:
Add references to System.IdentityModel & System.IdentityModel.Selectors as well as the WCF assemblies.
Set the security mode to Message on your binding
Set the Message.ClientCredentialType to MessageCredentialType.UserName
Create a type derived from UserNamePasswordValidator and implement the only method. You should throw a SecurityTokenException if the user name / password pair does not validate.
On your service host instance's Credentials property, set:
UserNameAuthentication.UserNamePasswordValidationMode to UserNamePasswordValidationMode.Custom
UserNameAuthentication.CustomUserNamePasswordValidator to a new instance of your UserNamePasswordValidator-derived class.
Set a service certificate with ServiceCertificate.SetCertificate()
As for the client-side credentials dialog, you can either make one yourself and on your proxy set proxy.ClientCredentials.UserName.UserName & proxy.ClientCredentials.UserName.Password before you open the proxy / use it the first time. Or you can check out how you can implement the System.ServiceModel.Dispatcher.IInteractiveChannelInitializer to create your own interactive initialization UI.
Option 2:
Another Alternative this sounds more like what you want to do ..Passing FormsAuthentication cookie to a WCF service
Why did I provide an answer to an old post - because someone might be looking for an answer. Hope this helps.

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.

ASP.NET, SilverLight, WCF & Forms Authentication - How to configure endpoints?

I have this existing environment:
1) ASP.NET 3.5 web application
2) forms authentication with the SqlMembershipProvider
I need to add the following:
1) a Silverlight charting object embedded in a web page.
2) a WCF service to be consumed by:
a) the Silverlight component embedded in an authenticated
web page, as mentioned above
b) server-based WCF clients with certificate based authentication
My question is - what is the easiest/best way to configure the WCF endpoints for the Silverlight object to authenticate to the WCF service using the security context of the already logged-in user (via the page that’s hosting the Silverlight object) without having to use the user's username/password again?
I've researched a lot of the MSDN and Patterns & Practices material and I thought I had a decent grasp of many of the potential authentication scenarios. But I can't seem to figure out a way to tie them together for the scenario I've outlined. I've found other people posting similar questions to mine but none of the answers I've read seem to fully answer their questions either. (Maybe I'm making this harder than it needs to be?)
I would think that the solution would be to somehow use the authentication token/cookie generated in the asp.net form login and somehow pass that to the Silverlight object which then includes it in the WCF request. But I don't see how to configure the WCF endpoint to use that token.
(In some of my other projects I've implemented the server-to-server scenario in 2.b above using certificate-based authentication, so I'm not too worried about adding that to the current mix I've outlined.)
Thanks in advance for any insight or pointers to the path forward.
Terry
Thanks codemeit for trying to help but I finally figured out what I was doing wrong - it was pilot error.
In trying to configure the endpoints for my Silverlight app I was testing with an asp.net page. I finally realized that when I test that way, the client endpoint is no longer originating from the authenticated browser - the client endpoint is the IIS server which in turn executes the request against the WCF server endpoint. So the security context changes and HttpContext.Current.User.Identity is always empty at the WCF server endpoint.
Once I got my test SL app running in the browser, it automatically inherited the security context of the authenticated browser and then HttpContext.Current.User.Identity was correct and authenticated at the WCF server endpoint.
Have you tried to enable your WCF services with aspNet compatibility, then see if the following is true.
string currentUserName = HttpContext.Current.User.Identity.Name;
bool isLoggedIn = HttpContext.Current.User.Identity.IsAuthenticated;
if these properties are being populated with the expected values, then this is the one you are after.
To enable aspNet Compatibility
add to web.config
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
add to the service impl class
[AspNetCompatibilityRequirements
(RequirementsMode=AspNetCompatibilityRequirementsMode.Required)]
In this case, the endpoint would be using basicHttpBinding, and you could check the authentication at run time within WCF.

Basic Authentication with WCF REST service to something other than windows accounts?

Is there a clean way to expose a WCF REST service that requires basic authentication, but where we handle the actual validation of the username/password ourselves? It seems that when you tell WCF in config that you want to use basic authentication, it forces you to turn on basic authentication in IIS and IIS can only do basic authentication against window accounts.
The only hack we have found is to lie to WCF and tell it there is no security on the service and then do authentication outside of the WCF stack using a generic IHttpModule (which has a proprietary config file to indicate which URLs have which authentication/authorization requirements).
It seems like there should be a better way. Anyone have one?
The WCF REST Contrib library enables this functionality:
http://github.com/mikeobrien/WcfRestContrib
It also allows you to secure individual operations.
is the username and password set on the client like:
cc.ClientCredentials.UserName.UserName = ReturnUsername();
cc.ClientCredentials.UserName.Password = ReturnPassword();
Or are they embedded in the body of the REST message?
If the former, you can use a custom UserNamePasswordValidator:
http://msdn.microsoft.com/en-us/library/aa702565.aspx
If the latter, you can set the service to no security, and use a custom ServiceAuthorizationManager to validate the contents of the message:
http://msdn.microsoft.com/en-us/library/ms731774.aspx
Hope one or the other helps! I'd try to post sample code & config, but I'm # home and dont have access to code, which is all # work.
See Custom Basic Authentication for RESTful services. Pablo's approach uses the interceptor functionality that is provided via the REST starter kit to solve the problem. If you do not want to depend on the REST starter kit, then you can create your own service host and use the inteceptor functionality provided.
If you host it on IIS, using custom http module is the way to go. You can bring over the principal over to WCF side to do code access security. See HTTP Basic Authentication against Non-Windows Accounts in IIS/ASP.NET (Part 3 - Adding WCF Support). Also see Custom HTTP Basic Authentication for ASP.NET Web Services on .NET 3.5/VS 2008.
If you are not using IIS, you should be able to implement userNameAuthentication. See Finally! Usernames over Transport Authentication in WCF.
Yes absolutely there is a way. You need to configuring a custom userNamePasswordValidationMode value for your service and point it to a class with an overridden method that can inspect and validate the credentials provided. When making a RESTful call, these credentials when using Basic authentication in its proper form should be in the request header. With this custom method you can inspect the credentials and then authenticate the client to your service. No Windows accounts or domain even needed.
The nice thing is you can then take that security context to the next level and provide fine-grained authrization at the method level. You might have instances where a large pool of clients are able to access the service, but not all methods within (i.e. paid clients vs. unpaid). In this case you can also provide authorization at the method level as well if needed.
Below is a step-by-step solution (with too many steps to embed) by me that contains both the needed configuration and security required to have a complete solution. The problem is often Basic authentication is used without securing the Transport with a SSL certificate and this is bad. Make sure to follow all the steps and you will implement Basic authentication without the need of any type of Windows accounts or configuration on your WCF RESTful based service.
RESTful Services: Authenticating Clients Using Basic Authentication