Custom authentication, authorization and session for WCF - wcf

I have read about various implementations of authentication and authorization for WCF, starting from reusing some built in .NET and WCF features and ending with completely custom implementations.
But there are so many factors to take into account, so I'm confused about how to implement it for my intranet business application project.
Here is what I need:
- WCF .NET 4.5 services will be hosted in IIS 7 or newer.
Most probably, ASP.NET compatibility will be disabled.
Protocol will be HTTP with BasicHttpBinding, but it might need binary serialization to minimize traffic.
WCF method will receive a custom session ID which will be checked against a user session object in a database. No .NET sessions are allowed in this project.
After receiving the ID, the service will read the corresponding user data (including authorization flags to see if the user is allowed to execute the current operation) and validate it. If data is invalid, an exception will be thrown and the WCF operation won't be executed. If validation succeeds, the identity of the user will be stored in a current operation context (and also current thread principal) so it can be accessed by various components during the WCF operation execution.
All the authentication&authorization should be done transparently before the execution of the WCF operation - without additional efforts from programmers who will create the WCF methods.
I need access to the WCF operation name being executed, when I perform the auth validations, so I can throw an exception if the user does not have permissions to execute the operation.
testers will use SoapUI, so they'll need to be able to pass the session ID through standard SOAP or HTTP headers.
Which would be the most straightforward way to implement my auth routines? Should I use a custom binding? Custom behavior? Some kind of a built-in request event handler (which one exactly, and will they work if ASP.NET compatibility is disabled)? Authorization policy (seems a bit overkill because I won't be using most of its built-in features anyway)? Something else?

You can try making use of Message Inspectors. Your session ID can be passed like a token through SOAP or HTTP Headers and will be inspected by WCF through your defined behavior before it executes the actual service operation.
You can check the articles here and here, particularly focusing on the IDispatchMessageInspector interface which offers the "AfterReceiveRequest" and "BeforeReceiveReply" methods.

Related

Session variable equivalent in OWIN self-host

I have a sample web API hosted in an OWIN process (self hosted, not in IIS). I get a JWT token in my controller and I want to be able to retreive it in another part of the application, a class that implements NserviceBus IMutateOutgoingTransportMessages. In my other web application POC (hosted in IIS), I used a simple session variable and it works just fine. But I'd like to know what would be the best way to do it in my new OWIN self hosted environment ? Static property in static class ?
This question is really broad and difficult to answer without detailed knowledge of your specific needs. Here's my interpretation of your issue:
You're already signing each request, perhaps storing the token in the browser sessionStorage (or even localStorage), but this does not suffice
You need to retrieve the token outside of or not in relation to any request cycle (if not, this is probably where you should be looking for answers)
Your application does not need to be stateless
Just one static property for one token in a static class would of course start breaking as soon as more than one request hits the application at the same time. Implementing a class that maintains a list of tokens may be a solution, although I can't tell what key you should use to identify each token. Interface details would vary depending on things like if you need to retrieve the token more than once.
Thread safety issues would apply to all handling and implementation of such a class. Using Immutable Collections and functional programming practices as an inspiration may help.
If lingering tokens poses a problem (and they probably would from a security perspective, if nothing else), you need to figure out how to make sure that tokens do not outstay their welcome, even if the cycle is for some reason not completed.
Seeing how you used Session as a solution in your POC, I'm assuming you want some similar behavior, and that one user should not be allowed to carry two tokens at the same time. You could store the tokens i a database, or even in the local file system, making maintenance and validity a separate issue all together.
There are implementations of cache-like functionality already available for OWIN self-hosted applications, and maybe one of those would serve as a shortcut to implementing everything yourself.
If this token business in fact is the only reason for introducing state in your application, then the best solution IMHO would be to rethink your architecture so that the application can remain stateless.
I'm facing a similar dilemma on a server i'm currently developing for a customer. My problem is that the server must make calls (and retain a live connection) with a legacy, multithreaded DLL, (aka the SDK).
I struggled to get this working on IIS with a regular Web API project. Failed badly since IIS recycles threads when it determines that a thread is going rogue... witch is what the SDK thread looks like in that perspective. Also, the SDK must be able to callback on the caller (client - single page app) and for this I'm using SignalR.
I then tried a multi-part system (single page + web api on IIS + WCF service for the SDK integration). But it is a real nightmare to manage because of the 2 way async communication that must occur between all apps. Again: failure.
So I reverted to a single self hosted OWIN + WebAPI service in a console app (for now). My problem is that some of the calls are lengthy and are processed in a worker thread. I managed to pass the SignalR client id in each ajax calls via headers. I can extract the id when in web api controller. But when the task goes async, I need to get the id (via an Unity injected service) from the class that manages the async task. This is where my problem is similar to yours. In IIS hosted apps, we have HttpContext. It is contextualized on each client calls, and follows any thread changes in the pipeline... But not in self hosted OWIN WCF apps...
I'm looking into Thread Local Storage, CallContext... and other means of keeping track of the original caller info during the lifecycle of the async call. I have read about OWIN pipeline, I can capture the info in a OWIN middleware... but how to safely keep that info for use in injected services? I'm still searching for an answer...
I was wondering if you have found a solution to this rather interesting problem ?
I prefer adding to your thread rather than start another parallel thread / SO question.

WCF wsHttpBinding : Avoiding multiple "ISSUE" calls while calling a web service using wsHttpBinding

I am using wsHttpBinding to call a WCF web service. When I look into the Fiddler2, I see multiple calls to the server before calling my actual OperationContract.
From this post I understood what these service calls are doing.
However, I want to know if there is any way to avoid these calls after first successful service call.
In my application, the web service is called so frequently that 3-4 additional calls per actual call to web service operation will not be accepted.
As you mentioend what happens is that WCF negotiates for a key. More details in here.
You have a few options:
set negotiateServerCredential and establishSecurityContext to false (this would require the client to have the server certificate out of band)
change to a different security mechanism (user name auth, or transport with SSL)
stay with the current situation. Once the negotiation is established no more extra calls are made. They happen once per proxy generation.
There is no way to make the negotiation process shorter. It consists of several message exchanges since this is the WS-Trust protocol.

WCF Sessions on Windows Azure

Our application architecture is as follows:
1) WCF service acts as a facade layer and sits on top of Service, Business Logic and Data Access layer
2) Every client, be it an MVC/ASP.NET, or any other type of application has a ClientTag that first needs to be authenticated and issued an "access token". This token is then passed by the client with every message into the Facade layer
3) The system will be hosted on Windows Azure
This would have been easy to implement with WCF sessions like so:
1) Client initiates a call to WCF to get the token (Client to WCF Session is established, thus every subsequent communication is part of the same "conversation")
2) WCF authenticates the ClientTag, issues the token, and stores it as a local variable
3) Client stores the token in it's own Session and pass it to WCF with every request
Where it breaks down is the fact that Azure (due to its high-availability/load-balancing nature) doesn't support WCF sessions. So, the questions is how do we implement this.
One solution is to use AppFabric caching to imitate session state in WCF layer. We would store the Access Token there and then validate it against what the client passes in. The problem with this is that there is no concurrency between client and WCF. So, we would have to advance WCF session timeout on every request from the same client but we'd want to avoid updating the cache on every request (it could be hundreds/sec).
Any suggestions? Has anyone implemented anything similar to this on Azure. Any feedback would be greatly appreciated.
P.S. It's not only authentication that would happen on the server, but also custom authorization for each client. (Some client might have access to some functions, and others might not).
Thanks!
I'm in the middle of implementing something directly similar to this, but using OAuth 2.0 as the authentication architecture through ACS.
The model I'm following is shamelessly stolen copied from an MSDN sample here: https://connect.microsoft.com/site1168/Downloads/DownloadDetails.aspx?DownloadID=35417. This assumes the client has a user interface, so the user can present some kind of username and password either directly or through some third-party identity provider.
The advantage of this approach is that the WCF layer doesn't need to use any kind of session state, so there's no tedious mucking about with machine keys or whatnot. You'll still get something that can be mapped to an IPrincipal, however, so if you want you can create a custom RoleProvider and use declarative roles in the usual way.
Note the sample uses old-school ASP.NET, and has a dependency on an opaque (and possibly rather buggy) assembly Microsoft.IdentityModel.Protocols.Oauth. And, unless I'm missing something, I've not seen this released anywhere else (e.g. as part of Windows Identity Foundation) so I suspect it's rather new.
An alternative approach could again be to use ACS, this time to authenticate a SAML token, again following the OAuth 2.0 protocols. Details and sample code is here: http://msdn.microsoft.com/en-us/library/windowsazure/hh127795.aspx. That may be better suited to a system with no UI.

