What is common practices for wrong ClientCredentials? - c#

I have WCF service hosted on local IIS under SSL.
It seems to be working with SL client. But I stuck on user authentication.
I have login screen with textboxes for user name and password. Once user click on login button something must happen, but what? I saw a lot of examples where are setting up ClientCredentials is the last step. What I suppose to do if user enter bad credentials?
The exception is throwing after calling some operation. I get not a fault exception I had thrown, but CommunicationException.
public class UserAuthentication : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
{
throw new FaultException("Invalid user name or password");
}
}
Also ClientCredentials became read only after calling some operation. So I have to refresh it some how. I was thinking to replace endpoint behavior, but I'm not sure is it good idea.
So, basically my main question is: "What I suppose to do if user enter bad credentials?"

There are two kinds of authentication when it comes to WCF.
First, you can create authentication that works BEFORE the user gets all the way to your WCF interface. So, if you were using client certificates, User/Password or Forms authentication, these forms of authentication are declared within the WCF endpoint definition. These forms of authentication challenge the user (in effect) before they even get to your ping() function, exposing a WCF authentication event during which you can check the client's credentials. This is good because it can help stop hackers from bombing your WCF service with denial of service attacks since the full request never gets processes without authentication. An example can be found here: http://msdn.microsoft.com/en-us/library/aa354513.aspx.
The other method is more obvious: creating a normal WCF login() function, called by the client, during which the client program hands over the ID/password combination for a commplete check against your database or directory. This method, too, works with or without SSL. This is programmed like any other endpoint function ... nothing special here.
Both methods work with or without SSL. In either case, if the credentials are wrong, you can program the login() or authentication() routine to return any error or message your like, including a regular 401 Unauthorized error.

Related

I was able to pass username and password to webservice, but its not the way i need to secure from unauthorized user

This is another question I have about web services and securing them. I made a WCF Web Service and this is the code that I used...
[OperationContract]
[WebInvoke(Method = "GET")]
string myData(string name, string pass);
and this is the code that I use to interact with the web service...
public string myData(string a, string b)
{
if (a == "chris" && b == "pass")
return "You did it";
else
return "Nope";
}
I know this looks basic and I understand that I can add more functionality to it, but I don't think this is the way I need. It looks a little dirty to me.
If have a web service sitting on a server and if someone tries to use the service, I would like a pop up to ask for a username and password, so I can verify that they are in the database and they can proceed invoking the web service.
For this to be done, should I set up authentication in IIS to do this? I think I'm over thinking things.
My client just wants me to be able to secure the web service from unauthorized users. So That's what I am running into an issue with, I'm not sure the correct way to secure everything from unauthorized access, should (and how) this be done in IIS or just use the code that I provided.
I apologize if this kind of question has been asked a million times but the question is always different and so are the answers.
You should set your authentication method say forms authentication
and set you credential in request. Also better do it as HTTPS.

Account management

