European ASP.NET 4.5 Hosting BLOG

BLOG about ASP.NET 4, ASP.NET 4.5 Hosting and Its Technology - Dedicated to European Windows Hosting Customer

European ASP.NET Core Hosting - HostForLIFE.eu :: Cookie Authentication and Policy Based Authorization in ASP.NET Core

clock February 6, 2017 10:23 by author Scott

This is the first part of the series of articles I'll be covering about ASP.NET Core Security. We're going to start off with cookie based authentication and build our way up to configuring policy based authorization.

As part of the ASP.NET Core security, there is a new richer policy based authorization that we can use to authorize against the claims in user's possession.

Let's build an example MVC application to demonstrate the concepts. In our scenario, we'll demand users to be authenticated and have Read claim to view the home page of our application.

I am using Visual Studio 2015 Pro Edition w/Update 3 (you should also be able to use the free community edition).

1. Create a new ASP.NET Core Web Application


2. Select the Empty Template


3. We need to add the required nuget packages to configure authorization, cookie authentication, and the mvc middleware. Bring up the project.jsonfile, add the following under the dependencies section.

"Microsoft.AspNetCore.Authorization": "1.0.0"
"Microsoft.AspNetCore.Authentication.Cookies": "1.0.0"
"Microsoft.AspNetCore.Mvc": "1.0.0"


4. Once you save the project.json file, Notice Visual Studio installs the missing nuget packages automatically. Next, bring up the Startup.cs where we'll configure the middleware we just included in our project.

5. In Configure method, add the following authentication middleware configuration;

app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        AuthenticationScheme = "Cookies",
        LoginPath = new StringPath("/Account/Login"),
        AccessDeniedPath = new StringPath("/Home/Forbidden"),
        AutomaticAuthenticate = true,
        AutomaticChallenge = true
    });

Here we're using the Cookie authentication, defining our LoginPath, where users will be redirected for authentication, and AccessDeniedPath when the user is not authorized. AutomaticAuthenticate flag indicates that the middleware should run on every request and attempt to validate and reconstruct any serialized principal it created. AutomaticChallenge flag indicates that the middleware should redirect the browser to the LoginPath or the AccessDeniedPath when the authorization fails (there are various other configuration options, however this the bare minimum we need for this example).

Next, we'll configure the requirements for the ReadPolicy. The policy will demand the user to be authenticated and have the Read claim in order access the required resource(s). Depending on your authorization logic, you can setup your policy to require additional claims.

public void ConfigureServices(IServiceCollection services) 
{
    services.AddAuthorization(options =>
    {
        options.AddPolicy("ReadPolicy", policyBuilder =>
        {
            policyBuilder.RequireAuthenticatedUser()
                .RequireAssertion(context => context.User.HasClaim("Read", "true"))
                .Build();
        });
    });
}

6. Finally we need to add the mvc middleware configuration.

app.UseMvc(builder =>
    {
        builder.MapRoute("default", "{controller=Home}/{action=index}/{id?}");
    });

Let's add couple of controllers so that we can test the login and the policy we've created. Create AccountController for user login and HomeController where we'll apply the ReadPolicy.

7. In the AccountController.cs add the following actions to login user;

[HttpGet]
public IActionResult Login(string returnUrl) 
{
    ViewData["ReturnUrl"] = returnUrl;
    return View();
}

