Tuesday, May 26, 2015

Implementing delegated authentication from an Azure MVC web app to an Azure Web API web service

Follow the information on this tutorial. Contained within that link, is this tutorial on authenticating a web app with delegated user identity to a web API service.

Authenticating users on an Azure web site (MVC) using Azure Active Directory (AAD)

Follow this guide provided on Github. It provides all of the information you need to enable the simplest form of Azure AD authentication in an MVC app. It can be used as the beginning step to getting a fully authenticated MVC web app / web API stack.

Monday, May 18, 2015

Creating an Intranet MVC 5 application using Windows Authentication that connects to a separate Intranet Web API 2 application also using Windows Authentication

Recently I wanted to create an Intranet MVC application using Windows Authentication that connects to a separate, pre-existing Intranet Web API 2 web service that also uses Windows Authentication. In order to get the Windows Authentication of the MVC application propagated to authenticate with the Web API 2 web service, I had to do the following:

1) Place the following in both applications' <system.web> sections in their respective configuration files.

        <authentication mode="Windows" />
        <authorization>
            <deny users="?" />
        </authorization>
2) Update the .NET aspnet.config file located at "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Aspnet.config" to change the following settings to the following values:

        <legacyImpersonationPolicy enabled="false"/>
        <alwaysFlowImpersonationPolicy enabled="true"/>
 3) In the code for the MVC app that wants to call the Web API 2 app, do the following:

            WindowsIdentity identity = (WindowsIdentity) this.HttpContext.User.Identity;

            using (identity.Impersonate())
            {
                searchModel.SearchResults = this.webApiService.FindWebApiItems(searchModel.SearchCriteria);
            }

This last bit is necessary to ensure that the currently authenticated user in the MVC app gets correctly propagated to the Web API 2 app. In the service that's mentioned in the code above, you'll also need to do the following for interacting with Web API 2:

4) Use the following to connect to Web API 2:

            HttpClientHandler handler = new HttpClientHandler
            {
                PreAuthenticate = true, 
                UseDefaultCredentials = true, 
                Credentials = CredentialCache.DefaultNetworkCredentials
            };

            using (HttpClient client = new HttpClient(handler))
            {
                string result = client.GetStringAsync(uriBuilder.Uri).GetAwaiter().GetResult();

                IList<MyWebApiModel> webApiModels = JsonConvert.DeserializeObject<MyWebApiModel[]>(result);

                return webApiModels;
            }
You should now have working code to propagate Windows Authentication via services.

As a side note, apparently there's also a way to change the settings so that you don't have to modify the global aspnet.config file, you can do it on a per-AppPool basis. The technique is described here, though I've never tried it myself.

Monday, April 27, 2015

A little gotcha with the Microsoft Task Parallel Library (TPL) Dataflow library

I've recently started using the Microsoft TPL Dataflow library in order to help improve the performance of some of our product's scheduled jobs. However, today, I ran into a little gotcha that's pretty important. When you're linking one block to another block, you must always ensure that the source block links to at least one target block that accepts its messages, otherwise it'll most likely deadlock!

Wednesday, April 08, 2015

Resolving "Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost'" in IIS with WCF web services

If you get an error that looks like "Could not establish trust relationship for the SSL/TLS secure channel with authority 'localhost'" in IIS while testing WCF web services, it most likely means that you haven't correctly specified the certificate for your service in IIS. If you're certain you've correctly specified the certificate, it most likely means that the IIS user doesn't have access to it, so you'll have to go in and manually grant permissions for it.

Removing a certificate binding from a port in Windows

As many people don't know, in Windows certificates can be bound to ports for securing content transferred over those ports. IIS happens to be particularly negatively affected by this if another program has a certificate bound to a port that you want to use, e.g. 443 for serving web pages.

Use the information at the following page to find the certificate binding and delete it :

https://msdn.microsoft.com/en-us/library/ms733791(v=vs.110).aspx

The short version:

Find the port: netsh http show sslcert | grep -C 5 443

This command will show all the SSL certificates that are bound to ports on your machine.

Delete the port: netsh http delete sslcert ipport=0.0.0.0:443

This should help deal with some of the more annoying (and less verbose) errors when doing things like trying to configure WCF services to use SSL.

Friday, March 20, 2015

Sunday, March 15, 2015

Using Ninject in an IIS-hosted environment to create a WCF service instance that's in a shared assembly (i.e. not the web application assembly)

Recently I wanted to create several WCF services for some of our internal applications and host these services in multiple different servers. There'd be no difference in the code between the locations where they'd be hosted. In order to avoid code duplication, I wanted to make these WCF services common and then just host them in the IIS applications. However, it's not as simple as creating a new (shared) assembly, creating the WCF service in that assembly and then sharing it between the different services. When I tried this, I ran into the problem where even though I specified the service in the config section:

<system.serviceModel>
         ....
</system.serviceModel> 
 
... it still wouldn't find my service and load it (I'm using Ninject as a dependency injection container for my WCF services).  They key to getting the shared services to be found and loaded properly was to create a .svc file in each of the services where the WCF services were shared, and it looked something like this in each case:

<%@ ServiceHost Language="C#" Debug="false" Service="MyWcfSharedServices.MySharedWebService" Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory" %>

After adding the .svc file and using the path to it in the system.serviceModel configuration in the configuration file, everything worked perfectly.

Wednesday, January 28, 2015

Resolving "The agent process was stopped while the test was running" on a TFS build agent

I'm currently working on a project that uses TFS for automated builds. Recently, our builds started failing with the error "The agent process was stopped while the test was running" while running unit tests. It wouldn't always happen during the same test, though it did frequently.

After inspecting the Event Viewer on the build machines, we found an error in the .NET Runtime that was taking down the build agent:

Application: QTAgent32_40.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: Moq.MockException
Stack:
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__5(System.Object)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(System.Object)
   at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()
The exception that was being thrown on a ThreadPoolThread (always extremely bad, never good) was a MockException: our unit testing framework was throwing an exception that was taking down the build agent.  But where?

How We Solved It

By some miracle, one of our developers decided to run our problematic tests with mstest on the command line on his local machine. As it turns out, this was great because it showed the stack traces for the loose threads on the command line. Turns out we had a lot more loose threads than just the one that was taking down our test agent on the build machine. The command the developer used was (similar to) the following:

mstest.exe /testcontainer:"C:\path\to\my\test.dll" /noisolation

After auditing all of the errors by rooting them out with command line runs of mstest, the solutions to our problems all boiled down to one thing:

*ALWAYS* wrap the contents of 'async void' methods with a try-catch block!