How to force an IIS hosted WCF or ASMX [webservice] to use session object readonly?

While making my first ajax attempts, I decided also, to go to use IIS hosted WCF now. The strange thing is, that the WCF cannot process several requests parallel for the same user/session, if sessionmode is enabled! If sessionmode is disabled on asp.net, the requests are processed parallel. The broser/client may execute several different requests, where some of them are long running. This blocks all further requets and make my ajax app unusable.
This applies to asmx [webservices] also. I had a big hope, to compile the webservice methods using "IReadOnlySessionState" interface, but this has - in oppsite to webpages - no influence. But I need access [most times readonly] to the asp.net session!
Does someone knows any solution to this problems.
Anyway, thanks a lot!
br--mabra
In .NET 4, you can do this in Application_BeginRequest
if (Context.Request.Path.EndsWith("xxx.svc"))
Context.SetSessionStateBehavior(SessionStateBehavior.ReadOnly);
I found this:
http://blogs.msdn.com/silverlightws/archive/2009/09/30/having-a-pollingduplex-service-and-any-other-wcf-service-in-the-same-website-causes-silverlight-calls-to-be-slow.aspx
Which states,
"All WCF services require read/write session state access if you enable ASP.Net sessions, which causes the replies to be queued sequentially. Ideally user should be able configure the WCF handler to be read only, which would allow polling duplex services to work with sessions. Unfortunately this is unsupported at this point."
...the only thing I can think of is if there's some way to manually force early release of the lock. I'm looking into that now.
You can provide a custom session state provider
See: http://koolsand.blogspot.com/2010/02/why-iis-hosted-wcf-services-does-not.html
whenever a request contains svc in the
path it intimates default session
state provider to use readonly lock
and not read-write lock. So using
readonly lock will allow the next wcf
call to be executed concurrently.

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