Retrieving the currently authenticated user in a WCF service - c#

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

Related

WCF, custom authorization with data being passed to service class

I wrote a UserNamePasswordValidator descendant for validation purpose (basicHttpBinding).
The problem is when I validate a user against back service I receive its identifier that I have to use in service class method. That turns out to be a huge problem... unless you know how to do it ...
Is there another authorization alternative that I will not have to pass userName / password in method header or even worse in method's parameters of the Service?
WCF service authentication and authorization can use UserNamePasswordValidator and IAuthorizationPolicy. Here's an article on how to do it. If not, try using IPrincipal.

What is common practices for wrong ClientCredentials?

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.

Why is it bad practice to secure MVC routes?

The MSDN is pretty clear about MVC Routing and Security:
The only supported way to secure an MVC application is to apply the AuthorizeAttribute attribute to each controller and use the AllowAnonymousAttribute attribute on the login and register actions.
However, I am considering the following approach:
First, I have implemented a custom Controller Factory that performs security checks based on information coming from our custom STS.
Among other information, the token issued by the STS contains claims describing all the MVC routes the user is allowed to access.
Then I check the user claims within the CreateController method:
public class SecuredControllerFactory : IControllerFactory
{
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
...
bool isAuthorized = principal.HasRequiredRight(verb, ressource);
...
}
}
This way we can configure and update security rules in a centralized manner, without redeploying our applications. Moreover, it fits the "convention over configuration" idea.
Is there something wrong with this approach? I don't see why it is considered a bad practice? Can someone exhibit a concrete security issue with this?
I guess it is bad practise because it breaks the Single Responsibility principle within the controller factory. The single responsibility of the controller factory should be to select and instantiate controllers.
I would question your reason for going with the controller factory approach:
This way we can configure and update security rules in a centralized
manner, without redeploying our applications.
This is a valid statement if you use the standard AuthorizeAttribute that specifies the allowed users/roles in code.
However, the recommended approach would be to derive from AuthorizeAttribute and implement your security rule logic in the derived class by overriding the protected AuthorizeCore() method. For example, it could look up permissions in a database so you could change them dynamically at runtime.
This also allows you to implement custom logic that gets called when the authorization check fails (HandleUnauthorizedrequest() method), which is presumably what you have to do in your custom controller factory when the authorization logic fails (e.g. redirect to a sign-on or error page?)
That way, you get the ability to change your security rules and manage them centrally without redeploying the whole application and you don't break the single responsibility of the ControllerFactory
ThinkTexture provide a good implementation in their identity model framework, as described here
http://leastprivilege.com/2012/10/26/using-claims-based-authorization-in-mvc-and-web-api/
This allows you to specify a Resource/Action and to encapsulate the authorization logic in a custom ClaimsAuthorizationManager in the usual WIF way. If you don't specify the resource and action explicitly in the attribute, the framework gets the values from the using the current HttpActionContext, which is nice.

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/

Categories