8. Add a simple Login.cshtml view under the Views/Account folder (create the folder structure if it doesn't exists) where the user can login to the application.

<form asp-action="Account/Login" method="post" 
      asp-route-returnUrl="@ViewData["ReturnUrl"]">
    <div>
        <label>Username</label>
        <input type="text" name="username" />
    </div>
    <div>
        <label>Password</label>
        <input type="password" name="password" />
    </div>
    <div><button>Login</button></div>
</form> 

In the POST login action, we have a simple verification; The username and the password must match in order to authenticate the user (Obviously you wouldn't do this in a real production application but for our demo purposes this is fine). If they match, we then create a set of claims, the claims identity, and the claims principle that represents the authenticated user. Then, we sign in the user (means we issue a cookie to the user which contains the set of claims we've created) and redirect back to the resource that was requested for access.

[HttpPost]
public async Task<IActionResult> Login(string username, string password, string returnUrl) 
{
    if (username == password)
    {
        var claims = new List<Claim>
        {
            new Claim("Read", "true"),
            new Claim(ClaimTypes.Name, "ayayalar"),
            new Claim(ClaimTypes.Sid, "12345")
        };

        var claimsIdentity = new ClaimsIdentity(claims, "password");
        var claimsPrinciple = new ClaimsPrincipal(claimsIdentity);

        await HttpContext.Authentication.SignInAsync("Cookies", claimsPrinciple);

        if (Url.IsLocalUrl(returnUrl))
        {
            return Redirect(returnUrl);
        }

        return Redirect("~/");
    }

    return View();
}

9. Add the following action to the HomeController.cs;

[Authorize(Policy = "ReadPolicy")]
public IActionResult Index() 
{
    return View();
}

Note that we passed the ReadPolicy to the authorization attribute. The user must be authenticated and have a Read claim to have access. Otherwise, they'll be forwarded to the Forbidden page as we specified in the authentication middleware configuration.

The Index.cshtml view for the home page (can be as simple as one line of code) under Views/Home folder;

<h1>Access Granted</h1>

We should be able to test our changes at this point. Once you run the application, you'll be redirected to the login page since you're not authenticated (notice the return url in the query string is set automatically by the framework). Upon successfully submitting your credentials, you will be authorized and redirected to the home page.

For testing purposes, try removing the Read claim we've added in the Loginaction, rebuild your solution and restart the application, even if the user can login successfully, authorization will be denied and the user will be redirected to the Forbidden page.



European ASP.NET Core 1.0 Hosting - HostForLIFE.eu :: How to Publish Your ASP.NET Core in IIS

clock November 3, 2016 09:27 by author Scott

When you build ASP.NET Core applications and you plan on running your applications on IIS you'll find that the way that Core applications work in IIS is radically different than in previous versions of ASP.NET.

In this post I'll explain how ASP.NET Core runs in the context of IIS and how you can deploy your ASP.NET Core application to IIS.

Setting Up Your IIS and ASP.NET Core

The most important thing to understand about hosting ASP.NET Core is that it runs as a standalone, out of process Console application. It's not hosted inside of IIS and it doesn't need IIS to run. ASP.NET Core applications have their own self-hosted Web server and process requests internally using this self-hosted server instance.

You can however run IIS as a front end proxy for ASP.NET Core applications, because Kestrel is a raw Web server that doesn't support all features a full server like IIS supports. This is actually a recommended practice on Windows in order to provide port 80/443 forwarding which kestrel doesn't support directly. For Windows IIS (or another reverse proxy) will continue to be an important part of the server even with ASP.NET Core applications.

Run Your ASP.NET Core Site

To run your ASP.NET Core site, it is quite different with your previous ASP.NET version. ASP.NET Core runs its own web server using Kestrel component. Kestrel is a .NET Web Server implementation that has been heavily optimized for throughput performance. It's fast and functional in getting network requests into your application, but it's 'just' a raw Web server. It does not include Web management services as a full featured server like IIS does.

If you run on Windows you will likely want to run Kestrel behind IIS to gain infrastructure features like port 80/443 forwarding via Host Headers, process lifetime management and certificate management to name a few.

ASP.NET Core applications are standalone Console applications invoked through the dotnet runtime command. They are not loaded into an IIS worker process, but rather loaded through a native IIS module called AspNetCoreModule that executes the external Console application.

Once you've installed the hosting bundle (or you install the .NET Core SDK on your Dev machine) the AspNetCoreModule is available in the IIS native module list:

The AspNetCoreModule is a native IIS module that hooks into the IIS pipeline very early in the request cycle and immediately redirects all traffic to the backend ASP.NET Core application. All requests - even those mapped to top level Handlers like ASPX bypass the IIS pipeline and are forwarded to the ASP.NET Core process. This means you can't easily mix ASP.NET Core and other frameworks in the same Site/Virtual directory, which feels a bit like a step back given that you could easily mix frameworks before in IIS.

While the IIS Site/Virtual still needs an IIS Application Pool to run in, the Application Pool should be set to use No Managed Code. Since the App Pool acts merely as a proxy to forward requests, there's no need to have it instantiate a .NET runtime.

The AspNetCoreModule's job is to ensure that your application gets loaded when the first request comes in and that the process stays loaded if for some reason the application crashes. You essentially get the same behavior as classic ASP.NET applications that are managed by WAS (Windows Activation Service).

Once running, incoming Http requests are handled by this module and then routed to your ASP.NET Core application.

So, requests come in from the Web and int the kernel mode http.sys driver which routes into IIS on the primary port (80) or SSL port (443). The request is then forwarded to your ASP.NET Core application on the HTTP port configured for your application which is not port 80/443. In essence, IIS acts a reverse proxy simply forwarding requests to your ASP.NET Core Web running the Kestrel Web server on a different port.

Kestrel picks up the request and pushes it into the ASP.NET Core middleware pipeline which then handles your request and passes it on to your application logic. The resulting HTTP output is then passed back to IIS which then pushes it back out over the Internet to the HTTP client that initiated the request - a browser, mobile client or application.

The AspNetCoreModule is configured via the web.config file found in the application's root, which points a the startup command (dotnet) and argument (your application's main dll) which are used to launch the .NET Core application. The configuration in the web.config file points the module at your application's root folder and the startup DLL that needs to be launched.

