I have the following situation (outline):
Authorization Webservice
This service gets called and verifies (by executing the given business logic) whether a user is valid or not.
Custom Business Webservice
This is some webservice created for a business app, that internally calls the "Authorization Webservice" in order to verify the account which called the business webservice.
I realized this logic by making use of WCF service authorization in my "Custom Business Webservice". Basically I configured
<serviceAuthorization principalPermissionMode="Custom">
<authorizationPolicies>
<add policyType="MyCompany.Authorization.WCF.AuthorizationPolicy, MyCompany.AuthorizationDll"/>
</authorizationPolicies>
</serviceAuthorization>
The AuthorizationPolicy internally invokes the "Authorization Webservice".
The Problem
The problem is that I need to impersonate the caller of my "Custom Business Webservice". The client identity is the correct one, however the WindowsIdentity is that of the application pool user.
Note, impersonation works within the service itself if I use [OperationBehavior(Impersonation = ImpersonationOption.Required)] but it does not within the AuthorizationPolicy's Evaluate(...) method.
(I use Transport level security using windows authentication credentials, obviously)
Anyone has any hints on how I can impersonate the caller prior to entering the IAuthorizationPolicy.Evaluate(...) method??
It always again feels a bit strange, answering to my own questions, but for the sake of sharing what I got with others I'm going to post the "solution" here.
I'll try to make it short:
Impersonating in the IAuthorizationPolicy.Evaluate(...) is not possible. (S4U2Self may work, didn't test that since I didn't have that option)
As I already mentioned, impersonating the caller within the webservice operation worked by placing the [OperationBehavior(Impersonation = ImpersonationOption.Required)]. So calling my custom webservice for retrieving the principal as the first statement in my service operation would always work. I didn't like that approach however.
As an alternative I tried to find the latest possible point in the call chain of a WCF service operation where the impersonation finally worked. This is where I found the OperationInvoker.
The following diagram illustrates the sequence of dispatchings that are done before the call arrives at the actual operation (taken from here):
Parameter Inspection was too early, impersonation didn't yet work, but it luckily worked in the Operation Invoker. So by writing a custom operation invoker and wrapping everything into a custom operation behavior attribute I was able to elegantly solve the problem.
More info on an according blog post I wrote.
Related
Background
I'm building a two-tiered C# .net application:
Tier 1: Winforms client application using the MVP (Model-View-Presenter) design pattern.
Tier 2: WebAPI RESTful service sitting on top of Entity Framework and SQL Server.
If you would like more detail on the application I'm building, I gave a probably too thorough explanation here.
Current Development
Currently, I'm working on the Winforms client. Particularly, I'm trying to hash out a adequate implementation of the command pattern within this client. I was fortunate enough to stumble across this excellent blog post that outlines a solid command architecture. To complement that post, the author followed up by explaining how he separates queries from commands. After reading those blogs, it becomes very clear that my tier 2 (web api service) would greatly benefit from implementing both of these. The generic implementation allows for fantastic flexibility, testability, and extensibility.
Question
What is less clear to me is how I go about implementing these patterns on the winforms client side of things (tier 1). Do queries and commands continue to be considered separate here? Consider a basic action, such as a login attempt. Is that a query or a command? Ultimately, you need data back (user information on the server) from the web service, so that would make me think it is a query. What about another case, such as a request to create a new user. I understand that you would create a command object that stores the user information and send that off to the service. Commands are supposed to be fire and forget, but wouldn't you want some sort of confirmation from the service that the command was successful? Furthermore, if a command handler returns void, how would you tell the presenter whether or not the user creation request was successful?
At the end of the day, for any given UI task (say the user creation request), does it end up that you end up having a winforms client based query/command, as well as a web api service version of the command/query which handles the request on that end?
Do queries and commands continue to be considered separate here?
Yes, typically you would fire a command and if you need to update the UI after this action has been performed you would perform a query to get the new information. An example will make this clear.
Let's say you would assign a specific guard to a certain area. The only information the command (which is only a DTO) needs is the Id of the guard and the Id of the area. The associated CommandHandler will perform all tasks to handle this, e.g. removing that guard from another area, booking him as unavailable etc.
Now your UI would want to show the change. The UI has probably some kind of list with all guards and their assigned area. This list will be populated by a single GetActiveGuardsAndAreaQuery which will return a List<GuardWithAreaInformationDto>. This DTO could contain all kinds of information about all guards. Returning this information from the command is not a clean separation of concerns, because the atomic command handling could be very well used from a similar but slightly different UI, which will require a slightly different update of the UI information.
such as a login attempt. Is that a query or a command?
IMO a login attempt is neither. It is a cross cutting concern, an implementation detail that the data is hidden behind a secure connection. The application however should not be concerned with this detail. Consider using the application with another customer where you could host the WebApi service in and Active Directory domain where you can use Windows Authentication. In that case the user only has to login to his machine and the security is handled by the client and server OS while communicating.
With the patterns you're referring to this can be nicely done using a AuthenticateToWebApiServiceCommandHandlerDecorator which makes sure their are login credentials to serve to the service by asking the user in a modal form, reading it from a config file, or whatever.
Checking if the credentials worked can be done by performing a kind of a standard Query your application always needs such as CheckIfUpdateIsAvailableQuery. If the query succeeds the login attempt succeeded otherwise it failed.
if a command handler returns void, how would you tell the presenter whether or not the user creation request was successful?
While it seems that void doesn't return anything this is not really true. Because if it doesn't fail with some exception (with a clear message what went wrong!) it must have succeeded.
In a follow up of the mentioned blog posts #dotnetjunkie describes a way to return information from commands but make notice of the added comment on the top of post.
To summarize, throw clear exceptions from failed commands. You can add an extra layer of abstraction client side to handle this nicely. Instead of injecting a commandhandler directly into the different presenters you can inject an IPromptableCommandHandler which has only one open generic implementation at compile time:
public interface IPromptableCommandHandler<TCommand>
{
void Handle(TCommand command, Action succesAction);
}
public class PromptableCommandHandler<TCommand> : IPromptableCommandHandler<TCommand>
{
private readonly ICommandHandler<TCommand> commandHandler;
public PromptableCommandHandler(ICommandHandler<TCommand> commandHandler)
{
this.commandHandler = commandHandler;
}
public void Handle(TCommand command, Action succesAction)
{
try
{
this.commandHandler.Handle(command);
succesAction.Invoke();
}
catch (Exception)
{
MessageBox.Show("An error occured, please try again.");
// possible other actions like logging
}
}
}
// use as:
public void SetGuardActive(Guid guardId)
{
this.promptableCommandHandler.Handle(new SetGuardActiveCommand(guardId),() =>
this.RefreshGuardsList());
}
At the end of the day, for any given UI task (say the user creation request), does it end up that you end up having a winforms client based query/command, as well as a web api service version of the command/query which handles the request on that end?
No!
Client side you should create a single open generic CommandHandlerProxy which solely task is to pass the command dto to the WebApi service.
For the service side architecture you should read another follow up: Writing Highly Maintainable WCF Services which describes an server side architecture to handle this very nicely. The linked project also contains an implementation for WebApi!
I currently have a service which is secured by TransportWithMessageCredential over https. This works great! I now need to add a bit of granularity to some operations on this service.
Lets say I have this method public IEnumerable<Project> GetProjects() now I need to add an additional method which will limit the projection to projects which the current user has access.
Is using code like this:
var uid = System
.ServiceModel
.OperationContext
.Current
.IncomingMessageProperties
.Security
.ServiceSecurityContext
.PrimaryIdentity;
var returnProjects = context.Projects.Where(p => p.ProjectManager.Equals(uid.Name));
going to leave me vulnerable to any type of attack?
I think this should be fine, since WCF will hit my custom UserNamePasswordValidator first and "authenticate" the user, then the code I have above will "authorize" them to get only their projects. Is there a flaw in my thinking here?
No, that is perfectly valid thinking. This is exactly the way that we implement user-specific security (with the minor exception that we use FormsAuthentication for identifying the user).
Before each request is processed, we always check the user and if there is anything suspicious about the request, we throw an exception.
I am using the following attribute to implement impersonation on my WCF service, as I need to impersonate the client during the entire execution of the method:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
The problem is that I don't want the users to have rights on the local file system (as this would be a security hole), so I want my logging library to be able to write to the log file with the real credentials that the service is running under. Applying the impersonation just around the necessary code would be tedious and inelegant, as there are many places where it is required. It would be neater if I could temporarily switch it off with a few lines of code in my logging library. What is the simplest way to achieve this?
I've never used impersonation before, but can you just set [OperationBehavior(Impersonation = ImpersonationOption.NotAllowed)] on the logging methods?
The current situation is as follows:
We have an production .net 3.5 WCF service, used by several applications throughout the organization, over wsHttpBinding or netTcpBinding. User authentication is being done on the Transport level, using Windows integrated security. This service has a method Foo(string parameter), which can only be called by members of given AD groups. The string parameter is obligatory.
A new client application has come into play (.net 3.5, C# console app), which eliminates the necessity of the string parameter. However, only calls from this particular application should be allowed to omit the string parameter. The identity of the caller of the client application should still be known by the server because the AD group limitation still applies (ruling out impersonation on the client side).
I found a way to pass on the "evidence" of the calling (strong-named) assembly in the message headers, but this method is clearly not secure because the "evidence" can easily be spoofed.
Also, CAS (code access security) seems like a possible solution, but I can't seem to figure out how to make use of CAS in this particular scenario.
Does anyone have a suggestion on how to solve this issue?
Edit: I found another thread on this subject; apparently the conclusion there is that it is simply impossible to implement in a secure fashion.
sounds to me like you need to pull the security out into a seperate service ... go down a more federated route this way you can implement a handshake form of encryption using public and private keys to generate a secure session token in both situations.
this way you cna still get both windows a=uthentication and a custom solution in play whilst retaining your attributes on methods for security (I am assuming that you are implementing it this way.)
sounds like a fair bit of work though - I had to do this from scratch and ran into some cross domain / delegation issues. But I am sure the idea is good.
howver you will end up with a nice solid claims based secuirty model
You could get the callers Address:
RemoteEndpointMessageProperty clientAddress =
OperationContext.Current.IncomingMessageProperties[RemoteEndpointMessageProperty.Name]
as RemoteEndpointMessageProperty;
string address = clientAddress.Address;
My applciation works as follows
[user]----username/password/domain----->[WCF service]
then i access the domain server to see to which actual DB the user is associated,
after getting that, i validate the user in his actual DB(DB is per domain)
the problem is that i need a place to store the domain name for the following requests against the db.
for example,if the users calls a WCF service operation:
Test()
first the validation procedure is called, (WCF UserNamePasswordValidator) which validates the user password(which is sent as part of the header for REST or as part of the SOAP), and the next function to be called is the Test, but by then i cant tell the domain of the user(to actually serve the request agains that domain..)
I dont want to change the signature of each domain to
Test(string domain)
I cant simply access the headers since i expose the same methods both as REST and as SOAP and the authentication is different for each of them..(one is with headers as with Amazon S3 and the later is using the SOAP standard)
so basically i'm looking for a global, per call storage.(i want to avoid the Per-Call initiation method)
thanks.
EDIT:
Maybe i should use the ThreadStaticAttribute? will that work?
This will not work. You can't store anything in UserNamePasswordValidator. It even doesn't have access to OperationContext because it runs on different thread.
The way to do this is create custom message inspector and extract the information from custom message header to custom operation context extension as Frank mentioned.
WCF knows a Current OperationContext. You can write your own extensions for it. Unrelated to this issue, I used the same mechanics in this NHibernate Session management here, which may work in its concept for you as well. It accesses the InstanceContext, but the concepts are similar.