I'm completely new to WCF, so I'm sorry if this question sounds dumb..
I'd like to create a web service which will have account management. What I mean is that I have a client which can request the service to register a new account, login and link things to my account.
The accounts are stored in a SQL Server database.
I have this interface:
[ServiceContract]
public interface IService1
{
[OperationContract]
bool Register(string username, string password);
}
In the class that implements the service, the new account is entered into the database.
Is this the right way of doing this or should I do this another way? Also, what about security? Obviously the password will be hashed in the database (I'm creating the hash in the method), but sending it to the service in clear text doesn't seem like the correct way.
The second problem is that I'd like to use a custom UserNamePasswordValidator so the client can only call the methods after authenticating (see my previous question: Basic authentication and WCF)
The problem is that I'd like to create an exception: you have to log in for every method EXCEPT the register method. Is there a way to do this? Or should I create a seperate service just for this one method?
I hope someone can help me out.
Thanks!
In WCF you sould use Transport or Message security to secure your messages. Implementing this is enought for you to secure your sending password. The Transport security will provide you SSL/TSL, while the message security will secure your messages according to WS-Security specification. If you want you can use both of them. See http://msdn.microsoft.com/en-us/library/ms733137.aspx about advantages and disadvantages of message security and http://msdn.microsoft.com/en-us/library/ms729700.aspx about transport.
Before enabling your custom validation you MUST implement one of above security models. When you implement your custom validation, it is just another security check before opening your channel. For example you have a code with custom security
factory = new ChannelFactory<IContract>(binding,
new EndpointAddress(address, EndpointIdentity.CreateX509CertificateIdentity(serviceCertificate)));
factory.Credentials.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust;
factory.Credentials.UserName.UserName = "admin";
factory.Credentials.UserName.Password = "qwerty";
channel = factory.CreateChannel();
When you create such channel, there first will be certificate check, then in your service side it will call Validate() method. There you can check your login and pass and throw exception, if they are wrong. So factory.CreateChannel() will return you exception, and the channel will not be built, so you would not be able to call any of your service methods. If you want to use only one method, I would recommend you to use stand-alone service for registaration purposes only or you can try to put your registration logic into your Validate() method.

Intercept WCF Method Call and "Re-route" based on Authentication status

Was curious if there was a way to check if a user is authenticated before making a method call and then returning a custom object and not completing the call if they aren't. For example:
We set the user principal in the Application_PostAuthenticateRequest in the global.asax to the user making the request if they are authenticated or to an anonymous user if they aren't. Currently in all methods that require authentication we have something similar to the following code:
public Result GetSomeObject()
{
if (HttpContext.Current.Request.IsAuthenticated)
{
}
}
Bottom line: We want to be able to check IsAuthenticated BEFORE we let WCF get inside the method on methods that require authentication, and if true, continue, if not, return a Result object (JSON) with an authentication error.
What you need to develop is called ServiceAuthorizationManager in WCF. You can find more information about this on:
http://pieterderycke.wordpress.com/2011/04/07/implementing-restricted-access-to-a-wcf-service-with-the-serviceauthorizationmanager/
You can write a custom httpmodule to intercept the requests to the service layer and do the authentication in there.
This article may be a starting point for what you are looking for: http://pieterderycke.wordpress.com/2010/12/04/extending-wcf-creating-a-logging-component/

Retrieving the currently authenticated user in a WCF service

Today, I implemented a custom authentication provider for my WCF service. It is able to determine if my user is valid or not, just as expected.
So, now I have this class:
public class MyCustomValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
User apiUser = User.Login(userName, password);
// other logic goes here.
}
}
The behaviour of my application depends on what objects the User can access. So, how can I get my User object from here to my service class? There is no immediately obvious way that I can see, as my service class does not inherit from anything by default, unlike the ASP.NET controllers.
My first instinct is to set up a static parameter in MyCustomValidator and then read it from there, but I suspect that a race condition could occur. Can anyone confirm or deny my suspicions?
And most importantly: Is there a better way to do this? This is the first time I have ever used WCF, so I'm not aware of the best practices involved here.
Thank you for your time.
You want to pass some data from validator to service instance. It is bad because you can't do it. UserNamePasswordValidator is only for validating credentials (user name and password). You don't have access to anything from your validator. It even doesn't see current operation context because it runs in different thread. Using static parameter is not a sloution - as you mentioned it is race condition.
I think you need to implement custom authentication and authorization and it is not easy:
WCF Authorizaton, Custom Authorization, Custom credentials and validation

How to do Authentication between a webservice and a mobile phone?

I want to make a windows mobile 6 cellphone application. This application will talk to a web service that I want to make.
I don't know much about web services and programming app for phones so I got a couple questions.
How do I do authentication? Like my user loads up my app and goes to the login page. They type in their credentials. This gets sent to the server and authenticated. Now what do I send back? Is there some sort of FormsAuthentication?
After they log in do I have to keep doing checks to see if they are logged in? Like in asp.net mvc I have AuthorizeAttributes on all my tags. That way no one can just type in the url to that action method and be able to access it. But since this is an application I am not sure if they could (say) go your login form (first form) and then somehow, without logging in, get to your main form (the one after the login form).
Do web services have Authorize tags like asp.net mvc? Since I probably need something along those lines to ensure no one types in their web brower my webservice path and get access to all those methods I made in it.
I am making a asp.net mvc application right now and when the user types their credentials on my site. It is sent what I am guessing is clear text? to the server hashed and then checked. I know maybe one day when I can afford it maybe to get ssl to make it more secure.
So my question how about with sending the credentials from the phone to the server will it be less secure than what I have for my website right now? About the same? What can be done to make it more secure (is it SSL again?).
Thanks
You could also use SOAP headers to pass around user credentials or the authentication token. You can find an article on how to do this on Authentication for Web Services (using SOAP headers), but to summarize, you create a header class:
using System.Web.Services.Protocols;
public class AuthHeader : SoapHeader
{
public string Username;
public string Password;
}
You define a public property on the web service
public AuthHeader AuthenticationInfo;
and add some attributes to any web methods you would like to be only accessible to authenticated users:
[SoapHeader ("AuthenticationInfo", Required=true)]
[WebMethod]
public string HelloSecretWorld()
{
if(!(AuthenticationInfo.UserName == "Hello" && AuthenticationInfo.UserName.Password == "World"))
throw new AuthenticationException();
return "Hello World";
}
The client code would look like:
MyWebService ws = new MyWebService();
ws.AuthenticationInfo = new AuthHeader {Username = "Hello", Password = "World"};
Console.Out.WriteLine(ws.HelloSecretWorld());
This way you don't need to modify the signatures of the methods to add authentication.
i've had to address this issue several times in connecting from hand held (Windows Mobile) applications to web services. The solution i've used is to create a cookie based on a hash of the user's login name and IP address once the authentication process has succeeded. e.g. User ID and pwd matches persisted credentials on the server. You then pass this cookie back to the client which will then be passed along with all web service requests for the rest of the session. e.g. The first parameter of any web method is the cookie.
pseudocode:
string cookie = webServiceInstance.Authenticate("userName", "password");
double balance = webServiceInstance.GetBalance(cookie, someId);
Of course you do want to use SSL so as to avoid passing your user id and pwd in plain text.

Categories