Here's what the web.config looks like:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!--
    Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
  -->
  <system.webServer>
    <handlers>
      <add name="aspNetCore" path="*" verb="*"
        modules="AspNetCoreModule" resourceType="Unspecified" />
    </handlers>
    <aspNetCore processPath="dotnet"
                arguments=".\AlbumViewerNetCore.dll"
                stdoutLogEnabled="false"
                stdoutLogFile=".\logs\stdout"
                forwardWindowsAuthToken="false" />
  </system.webServer>
</configuration>

You can see that module references dotnetexe and the compiled entry point DLL that holds your Main method in your .NET Core application.

IIS is Recommended!

We've already discussed that when running ASP.NET Core on Windows, it's recommended you use IIS as a front end proxy. While it's possible to directly access Kestrel via an IP Address and available port, there are number of reasons why you don't want to expose your application directly this way in production environments.

First and foremost, if you want to have multiple applications running on a single server that all share port 80 and port 443 you can't run Kestrel directly. Kestrel doesn't support host header routing which is required to allow multiple port 80 bindings on a single IP address. Without IIS (or http.sys actually) you currently can't do this using Kestrel alone (and I think this is not planned either).

The AspNetCoreModule running through IIS also provides the necessary process management to ensure that your application gets loaded on the first access, ensures that it stays up and running and is restarted if it crashes. The AspNetCoreModule provides the required process management to ensure that your AspNetCore application is always available even after a crash.

It's also a good idea to run secure SSL requests through IIS proper by setting up certificates through the IIS certificate store and letting IIS handle the SSL authentication. The backplane HTTP request from IIS can then simply fire a non-secure HTTP request to your application. This means only a the front end IIS server needs a certificate even if you have multiple servers on the backplane serving the actual HTTP content.

IIS can also provide static file serving, gzip compression of static content, static file caching, Url Rewriting and a host of other features that IIS provides natively. IIS is really good and efficient at processing non-application requests, so it's worthwhile to take advantage of that. You can let IIS handle the tasks that it's really good at, and leave the dynamic tasks to pass through to your ASP.NET Core application.

The bottom line for all of this is if you are hosting on Windows you'll want to use IIS and the AspNetCoreModule.

How to Publish ASP.NET Core in IIS

In order to run an application with IIS you have to first publish it. There are two ways to that you can do this today:

1. Use dotnet publish

Using dotnet publish builds your application and copies a runnable, self-contained version of the project to a new location on disk. You specify an output folder where all the files are published. This is not so different from classic ASP.NET which ran Web sites out of temp folders. With ASP.NET Core you explicitly publish an application into a location of your choice - the files are no longer hidden away and magically copied around.

