ASP.NET Core, MVC

From WCF to Secure ASP.NET Core

Here is the challenge: securing a system of WCF services with modern OAuth and OpenIDConnect.

The entire business logic of this solution is handled and served by WCFs.  Nothing wrong with it, but the security practices were a bit outdated and not up to standard.

Considering that years of features and logic were coded in those WCFs, the budget was limited and the need to upgrade to a secure and modern system became quickly very urgent, a rewrite of the entire solution was definitely not an option.  Therefore, I decided to place all the WCFs end-point behind a ASP.NET Core proxy that leverages the Identity Server 4 framework for authentication.

Another challenge I faced was that the entire solution was in VB and I am mainly a C# developer; additionally this is a VB shop that was a little reluctant in moving to C#.  But after long pondering and knowing that in the end VB and C# compile down to the same Microsoft Intermediate Lanaguage (MSIL) we decided to code this proxy in C# and eventually start porting some of these WCF functionality into a VB .NET Standard Class Library that plays well with C# projects anyway.

After doing some research I found several sources of information that I am sharing below. Definitely the most important and inspiring one was this video and blog of Shayne Boyer called ASP.NET Core: Getting clean with SOAPThese other sources might be helpful as well:

– Here is a way to securing existing WCFs and keep open the door for more modern WebApi systems. The problem is that is done with Identity Server 3 (older version): https://leastprivilege.com/2015/07/02/give-your-wcf-security-architecture-a-makeover-with-identityserver3/ Check also the link to Github samples.

– Here is an article on CORS for WCF:

https://blogs.msdn.microsoft.com/carlosfigueira/2012/05/14/implementing-cors-support-in-wcf/

The solution in question has a few different clients:  Javascript client (browser dashboard apps), mobile apps and server client.  IdentityServer 4 has a configuration for each of these case scenarios (or flows) and their Quickstart samples give you a very good idea on how to implement them.

The key here is the creation of the WCF client that from the ASP.NET Core WebApi calls the WCF services.  Shayne uses the “svcutil” (ServiceModel Metadata Utility Tool) to automatically generate the WCF client code.  But instead I decided to use this great Visual Studio extension that does just that but makes it easier to instantiate and use a WCF client. The extension is called  Microsoft WCF Web Service Reference Provider , once installed you just go to “Connected Services” in your solution explorer, input the endpoint url and the tool creates all the code you need.  Also, just recently this tool has been included in Visual Studio 2017 (version 15.5 and above), thus no need to install this extension anymore. One thing I must mention about this tool is that it work only with a SOAP endpoints, if the WCF has other type of endpoints (like REST) the tool will not be able to read the service metadata end will return an error. You can always add a SOAP endpoint to your WCF (hopefully you have access to it).

The extension creates a client that you can instantiate by passing the “EndpointConfiguration” type and use it to call each method exposed by the WCF (by default async). Here is how:

WCFclient client = new WCFclient(EndpointConfiguration.soap);
var result = await client.MyMethodAsync(args);

Now, one of the things that we need to make sure to do is to close and dispose of the WCF Client at the end of each request.  And here the ASP.NET Core Dependency Injection comes in handy.

The ASP.NET Core DI call the Dispose() method of the injected service if it implements the  IDisposable interface.  Our WCF client created with either the VS extension or the svcutil.exe utility does not implement IDisposable.  So we will wrap the client in a class and implement the interface ourselves. The WCF Client do expose the Close() and Abort() methods needed to dispose the service client (see below).

Be careful as the ASP.NET docs note the followings:

// container will create the instance(s) of these types and will dispose them
services.AddScoped<Service1>();
services.AddSingleton<Service2>();

// container did not create instance so it will NOT dispose it
services.AddSingleton<Service3>(new Service3());
services.AddSingleton(new Service3());

So if the DI creates the instance it will dispose of it (if it implements IDisposable) but if it doesn’t it will not dispose of it even if it implements IDisposable. So do not pass in an instantiated object as an argument, just let DI do the magic.

In wrapping the WCF client we want to maintain the possibility of changing the EndpointConfiguration as well as other configurations we might want to pass in in the future (like a different URL to point to if necessary).  Thus we inherit from the IWCFClient (the WCF interface implemented by the WCF and its client which is brought in by the VS extension above) and IDisposable and we pass in the configuration directly into “base” by way of the contructor:

public class WCFClientBySoap : IWCFClient, IDisposable
{
    public WCFClientBySoap() : base(EndpointConfiguration.soap)
    {
    }

    private bool disposedValue = false; 

    protected async virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                try
                {
                    if (State != System.ServiceModel.CommunicationState.Faulted)
                    {
                        await CloseAsync();
                    }
                }
                finally
                {
                    if (State != System.ServiceModel.CommunicationState.Closed)
                    {
                        Abort();
                    }
                }
            }

            disposedValue = true;
        }
    }

    public void Dispose()
    {
        Dispose(true);
    }
}

Here is a blog that talk about disposing of a WCF Client WCF Client Closal and Disposal

Now we just need to register this wrapper with the ASP.NET Core DI container.  Because we want to be able to change the wrapper in case of different configurations, we register the wrapper as a concrete class of the WCF interface.  In Startup.cs we add this line in the ConfigurationServices method:

services.AddScoped<IWCFClient, WCFClientBySoap>();

Finally we create a controller/action endpoint for each WCF endpoint leveraging the injected client:

[Produces("application/json")]
[Route("mycontroller")]
public class MyControllerController : Controller
{
    private IWCFClient _wcfclient;

    public MyControllerController(IWCFClient wcfclient)
    {
        _wcfclient = wcfclient;

    }

    [HttpGet("getMyData")]
    public async Task<IActionResult> GetMyData()
    {
        try
        {
            var result = await _wcfclient.getMyDataAsync();
            if (result == null)
            {
                return BadRequest("Couldn't get Data");
            }
            return new ObjectResult(result);
         }
         catch (Exception x)
         {
             return BadRequest(x.Message);
         }
     }
}

And this is all. It just works.

 

MVC

Return URL with fragment in ASP.NET Core MVC

I am working on a web project based on Asp.Net MVC and Aurelia and I decided to structure it with part MVC and part Spa (Aurelia). The project also implements a basic authentication system (Asp.Net Core Identity) where if a non-authenticated user is trying to access a secure page it is redirected to the login page, which is standard procedure in these cases.

As you can see the return URL sent in with the query string includes a fragment, used by the Aurelia routing (or any spa framework routing you are using):

http://localhost:14500/Auth/Login?ReturnUrl=%2Fcamp%2F7#sessions

The problem is that the fragment  portion of the URL is never sent to the server and it is therefore ignored. So here is what happens:

The fragment of the URL is not being added to the action url of the form, so when you post the login form the server redirects to a URL without fragment and you are not able to get to the correct page handled by the spa router.

So, I included a little Javascript functions that picks up the return URL from the browser’s location.href and updates the form action with the correct return URL:

$(document).ready(function () {
        var form = $("form")[0];
        var hash = document.location.hash;
        if (hash) {
            if (form) {
                if (form.action) {
                    form.action = document.location.href;
                }
            }
        }
    });

Here is how the form action looks like after this code runs:

Now, when the user logs in and the server redirect to the originally requested URL, Aurelia router picks it up and renders the correct page.