A typical publish command may look like this:

dotnet publish
      --framework netcoreapp1.0
      --output "c:\temp\AlbumViewerWeb"
      --configuration Release

If you open this folder you'll find that it contains your original application structure plus all the nuget dependency assemblies dumped into the root folder:

Once you've published your application and you've moved it to your server (via FTP or other mechanism) we can then hook up IIS to the folder.

After that, please just make sure you setup .NET Runtime to No Managed Code as shown above.

And that's really all that needs to happen. You should be able to now navigate to your site or Virtual and the application just runs.

You can now take this locally deployed Web site, copy it to a Web Server (via FTP or direct file copy or other publishing solution), set up a Site or Virtual and you are off to the races.

2. Publish Using Visual Studio

The dotnet publish step works to copy the entire project to a folder, but it doesn't actually publish your project to a Web site (currently - this is likely coming at a later point).

In order to get incremental publishing to work, which is really quite crucial for ASP.NET Core applications because there are so many dependencies, you need to use MsDeploy which is available as part of Visual Studio's Web Publishing features.

Currently the Visual Studio Tooling UI is very incomplete, but the underlying functionality is supported. I'll point out a few tweaks that you can use to get this to work today.

When you go into Visual Studio in the RC2 Web tooling and the Publish dialog, you'll find that you can't create a publish profile that points at IIS. There are options for file and Azure publishing but there's no way through the UI to create a new Web site publish.

However, you can cheat by creating your own .pubxml file and putting it into the \Properties\PublishProfilesfolder in your project.

To create a 'manual profile' in your ASP.NET Core Web project:

  • Create a folder \Properties\PublishProfiles
  • Create a file <MyProfile>.pubxml

You can copy an existing .pubxml from a non-ASP.NET Core project or create one. Here's an example of a profile that works with IIS:

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <WebPublishMethod>MSDeploy</WebPublishMethod>
    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <SiteUrlToLaunchAfterPublish>http://samples.west-wind.com/AlbumViewerCore/index.html</SiteUrlToLaunchAfterPublish>
    <LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
    <ExcludeApp_Data>False</ExcludeApp_Data>
    <PublishFramework>netcoreapp1.0</PublishFramework>
    <UsePowerShell>True</UsePowerShell>
    <EnableMSDeployAppOffline>True</EnableMSDeployAppOffline>
    <MSDeployServiceURL>https://publish.west-wind.com</MSDeployServiceURL>
    <DeployIisAppPath>samples site/albumviewercore</DeployIisAppPath>
    <RemoteSitePhysicalPath />
    <SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
    <MSDeployPublishMethod>RemoteAgent</MSDeployPublishMethod>
    <EnableMSDeployBackup>False</EnableMSDeployBackup>
    <UserName>username</UserName>
    <_SavePWD>True</_SavePWD>
    <ADUsesOwinOrOpenIdConnect>False</ADUsesOwinOrOpenIdConnect>
    <AuthType>NTLM</AuthType>
  </PropertyGroup>
</Project>

Once you've created a .pubxml file you can now open the publish dialog in Visual Studio with this Profile selected:

At this point you should be able to publish your site to IIS on a remote server and use incremental updates with your content.

#And it's a Wrap Currently IIS hosting and publishing is not particularly well documented and there are some rough edges around the publishing process. Microsoft knows of these issues and this will get fixed by RTM of ASP.NET Core.

In the meantime I hope this post has provided the information you need to understand how IIS hosting works and a few tweaks that let you use the publishing tools available to get your IIS applications running on your Windows Server.



About HostForLIFE.eu

HostForLIFE.eu is European Windows Hosting Provider which focuses on Windows Platform only. We deliver on-demand hosting solutions including Shared hosting, Reseller Hosting, Cloud Hosting, Dedicated Servers, and IT as a Service for companies of all sizes.

We have offered the latest Windows 2012 Hosting, ASP.NET 4.5 Hosting, ASP.NET MVC 4 Hosting, ASP.NET MVC 5 Hosting and SQL 2014 Hosting.


Tag cloud

Sign in