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 :: Dynamically Check And Uncheck Checkbox Based On DB Value In Gridview

clock July 23, 2019 12:23 by author Peter

This code will help the developers to check and uncheck the gridview checkbox based on the value from the database.
Create a GridView with checkbox.

<asp:GridView ID="Gridview" runat="server" Font-Size="8pt" 
        PageSize="200" Width="880px" AutoGenerateColumns="False"> 
        <Columns> 
            <asp:TemplateField> 
                <HeaderTemplate> 
                    <asp:CheckBox ID="chkHeader" Text="Select All" runat="server" /> 
                </HeaderTemplate> 
                <ItemTemplate> 
                    <asp:CheckBox ID="chkChild" runat="server"  Checked='<%# Eval("PROCESSED").ToString().Equals("1") %>' Enabled='<%# !Eval("PROCESSED").ToString().Equals("1") %>'/> 
                </ItemTemplate> 
            </asp:TemplateField>            
        </Columns> 
    </asp:GridView> 


Get the data from the database, the field from the database to check the checkbox should be 1 or 0.

DB Table data

PROCESSED (HEADER)
1
1
0

DataField "PROCESSED" should be 1 or 0 (boolean),

Checked='<%# Eval("PROCESSED").ToString().Equals("1") %>' 

The above GridView code will check the checkbox if the value from the PROCESSED field in DB is 1 else if the PROCESSED value is other than 1 the checkbox will be unchecked,

Enabled='<%# !Eval("PROCESSED").ToString().Equals("1") %>' 

This code will help us to enable or disable the text box. In the above mentioned code, if the PROCESSED is 1, checkbox will be disabled else the checkboc will be enable.

HostForLIFE.eu ASP.NET 4.8 Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.



European ASP.NET Core Hosting :: A Quick And Simple Look Into .NET Core And Comparison To .NET Standard

clock July 16, 2019 11:54 by author Peter
First, as Microsoft simply described, .NET Core is an open-source, general-purpose development platform maintained by Microsoft and the .NET community on GitHub. .NET is cross-platform which supports Windows, macOS, and Linux and can be used to implement devices, cloud, and IoT applications. Historically, the .NET Framework had only worked on Windows devices. The Xamarin and Mono projects worked to bring .NET to mobile devices, macOS, and Linux. .NET Core provides a standard base library that can now be used across Windows, Linux, macOS, and mobile devices, still via Xamarin.

.NET Core has multiple characteristics such as cross-platform programming for Windows, Linux, MacOS, as well as consistency across architectures. It runs your code with the same behavior on multiple architectures, including x64, x86, and ARM. .NET Core provides flexible deployment, can be included in your app or installed side-by-side such as user-wide or system-wide installations, and can be used with Docker containers.

.NET Core makes it simpler for developers to build microservice architecture systems promptly. As such, systems include several independent and dynamic microservices, the developers can focus on specific microservices. .NET Core enables programmers to develop custom microservices by using varying programming languages, technologies, and frameworks. Likewise, the developers can build a robust system by combining multiple microservices flawlessly.

PROGRAMMING LANGUAGE SUPPORT
From a programming point of view C#, Visual Basic, and F# languages can be used to write applications and libraries for .NET Core. Additionally, with .NET Core 3.0 C# 8.0 will be supported. Currently, VB.NET compiles and runs on .NET Core, but the separate Visual Basic Runtime is not implemented. Microsoft announced that .NET Core 3 would include the Visual Basic Runtime.

GENERAL SUPPORTED FEATURES
.NET Core supports four cross-platform scenarios: ASP.NET Core web apps, command-line apps, libraries, and Universal Windows Platform apps. However, it does not presently apply Windows Forms or WPF which render the standard GUI for desktop software on Windows. Also, .NET Core 3 supports desktop technologies WinForms, WPF and UWP. Besides these, .NET Core supports the use of NuGet packages. Differently than before like .NET Framework, which is serviced using Windows Update, .NET Core depends on its package manager to get updates.

.NET Core consists of CoreCLR, a whole runtime implementation of the Common Language Runtime, which created at Microsoft as the virtual machine for handling execution of .NET programs and includes a just-in-time compiler called RyuJIT. Moreover, .NET Core also contains CoreRT, the .NET Native runtime enhanced to be integrated into AOT compiled native binaries.

.NET Core also includes CoreFX, which is a partial branch of .NET Framework standard libraries. While .NET Core shares a subset of .NET Framework APIs and comes with its own API that is not a subset of .NET Framework. Also, a variant of the .NET Core library is used for UWP.

.NET Core's command-line interface provides an execution entry point for operating systems and gives developer services similar compilation and package management.

Use .NET Core when

  • You want to build cross-platform applications
  • If the new application (web or service) needs to run on multiple platforms- Windows, Linux, macOS, choose .NET Core over .NET Framework. Visual Studio Code and third-party editors such as Sublime, Emacs, VI support .NET Core for cross-platform development.
  • The need is to build high-performance and scalable systems
  • When a performance-oriented and scalable system is on the list, it is better to prefer .NET Core over the .NET Framework. Reason being, .NET Core offers high-performance server runtime for Linux and Windows Server.
  • When you are using microservices or Docker containers
  • For applications or services that use microservices or Docker containers, opting .NET Core makes more sense. Reasons include,
    • .NET Core facilitates mixing microservices or services developed with Ruby, Java, .NET Framework, or other monolithic technologies.
    • Containers usually work in conjugation with microservices architecture. With .NET Framework, there is a limitation to work with Windows containers only. Moreover, while creating and deploying a container, the image size is smaller with .NET Core vs .NET Framework.
  • You need side-by-side .NET versions per application
  • For applications that may have a dependency on different versions of .NET for installation, opt for .NET Core. .NET Core offers side by side installation of multiple versions for .NET Core runtime on the same machine.

Use the .NET Framework when:

  • The app is using .NET technologies that are not available for .NET Core.
  • Several .NET technologies are not available for .NET Core. For example, ASP.NET web pages applications or workflow related services (WCF Data Services, Windows Workflow Foundation) are not included in. NET Core.
  • The existing app uses a platform that .NET Core does not support.
  • Some of the Microsoft or third-party services/platforms do not offer support to .NET Core. For example, Azure’s Service Fabric Stateful Reliable Services programming model does not support .NET Core and is available for.NET Framework.

Finally, the .NET Framework supports Windows and web applications. .NET Core is the new open-source and cross-platform framework to build applications for all operating systems including Windows, Mac, and Linux. .NET Core supports UWP and ASP.NET Core only.

HostForLIFE.eu ASP.NET 4.8 Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.

 



European ASP.NET Core Hosting :: Register And Use Multiple Implementations Of A Dependency In ASP.NET Core Dependency Injection

clock July 12, 2019 12:13 by author Peter

There can be situations where you need to register multiple implementations of the same dependency for your applications. For example, if you want to add features to your application without changing the existing code, a good way to do it is to add a new implementation for that. Your application needs to be written in a certain way to do this correctly. We have a really simple example that demonstrates this in this article. But when you eventually need to do this, ASP.Net Core built-in Dependency Injection providers capabilities to achieve this. In this article, we will look at how to do this with an example.
Registering Multiple Implementations of a Dependency

As an example, let’s take an online e-commerce website. This site gives Discounts to the customers on certain occasions and when certain conditions are met. I have an interface called IDiscount where it defines a discount and the logic to calculate it. For each type of discount, you want to provide in your e-commerce application, you can have an implementation of the IDiscount interface. Then I have an interface called IDiscountProcessor where the implementation of this interface handles calling all the implementations of IDiscount to calculate the final discount for a given Order.

You have a couple of ways to register multiple implementations of a dependency in ASP.Net Core. One way is to just use the provided extension methods on IServiceCollection to register your implementations with the desired lifetime.
    services.AddScoped<IDiscountProcessor, OrderDiscountProcessor>(); 
    services.AddScoped<IDiscount, SeasonalDiscount>(); 
    services.AddScoped<IDiscount, LargeOrderDiscount>(); 
    services.AddScoped<IDiscount, ThreeOrModeDiscount>();  


Here, I have registered the OrderDiscountProcessor implementation of IDiscountProcessor and 3 implementations of IDiscount interface.

This will work fine when we eventually resolve all the implementations of IDiscount interface we can calculate the total discount. But the problem comes when you have multiple registrations of the same implementation. For example, let’s say one of the developers accidentally registered SeasonalDiscount implementation twice. What will happen is that the Seasonal discount will be applied twice for all the orders, costing the organization money.

A better way of registering multiple implementations is to use TryAddEnumerable extension method given in the Microsoft.Extensions.DependencyInjection.Extensions namespace. This will not register any duplicate implementations making multiple implementation registration safe. The registration is a bit different where you need to use ServiceDescriptors to register the dependency. The modified implementation looks like this.
    services.AddScoped<IDiscountProcessor, OrderDiscountProcessor>(); 
    services.TryAddEnumerable(new[] 
    { 
        ServiceDescriptor.Scoped<IDiscount, SeasonalDiscount>(), 
        ServiceDescriptor.Scoped<IDiscount, LargeOrderDiscount>(), 
        ServiceDescriptor.Scoped<IDiscount, ThreeOrModeDiscount>() 
    }); 


Injecting and Using Multiple Implementations of a Dependency

Once your implementations are registered with the Dependency Injection container, they are ready to be used. To inject all the registered implementations, you need to use IEnumerable<> of the implementation type in your constructor. So, your constructor would look something like this. This is our OrderDiscountProcessor implementation.
    public class OrderDiscountProcessor : IDiscountProcessor 
    { 
        private readonly IEnumerable<IDiscount> _discounts; 
     
        public OrderDiscountProcessor(IEnumerable<IDiscount> discounts) 
        { 
            _discounts = discounts; 
        } 
        // ... 
    } 


Here I am injecting IEnumerable<IDiscount> where it injects all the registered implementations to my class. Then in my ProcessDiscount() method I can use the implementations like this.
    public (double, List<string>) ProcessDiscount(OrderViewModel order) 
    { 
        var discountDiscroptoons = new List<string>(); 
        var totalDiscount = 0.0; 
     
        foreach (var discount in _discounts) 
        { 
            var addedDiscount = discount.CalculateDiscount(order); 
            if (addedDiscount > 0) 
            { 
                 discountDiscroptoons.Add(discount.Description); 
            } 
            totalDiscount += addedDiscount; 
        } 
     
        return (totalDiscount, discountDiscroptoons); 
     } 


I can now iterate through all the implementations of IDiscount interface and call its CalculateDiscount() method to calculate the discount for the given Order.

Note that you can only use IEnumerable<> for your injections of multiple implementations. Any other type like IList<>, ICollection<> will not work in this case.
Summary

In this article, we looked into the process of how to register multiple implementations of the same dependency in ASP.NET Core and how to use these dependencies in our classes by injecting them. The simple sample application used to demonstrate this usage is available for download with this article or you can find the source code on GitHub under the following repository

HostForLIFE.eu ASP.NET 4.8 Hosting

European best, cheap and reliable ASP.NET hosting with instant activation. HostForLIFE.eu is #1 Recommended Windows and ASP.NET hosting in European Continent. With 99.99% Uptime Guaranteed of Relibility, Stability and Performace. HostForLIFE.eu security team is constantly monitoring the entire network for unusual behaviour. We deliver hosting solution including Shared hosting, Cloud hosting, Reseller hosting, Dedicated Servers, and IT as Service for companies of all size.

 



European ASP.NET Core Hosting :: How to Fix “An error occurred while starting the application” in ASP.NET Core on IIS

clock July 5, 2019 07:33 by author Scott

.NET Core is the latest Microsoft product and Microsoft always keep update their technologies. We have written tutorial about how to publish ASP.NET Core on IIS server, but we know that some of you sometimes receive error when deploying your ASP.NET Core. Feel frustrated to fix the issue? Yeah, not only you have headache, but some of our clients also experience same problem like you. That’s why we write this tutorial and hope it can help to fix your issue!

Anyone see this error? Have problem to solve it? We want to help you here!

The Problem

 

It basically means something bad happened with your application. Things you need to check

  • You might not have the correct .NET Core version installed on the server.
  • You might be missing DLL’s
  • Something went wrong in your Program.cs or Startup.cs before any exception handling kicked in

If you use Windows Server, then I believe that you can’t find anything on your Event Viewer too. You’ll notice that there is no error on your Event Viewer log. Why? This is because Event Logging must be wired up explicitly and you’ll need to use the Microsoft.Extensions.Logging.EventLog package, and depending on the error, you might not have a chance to even catch it to log to the Event Viewer.

How to Fix it?

So, how to fix error above? The followings are the steps to fix the error:

1. Open your web.config

2. Change stdoutLogEnabled=true

3. Create a logs folder

  • Unfortunately, the AspNetCoreModule doesn’t create the folder for you by default
  • If you forget to create the logs folder, an error will be logged to the Event Viewer that says: Warning: Could not create stdoutLogFile \\?\YourPath\logs\stdout_timestamp.log, ErrorCode = -2147024893.
  • The “stdout” part of  the value “.\logs\stdout” actually references the filename not the folder.  Which is a bit confusing.

4. Run your request again, then open the \logs\stdout_*.log file

Note – you will want to turn this off after you’re done troubleshooting, as it is a performance hit.

So your web.config’s aspNetCore element should look something like this

 <aspNetCore processPath=”.\YourProjectName.exe” stdoutLogEnabled=”true” stdoutLogFile=”.\logs\stdout” />

Doing this will log all the requests out to this file and when the exception occurs, it will give you the full stack trace of what happened in the \logs\stdout_*.log file

  

 

 

Hope this helps!

Looking for ASP.NET Core hosting with affordable cost?

We know it is quite hard to find reliable hosting that support ASP.NET Core. We believe that some of you have signed up for 1 hosting, but they are below your expectation. Maybe they don’t support latest ASP.NET Core or they might support .NET Core but their support are not competent. We are here to help you. If you are looking for cheap, reliable with best ASP.NET Core hosting support, then you can visit our site at https://www.hostforlife.eu.



European ASP.NET Core Hosting :: How to Host ASP.NET Core Application as a Windows Service

clock July 4, 2019 08:38 by author Scott

I recently came across the need to host a .NET Core web app as a Windows Service. In this case, it was because each machine needed to locally be running an API. But it’s actually pretty common to have a web interface to manage an application on a PC without needing to set up IIS. For example if you install a build/release management tool such as Jenkins or TeamCity, it has a web interface to manage the builds and this is able to be done without the need for installing and configuring an additional web server on the machine.

Luckily .NET Core actually has some really good tools for accomplishing all of this (And even some really awesome stuff for being able to run a .NET Core web server by double clicking an EXE if that’s your thing).

A Standalone .NET Core Website/Web Server

The first step actually has nothing to do with Windows Services. If you think about it, all a Windows Service is, is a managed application that’s hidden in the background, will restart on a machine reboot, and if required, will also restart on erroring. That’s it! So realistically what we first want to do is build a .NET Core webserver that can be run like an application, and then later on we can work out the services part.

For the purpose of this tutorial, I’m just going to be using the default template for an ASP.net Core website. The one that looks like this:

We first need to head to the csproj file of our project and add in a specific runtime (Or multiple), and an output type. So overall my csproj file ends up looking like:

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <RuntimeIdentifiers>win10-x64;</RuntimeIdentifiers>
    <OutputType>Exe</OutputType>
  </PropertyGroup> 

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>
</Project>

Our RuntimeIdentifiers (And importantly notice the “s” on the end there) specifies the runtimes our application can be built for. In my case I’m building only for Windows 10, but you could specify other runtime monkiers if required.

Ontop of this, we specify that we want an outputtype of exe, this is so we can have a nice complete exe to run rather than using the “dotnet run” command to start our application. I’m not 100% sure, but the exe output that comes out of this I think is simply a wrapper to boot up the actual application dll. I noticed this because when you change code and recompile, the exe doesn’t change at all, but the dll does.

Now we need to be able to publish the app as a standalone application. Why standalone? Because then it means any target machine doesn’t have to have the .NET Core runtime installed to get everything running. Ontop of that, there is no “what version do you have installed?” type talk. It’s just double click and run.

To publish a .NET Core app as standalone, you need to run the following command from the project directory in a command prompt/powershell:

dotnet publish --configuration Release --self-contained -r win10-x64

It should be rather self explanatory. We are doing a publish, using the release configuration, we pass through the self contained flag, and we pass through that the runtime we are building for is Windows 10 – 64 Bit.

From your project directory, you can head to:  \bin\Release\netcoreapp2.1\win10-x64\publish

This contains your application exe as well as all framework DLL’s to run without the need for a runtime to be installed on the machine. It’s important to note that you should be inside the Publish folder. One level up is also an exe but this is not standalone and relies on the runtime being installed.

From your publish folder, try double clicking yourapplication.exe.

Hosting environment: Production
Content root path: \bin\Release\netcoreapp2.1\win10-x64\publish
Now listening on:
http://localhost:5000
Now listening on: https://localhost:5001
Application started. Press Ctrl+C to shut down.

In your browser head to http://localhost:5000 and you now have your website running from an executable. You can copy and paste this publish folder onto any Windows 10 machine, even a fresh install, and have it spin up a webserver hosting your website. Pretty impressive!

Installing As A Window Service

So the next part of this tutorial is actually kinda straight forward. Now that you have an executable that hosts your website, installing it as a service is exactly the same as setting up any regular application as a service. But we will try and have some niceties to go along with it.

First we need to do a couple of code changes for our app to run both as a service, and still be OK running as an executable (Both for debugging purposes, and in case we want to run in a console window and not as a service).

We need to install the following from your package manager console:

Install-Package Microsoft.AspNetCore.Hosting.WindowsServices

Next we need to go into our program.exe and make your main method look like the following:

public static void Main(string[] args)
{
 var isService = !(Debugger.IsAttached || args.Contains("--console"));
 var builder = CreateWebHostBuilder(args.Where(arg => arg != "--console").ToArray()); 

 if (isService)
 {

 var pathToExe = Process.GetCurrentProcess().MainModule.FileName;
 var pathToContentRoot = Path.GetDirectoryName(pathToExe);
 builder.UseContentRoot(pathToContentRoot);
 

 var host = builder.Build(); 

 if (isService)
 {
 host.RunAsService();
 }
 else
 {
 host.Run();
 }
}

This does a couple of things :

  • It checks whether we are using the debugger, or if we have a console argument of “–console” passed in.
  • If neither of the above are true, it sets the content root manually back to where the exe is running. This is specifically for the service runtime.
  • Next if we are a service, we use a special “RunAsService()” method that .NET Core gives us
  • Otherwise we just do a “Run()” as normal.

Obviously the main point of this is that if the debugger is attached (e.g. we are running from visual studio), or we run from a command prompt with the flag “–console”, it’s going to run exactly the same as before. Back in the day we used to have to run the service with a 10 second sleep at the start of the app, and quickly try and attach the debugger to the process before it kicked off to be able to set breakpoints etc. Now it’s just so much easier.

Now let’s actually get this thing installed!

In your project in Visual Studio (Or your favourite editor) add a file called install.bat to your project. The contents of this file should be:

sc create MyService binPath= %~dp0MyService.exe
sc failure MyService actions= restart/60000/restart/60000/""/60000 reset= 86400
sc start MyService
sc config MyService start=auto

Obviously replace MyService with the name of your service, and be sure to rename the exe to the actual name of your applications exe. Leave the %~dp0 part as this refers to the current batch path (Allowing you to just double click the batch file when you want to install).

The install file creates the service, sets up failure restarts (Although these won’t really be needed), starts the service, and sets the service to auto start in the future if the machine reboots for any reason.

Go ahead and create an uninstall.bat file in your project. This should look like:

sc stop MyService
timeout /t 5 /nobreak > NUL
sc delete MyService

Why the timeout? I sometimes found that it took a while to stop the service, and so giving it a little bit of a break inbetween stopping and deleting helped it along it’s way.

Important! For both of these files, be sure to set them up so they copy to the output directory in Visual Studio. Without this, your bat files won’t output to your publish directory.

Go ahead and publish your application again using our command from earlier:

dotnet publish --configuration Release --self-contained -r win10-x64

Now in your publish directory, you will find your install and uninstall bat files. You will need to run both of these as Administrator for them to work as installing Windows Services requires elevated access. A good idea is that the first time you run these, you run them from a command prompt so you can catch any errors that happen.

Once installed, you should be able to browse to http://localhost:5000 and see your website running silently in the background. And again, the best part is when you restart your machine, it starts automatically. Perfect!



European ASP.NET Core Hosting :: Alert Dialog From Controller Without JavaScript In View

clock May 9, 2019 12:27 by author Peter
We can show an alert dialog in the browser from Controller without using any JavaScript in the View, which saves our time and makes the popping up of dynamic data way faster.
 
Displaying an Alert Dialog popup can be done from the controller and even from the server-side, but it is very useful when you want to display an alert using much less code.
 
In your Controller, copy the below code just before your return code.

public ActionResult SmartRegister(csUser model)  
 {               
     User us = new User();  
     rfSocietyEntities db = new rfSocietyEntities();  
     if (ModelState.IsValid)  
     {  
         int count = db.Users.Where(a => a.Email.Equals(model.Email)).Count();  
         if (count == 0)  
         {  
             us.Admin = model.Admin;  
             us.Email = model.Email;  
             us.FullName = model.FullName;  
             us.Password = model.Password;  
             us.PhoneNo = model.PhoneNo;  
             db.Users.Add(us);  
             db.SaveChanges();  
             return RedirectToAction("Dashboard""Dashboard");  
         }  
         else  
         {  
             TempData["msg"] = "<script>alert('Email id already registered.');</script>";  
             return View (model);  
         }  
     }  
     else  
     {  
         TempData["msg"] = "<script>alert('Please Check Data entered or try later.');</script>";  
         return View(model);  
     }  
}    
In your View file, add the below code.
  @Html.Raw(TempData["msg"])




European ASP.NET Core Hosting - HostForLIFE.eu :: ASP.NET Core Security Headers

clock April 30, 2019 11:13 by author Peter

With the help of headers, your website could send some useful information to the browser. Let’s see how it is possible to add more protection to your website.
To add a header for each request, we can use middleware.

XSS and CSP
Still in the OWASP top 10, there is XSS - Cross-Site Scripting attack. Sure, it helps a lot to encode symbols before displaying text on the website (using any one of the HtmlEncoder, JavaScriptEncoder, and UrlEncoder). And, it’s better never to use @Html.Raw(). But it is also possible to add a header that will inform the browser to stop XSS attack. This kind of header is useful mostly for old browsers.
app.Use(async (context, next) =>  
{  
context.Response.Headers.Add("X-Xss-Protection", "1");  
await next();  
}); 


For new browsers, it is better to use CSP. Here is how it is possible to add the CSP header.
app.Use(async (context, next) =>  
{  
context.Response.Headers.Add(  
  "Content-Security-Policy",  
  "default-src 'self'; " +  
  "img-src 'self' myblobacc.blob.core.windows.net; " +  
  "font-src 'self'; " +  
  "style-src 'self'; " +  
  "script-src 'self' 'nonce-KIBdfgEKjb34ueiw567bfkshbvfi4KhtIUE3IWF' "+  
  " 'nonce-rewgljnOIBU3iu2btli4tbllwwe'; " +  
  "frame-src 'self';"+  
  "connect-src 'self';");  
await next();  
});  


In this example, it is allowed to run scripts.js files only from the current website (that is a meaning of ‘self’). And it is allowed to run 2 specified with “nonce” attribute scripts that are inserted in page inside script tag. For example, if you are using some script like this one inside your page.
<script>  
function showMessage() {  
alert("Just for demo");  
}   
</script>  

Then, you will be not able to run this script without adding ‘unsafe-inline’ into your CSP definition.

But adding ‘unsafe-inline’ means leaving your website not-protected. So, better move the script into .js file or use a nonce. Just add to your script attribute nonce with some random value. For example,
<script nonce="KUY8VewuvyUYVEIvEFue4vwyiuf"> </script>  

Then, you can add to your CSP script-scr value ‘nonce-KUY8VewuvyUYVEIvEFue4vwyiuf’ and you will be able to run scripts from exactly this <script> section.

‘unsafe-inlne’ is also related to events that are added to your html as attributes. Like onclick, onchange, onkeydown, onfocus. For example, instead of the following onclick event, you should add id or class to your element and call event from <script> or .js file.
<p onclick="showMessage()">Show message</p>  

Like this,
<p id="message-text">Show message</p>  

<script nonce=”KUY8VewuvyUYVEIvEFue4vwyiuf”>  
$(document).ready(function() {  
$("#message-text") (function() {  
alert( "Just for demo" );  
});   
});  
</script>  


X-Frame-Options
By default, it is possible to display your website inside an iframe. But with one small header, it is possible to disallow this. Why? Because someone could display your website inside a frame and place a transparent layer over it. And, the users would be thinking that they are clicking on your website buttons/links but in a real case, they would be clicking on items placed in the transparent layer. And as cookies still could be in the user’s browser, some operation could be authenticated. This kind of attack is called Clickjacking. And, here is a header to protect your website from this attack.
context.Response.Headers.Add("X-Frame-Options", "DENY");  

Content sniffing
By the next link File Upload XSS you can find a more or less fresh sample of how it is possible to inject JavaScript into an svg file. And if a file like this would be located on the server that would have content sniffing security enabled, then JavaScript wouldn’t work because svg extension doesn’t correspond to JS content. Hope you believe me now that the next header is required.
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");  

Referrer-Policy
One of the headers that is automatically added by browsers is “Referer”. It contains a site from which the user has been transferred. Sometimes, that is convenient for analytics. But sometimes, the URL could contain some private information that is better not to be disclosed.

If you don’t want to allow browsers to display your website as last visited in “Referer” header, please use the Referrer-Policy: no-referrer

Here is an example of all headers in one middleware.
app.Use(async (context, next) =>  
{  
context.Response.Headers.Add("X-Xss-Protection", "1");  
context.Response.Headers.Add("X-Frame-Options", "DENY");  
context.Response.Headers.Add("Referrer-Policy", "no-referrer");  
context.Response.Headers.Add("X-Content-Type-Options", "nosniff");  
              context.Response.Headers.Add(  
  "Content-Security-Policy",  
  "default-src 'self'; " +  
  "img-src 'self' myblobacc.blob.core.windows.net; " +  
  "font-src 'self'; " +  
  "style-src 'self'; " +  
  "script-src 'self' 'nonce-KIBdfgEKjb34ueiw567bfkshbvfi4KhtIUE3IWF' "+  
  " 'nonce-rewgljnOIBU3iu2btli4tbllwwe'; " +  
  "frame-src 'self';"+  
  "connect-src 'self';");  
await next();  
});  


Sure, you can read information about each one header and change value to something more appropriate for your needs.
Strict-Transport-Security

For activating Strict-Transport-Security - web security policy mechanism that helps to protect your website from protocol downgrade attacks and cookie hijacking, add the next one to your middleware pipeline (or just don’t remove it),
app.UseHsts();  

This middleware will add “Strict-Transport-Security” header

Removing Server Header
Sometimes, headers could provide some information that is better to hide. To disable the Server header from Kestrel, you need to set AddServerHeader to false. Use UseKestrel() if your ASP.NET Core version is  lower than 2.2 and ConfigureKestrel() if not.
WebHost.CreateDefaultBuilder(args)  
     .UseKestrel(c => c.AddServerHeader = false)  
     .UseStartup<Startup>()  
     .Build();



European ASP.NET Core Hosting :: Create A Typed HttpClient With

clock April 23, 2019 10:57 by author Peter

HttpClient is used for sending HTTP requests and receiving HTTP responses from a resource identified by a URI. But, HttpClient has some issues. To read more on the issues of HttpClient, you can check this link. In the .NET Core 2.1 release, Microsoft has introduced a new way of designing HttpClients to solve these issues, and it's called HttpClientFactory. HttpClientFactory is an opinionated factory, available since .NET Core 2.1, for creating HttpClient instances in our applications. This means that we can create HttpClients and can register them in the HttpClientFactory in our application and can leverage the dependency injection capabilities of the .NET core to inject these HttpClients in our code. HttpClientFactory allows us to no longer care about the lifecycle of the HttpClient by leaving it to the framework.
 
There are three ways to use HttpClientFactory to instantiate HttpClients.

  • Default client
  • Named client
  • Typed client

In order to use the factory, we need to register it in the DI container. So, we need to use an extension method AddHttpClient() on IServiceCollection interface in our Startup.cs class. This will allow us to inject the HttpClient in our class constructors.
 
In this article, we will see how to create a Typed HttpClient using the HttpClient factory in a .NET core MVC application and use it for making HTTP calls. I prefer Typed HttpClient over the other two because,

    As the name suggests, typed clients provide type safety.
    Typed clients help in encapsulating the API calls when we are making use of the HttpClient at one place, thus making our code DRY (Don't Repeat Yourself). The other two will scatter the implementation details of making HTTP calls throughout the codebase.

We will make a simple MVC application to learn the workings of typed HttpClient. This application will receive the name of a movie and call a REST API to fetch the details of that movie and shall display it to the user. I will be using Visual Studio Code for developing the application. The REST API used for fetching the movie details is the OMDB API. The OMDB API is a RESTful web service to obtain movie information. This is a free API with a 1000 requests per day limit for a user. We need an API key for accessing this API. To know more details about this API you can check their website.

Create a folder called MovieFinder and open it in VS Code. Create an MVC application by running the following command in the terminal.
    dotnet new mvc --name MovieFinder 

This shall create a basic .NET Core MVC application. Now, let’s create a View Model class to hold the data from the OMDB API. So, let’s add a class named MovieDetailModel.
    public class MovieDetailModel 
    { 
        public string Title { get; set; } 
        public string Year { get; set; } 
        public string Director { get; set; } 
        public string Actors { get; set; } 
        public string IMDBRating { get; set; } 
        public string PosterImage { get; set; } 
        public string Plot { get; set; } 
    } 


Now, we need to create an interface for our typed client. Let's name it IMovieDetailsClient.
    public interface IMovieDetailsClient 
    { 
        Task<MovieDetailModel> GetMovieDetailsAsync(string movieName); 
    } 


This interface contains a single method, GetMovieDetailsAsync, which accepts the movie name as the parameter and shall return the details of that movie. Now we need to create a class which implements this interface. This class shall contain the actual logic of calling the OMDB API to fetch the movie details.
    public class MovieDetailsClient : IMovieDetailsClient 
    { 
        private readonly HttpClient _httpClient; 
     
        public MovieDetailsClient(HttpClient httpClient) 
        { 
            httpClient.BaseAddress = new Uri("http://www.omdbapi.com/"); 
            _httpClient = httpClient; 
        } 
     
        public async Task<MovieDetailModel> GetMovieDetailsAsync(string movieName) 
        { 
            var queryString = $"?t={movieName}&apikey=<your-api-key>"; 
            var response = await _httpClient.GetStringAsync(queryString); 
     
            JObject json = JObject.Parse(response); 
     
            if (json.SelectToken("Response").Value<string>() == "True") 
            { 
     
                var movieDetails = new MovieDetailModel 
                { 
                    Title = json.SelectToken("Title").Value<string>(), 
                    Year = json.SelectToken("Year").Value<string>(), 
                    Director = json.SelectToken("Director").Value<string>(), 
                    Actors = json.SelectToken("Actors").Value<string>(), 
                    IMDBRating = json.SelectToken("imdbRating").Value<string>(), 
                    PosterImage = json.SelectToken("Poster").Value<string>(), 
                    Plot = json.SelectToken("Plot").Value<string>() 
                }; 
     
                return movieDetails; 
            } 
     
            return new MovieDetailModel 
            { 
                Title = movieName 
            }; 
        } 
    } 


In this class, we inject the HttpClient in our class constructor and set the base address of our OMDB API endpoint. We also implement GetMovieDetailsAsync method declared in our interface. We called the OMDB API from our method and mapped the API response to our view model and returned it. I have used the JSON.NET library for parsing the response from the API.
Note that I have hardcoded the API Base address and the API key in the code. This is not a healthy practice. We shall always prefer moving these kinds of values to configuration files and shall read those values from the configuration files in our code.
 
We have now created our typed client. Now let's create the view for user interaction. In the Index.cshtml file in the Views\Home folder, replace the existing code with the following code.
    @{ 
        ViewData["Title"] = "Home Page"; 
    } 
     
    @model MovieDetailModel 
     
    <form  
        asp-controller="Home"  
        asp-action="Submit" 
        method="post"  
        class="form-horizontal"  
        role="form"> 
     
        <div class="form-group"> 
            <label for="Title">Title</label> 
            <input  
                class="form-control"  
                placeholder="Enter Title" 
                asp-for="Title">    
        </div> 
        <button type="submit" class="btn btn-primary">Submit</button> 
    </form> 
     
     
    @{ 
        <br> 
         
        if(!string.IsNullOrEmpty(Model?.Year)) 
        { 
            var title = Model.Title; 
            var year = Model.Year;   
            var message = $"{title} is release on {year}";  
      
            <br> 
            <div class="card" style="width: 18rem;"> 
                <img class="card-img-top" src=@Model.PosterImage alt="Poster Not Available"> 
                <div class="card-body"> 
                    <h5 class="card-title">@Model.Title (@Model.Year)</h5> 
                    <p class="card-text">@Model.Plot</p>               
                </div> 
                <ul class="list-group list-group-flush"> 
                    <li class="list-group-item"><strong>Director : @Model.Director</strong></li> 
                    <li class="list-group-item"><strong>Actors : @Model.Actors</strong></li> 
                    <li class="list-group-item"><strong>Rating : @Model.IMDBRating</strong></li> 
                </ul> 
            </div>      
        } 
         
        if(Model != null && string.IsNullOrEmpty(Model?.Year)) 
        { 
            <div class="alert alert-danger" role="alert"> 
                <strong>Sorry!! Requested Movie Details are not available..</strong>  
            </div> 
        } 
    } 


Now, we need to add the Controller code for accepting the movie name from the view and for displaying the movie details. For that, we need to inject the typed client we had created into the constructor of our controller. So, we need to register this typed client with the HttpClient factory in our Startup.cs class. Add the following code in the ConfigureServices method in the startup class.
    services.AddHttpClient<IMovieDetailsClient, MovieDetailsClient>(); 

Now, let's add our controller methods. In the HomeController make the changes as below.
    public class HomeController : Controller 
    { 
        private readonly IMovieDetailsClient _movieDetailsClient; 
     
        public HomeController(IMovieDetailsClient movieDetailsClient) 
        { 
            _movieDetailsClient = movieDetailsClient; 
        } 
     
        public IActionResult Index() 
        { 
            return View(); 
        } 
     
        [HttpPost] 
        public async Task<IActionResult> Submit(MovieDetailModel model) 
        { 
            var movieDetail = await _movieDetailsClient.GetMovieDetailsAsync(model.Title); 
            return View("Index", movieDetail); 
        }       
    } 


We are injecting our IMovieDetails client in the constructor of our controller and assigning it to a read-only field _movieDetailsClient. We have also defined an action named Submit which takes the title of the movie from the view as a parameter. This method makes use of our typed HttpClient to fetch the details of that movie and shall return the view with the details of that movie.

Now, run the application. Execute the command dotnet run in the terminal. Open a browser and navigate to https://localhost:5001/.

 



European ASP.NET Core Hosting :: RESTful WebAPI With Onion Architecture

clock April 9, 2019 11:29 by author Peter

Hello friends, here I will show you how to create a WebApi with the following characteristics:

  • ASP.Core 2.1
  • EntityFramework
  • FluentValidation
  • Nlogger
  • Swagger
  • Jwt

Let's start. First create an empty project, then add the following folders:

  • Application
  • Domain
  • Service
  • Infrastructure

Then in the Domain folder, we create a library project Net.Core 2.1 with the name WebApi.Domain add the following dependencies

FluentValidation.AspNetCore

In this project, we add the following folders:

  • Dtos
  • Entities
  • Interfaces

In the Entities folder, we create the BaseEntity class:

    namespace WebApi.Domain.Entities 
    { 
        public abstract class BaseEntity 
        { 
            public virtual int Id { get; set; } 
        } 
    } 

Our project classes will inherit the field Id from this abstract class (if you want you can add other fields like CreatedAt or CreatedBy).

Then we create the Country class with the properties that defines a Country.

    namespace WebApi.Domain.Entities 
    { 
        public class Country : BaseEntity 
        { 
            public string Name { get; set; } 
            public int Population { get; set; } 
            public decimal Area { get; set; } 
            public string ISO3166 { get; set; } 
            public string DrivingSide { get; set; } 
            public string Capital { get; set; } 
     
        } 
    } 

Now to make the exercise more interesting, we are going to assume that we do not want to expose all the Country class. In the Dtos folder, we create the following CountryDensityDTO class.

    using System; 
    using WebApi.Domain.Entities; 
     
    namespace WebApi.Domain.Dtos 
    { 
        public class CountryDensityDTO : BaseEntity 
        { 
            public string Name { get; set; } 
            public string Capital { get; set; } 
            public decimal Area { get; set; } 
            public int Population { get; set; } 
     
     
            public int Populationdensity 
            { 
                get 
                { 
                    return Decimal.ToInt32(Population / Area); 
                } 
            } 
        } 
    }

This class exposes Name, Capital Area, Population and a calculated field Populationdensity.
Now we will continue with the Infrastructure layer and then we will finish the missing parts.We go to the Infrastructure folder and create a library Net.Core 2.1. We name it WebApi.Infrastructure.Data.

We add the following Packages:

  • Microsoft.EntityFrameworkCore.SqlServer 2.1.4
  • Microsoft.EntityFrameworkCore.Tools 2.1.4
  • Microsoft.Extensions.Identity.Stores 2.1.1
  • Microsoft.VisualStudio.Web.CodeGeneration.Design 2.1.5
  • Add Project reference WebApi.Domain 

We create the following folders:

  • Context
  • EntityDbMapping
  • Repository

In the Context Folder, we add the SqlServerContext class. We refer to our Country entity with DbSet to work with the database. As we work with CodeFirst approach, we will create a mapping for our entity Country in the database.
"modelBuilder.Entity<Country>(new CountryMap().Configure);"

Optionally, in this part we can also add seed data when creating a table.

using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 
using Microsoft.EntityFrameworkCore; 
using WebApi.Domain.Entities; 
using WebApi.Infrastructure.Data.EntityDbMapping; 

namespace WebApi.Infrastructure.Data.Context 

public class SqlServerContext :   IdentityDbContext<ApplicationUser> 

    public DbSet<Country> Country { get; set; } 

    public SqlServerContext(DbContextOptions<SqlServerContext> options) : base(options) 
    { 
      
    }     
    protected override void OnModelCreating(ModelBuilder modelBuilder) 
    { 
        base.OnModelCreating(modelBuilder); 
        modelBuilder.Entity<Country>(new CountryMap().Configure); 
        // ModelBuilderExtensions.Seed(modelBuilder); 

    } 

//Data for first time on table 
public static class ModelBuilderExtensions 

    public static void Seed(this ModelBuilder modelBuilder) 
    { 
        modelBuilder.Entity<Country>().HasData( 
            new Country 
            { 
                Id = 1, 
                Name = "Venezuela", 
                Population = 300000000, 
                Area = 230103 
              
            }, 
            new Country 
            { 
                Id = 2, 
                Name = "Peru", 
                Population = 260000000, 
                Area =33249               
            } 
        ); 
    } 


In the folder, EntityDbMapping, we create the CountryMap class. In this class, we define the physical representation of the properties of the Country class as fields in the table of the database.

    using Microsoft.EntityFrameworkCore;   
    using Microsoft.EntityFrameworkCore.Metadata.Builders;   
    using WebApi.Domain.Entities;   
       
    namespace WebApi.Infrastructure.Data.EntityDbMapping   
    {   
        public class CountryMap : IEntityTypeConfiguration<Country>   
        {   
            public void Configure(EntityTypeBuilder<Country> builder)   
            {   
                builder.ToTable("Country");   
       
                builder.HasKey(c => c.Id);   
       
                builder.Property(c => c.Name)   
                    .IsRequired()   
                    .HasColumnName("Name")   
                    .HasColumnType("varchar(150)");   
       
                builder.Property(c => c.Population)   
                    .IsRequired()   
                    .HasColumnType("int")   
                    .HasColumnName("Population");   
       
                builder.Property(c => c.Area)   
                    .IsRequired()   
                    .HasColumnType("decimal(14,2)")   
                    .HasColumnName("Area");   
       
                builder.Property(c => c.ISO3166)   
                .IsRequired()   
                .HasColumnType("varchar(3)")   
                .HasColumnName("ISO3166");   
       
                builder.Property(c => c.DrivingSide)   
                .IsRequired()   
                .HasColumnType("varchar(50)")   
                .HasColumnName("DrivingSide");   
       
                builder.Property(c => c.Capital)   
                .IsRequired()   
                .HasColumnType("varchar(50)")   
                .HasColumnName("Capital");   
            }   
       
        }   
    }   


This is it for now.
In the next chapter, we will implement validations with FluentValidation. We will also configure Mapper to use it with our DTOs and will implement Identity using Jwt.



European ASP.NET Core Hosting :: How to Use Auth Cookies in ASP.NET Core

clock March 29, 2019 11:49 by author Scott

Cookie-based authentication is the popular choice to secure customer facing web apps. For .NET programmers, ASP.NET Core has a good approach that is worth looking into. In this take, I will delve deep into the auth cookie using ASP.NET Core 2.1. Version 2.1 is the latest LTS version as of the time of this writing. So, feel free to follow along, I’ll assume you’re on Visual Studio or have enough C# chops to use a text editor. I will omit namespaces and using statements to keep code samples focused. If you get stuck, download the sample code found at the end.

With ASP.NET 2.1, you can use cookie-based authentication out of the box. There is no need for additional NuGet packages. New projects include a metapackage that has everything, which is Microsoft.AspNetCore.App. To follow along, type dotnet new mvc in a CLI or do File > New Projectin Visual Studio.

For those of you who come from classic .NET, you may be aware of the OWIN auth cookie. You will be happy to know those same skills transfer over to ASP.NET Core quite well. The two implementations remain somewhat similar. With ASP.NET Core, you still configure the auth cookie, set up middleware, and set identity claims.

Setup

To begin, I’ll assume you know enough about the ASP.NET MVC framework to gut the scaffolding into a skeleton web app. You need a HomeController with an Index, Login, Logout, and Revoke action methods. Login will redirect to Index after it signs you in, so it doesn’t need a view. I’ll omit showing view sample code since views are not the focus here. If you get lost, be sure to download the entire demo to play with it.

I’ll use debug logs to show critical events inside the cookie authentication. Be sure to enable debug logs in appsettings.json and disable Microsoft and system logs.

My log setup looks like this:

"LogLevel": {
  "Default": "Debug",
  "System": "Warning",
  "Microsoft": "Warning"
}

Now you’re ready to build a basic app with cookie authentication. I’ll forgo HTML forms with a user name and password input fields. These front-end concerns only add clutter to what is more important which is the auth cookie. Starting with a skeleton app shows how effective it is to add an auth cookie from scratch. The app will sign you in automatically and land on an Index page with an auth cookie. Then, you can log out or revoke user access. I want you to pay attention to what happens to the auth cookie as I put authentication in place.

Cookie Options

Begin by configuring auth cookie options through middleware inside the Startup class. Cookie options tell the authentication middleware how the cookie behaves in the browser. There are many options, but I will only focus on those that affect cookie security the most.

  • HttpOnly: A flag that says the cookie is only available to servers. The browser only sends the cookie but cannot access it through JavaScript.
  • SecurePolicy: This limits the cookie to HTTPS. I recommend setting this to Always in prod. Leave it set to None in local.
  • SameSite: Indicates whether the browser can use the cookie with cross-site requests. For OAuth authentication, set this to Lax. I am setting this to Strict because the auth cookie is only for a single site. Setting this to None does not set a cookie header value.

There are cookie options for both the auth cookie and a global cookie policy. Stay alert since the cookie policy can override auth cookie options and vice versa. Setting HttpOnly to false in the auth cookie will override cookie policy options. While setting SameSite in the cookie policy overrides auth cookie options. In my demo, I’ll illustrate both scenarios, so it is crystal clear how this works.

In the Startup class, find the ConfigureServices method and type:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
  .AddCookie(options =>
  {
    options.Cookie.HttpOnly = true;
    options.Cookie.SecurePolicy = _environment.IsDevelopment()
      ? CookieSecurePolicy.None : CookieSecurePolicy.Always;
      options.Cookie.SameSite = SameSiteMode.Lax;
  });

This creates the middleware service with the AddAuthentication and AddCookie methods. AuthenticationScheme is useful when there is more than one auth cookie. Many instances of the cookie authentication let you protect endpoints with many schemes. You supply any string value; the default is set to Cookies. Note that the options object is an instance of the CookieAuthenticationOptions class.

The SecurePolicy is set through a ternary operator that comes from _environment. This is a private property that gets set in the Startup constructor. Add IHostingEnvironment as a parameter and let dependency injection do the rest.

In this same ConfigureServices method, add the global cookie policy through middleware:

services.Configure<CookiePolicyOptions>(options =>
{
  options.MinimumSameSitePolicy = SameSiteMode.Strict;
  options.HttpOnly = HttpOnlyPolicy.None;
  options.Secure = _environment.IsDevelopment()
    ? CookieSecurePolicy.None : CookieSecurePolicy.Always;
});

Take a good look at SameSite and HttpOnly settings for both cookie options. When I set the auth cookie, you will see this set to HttpOnly and Strict. This illustrates how both options override each other.

Invoke this middleware inside the request pipeline in the Configure method:

app.UseCookiePolicy();
app.UseAuthentication();

The cookie policy middleware is order sensitive. This means it only affects components after invocation. By invoking the authentication middleware, you will get a HttpContext.User property. Be sure to call this UseAuthentication method before calling UseMvc.

Login

In the HomeController add an AllowAnonymous filter to the Login and Logout methods. There are only two action methods available without an auth cookie.

Inside the Startup class, look for the AddMvc extension method and add a global auth filter:

services.AddMvc(options => options.Filters.Add(new AuthorizeFilter()))

With the app secure, configure the cookie name and login / logout paths. Find where the rest of the CookieAuthenticationOptions are and do:

options.Cookie.Name = "SimpleTalk.AuthCookieAspNetCore";
options.LoginPath = "/Home/Login";
options.LogoutPath = "/Home/Logout";

This will cause the app to redirect to the login endpoint to sign in. However, before you can take this for a spin, you’ll need to create the auth cookie.

Do this inside the Login action method in the HomeController:

var claims = new List<Claim>
{
  new Claim(ClaimTypes.Name, Guid.NewGuid().ToString())
}; 

var claimsIdentity = new ClaimsIdentity(
  claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties(); 

await HttpContext.SignInAsync(
  CookieAuthenticationDefaults.AuthenticationScheme,
  new ClaimsPrincipal(claimsIdentity),
  authProperties);

AuthenticationProperties drive further auth cookie behavior in the browser. For example, the IsPersistent property persists the cookie across browser sessions. Be sure to get explicit user consent when you enable this property. ExpiresUtc sets an absolute expiration, be sure to enable IsPersistent and set it to true. The default values will give you a session cookie that goes away when you close the tab or browser window. I find the default values in this object enough for most use cases.

To take this for a spin load up the browser by going to the home or Index page. Note it redirects to Login which redirects back to Index with an auth cookie.

Once this loads it looks something like this. Be sure to take a good look at how the auth cookie is set:

JWT Identity Claim

Often, an auth cookie isn’t enough to secure API endpoints or microservices. For the web app to call a service, it can use a JWT bearer token to authenticate. To make the access token accessible, place it inside the identity claims.

In the Login action method within HomeController, expand the list of claims with a JWT:

var userId = Guid.NewGuid().ToString();
var claims = new List<Claim>
{
  new Claim(ClaimTypes.Name, userId),
  new Claim("access_token", GetAccessToken(userId))
}; 

private static string GetAccessToken(string userId)
{
  const string issuer = "localhost";
  const string audience = "localhost"; 

  var identity = new ClaimsIdentity(new List<Claim>
  {
    new Claim("sub", userId)
  }); 

  var bytes = Encoding.UTF8.GetBytes(userId);
  var key = new SymmetricSecurityKey(bytes);
  var signingCredentials = new SigningCredentials(
    key, SecurityAlgorithms.HmacSha256); 

  var now = DateTime.UtcNow;
  var handler = new JwtSecurityTokenHandler(); 

  var token = handler.CreateJwtSecurityToken(
    issuer, audience, identity,
    now, now.Add(TimeSpan.FromHours(1)),
    now, signingCredentials); 

  return handler.WriteToken(token);
}

I must caution, don’t ever do this is in production. Here, I use the user id as the signing key which is symmetric to keep it simple. In a prod environment use an asymmetric signing key with public and private keys. Client apps will then use a well-known configuration endpoint to validate the JWT.

Placing the JWT in ClaimsIdentity makes it accessible through the HttpContex.User property. For this app, say you want to put the JWT in a debug log to show off this fancy access token.

In the Startup class, create this middleware inside the Configure method:

app.Use(async (context, next) =>
{
  var principal = context.User as ClaimsPrincipal;
  var accessToken = principal?.Claims
    .FirstOrDefault(c => c.Type == "access_token"); 

  if (accessToken != null)
  {
    _logger.LogDebug(accessToken.Value);
  } 

  await next();
});

The _logger is another private property you set through the constructor. Add ILogger<Startup> as a parameter and let dependency injection do the rest. Note the ClaimsPrincipal has a list of Claims you can iterate through. What I find useful is to look for a Type of claim like an access_token and get a Value. Because this is middleware always call next() so it doesn’t block the request pipeline.

Logout

To log out of the web app and clear the auth cookie do:

await HttpContext.SignOutAsync(
  CookieAuthenticationDefaults.AuthenticationScheme);

This belongs inside the Logout action method in the HomeController. Note that you specify the authentication scheme. This tells the sign-out method which auth cookie it needs to blot out. Inspecting HTTP response headers reveals Cache-Control and Pragma headers set to no-cache. This shows the auth cookie disables browser caching when it wants to update the cookie. The Login action method responds with the same HTTP headers.

Revocation

There are use cases where the app needs to react to back-end user access changes. The auth cookie will secure the application, but, remains valid for the lifetime of the cookie. With a valid cookie, the end-user will not see any changes until they log out or the cookie expires. In ASP.NET Core 2.1, one way to validate changes is through cookie authentication events. The validation event can do back-end lookups from identity claims in the auth cookie. Create the event by extending CookieAuthenticationEvents. Override the ValidatePrincipal method and set the event in the auth cookie options.

For example:

public class RevokeAuthenticationEvents : CookieAuthenticationEvents
{
  private readonly IMemoryCache _cache;
  private readonly ILogger _logger; 

  public RevokeAuthenticationEvents(
    IMemoryCache cache,
    ILogger<RevokeAuthenticationEvents> logger)
  {
    _cache = cache;
    _logger = logger;
  } 

  public override Task ValidatePrincipal(
    CookieValidatePrincipalContext context)
  {
    var userId = context.Principal.Claims
      .First(c => c.Type == ClaimTypes.Name); 

    if (_cache.Get<bool>("revoke-" + userId.Value))
    {
      context.RejectPrincipal(); 

      _cache.Remove("revoke-" + userId.Value);
      _logger.LogDebug("Access has been revoked for: "
        + userId.Value + ".");
    } 

    return Task.CompletedTask;
  }
}

To have IMemoryCache set by dependency injection, put AddMemoryCache inside the ConfigureSerices method in the Startup class. Calling RejectPrincipal has an immediate effect and kicks you back out to Login to get a new auth cookie. Note this relies on in-memory persistence which gets set in the Revoke action method. Keep in mind that this event runs once per every request, so you want to use an efficient caching strategy. Doing an expensive lookup at every request will affect performance.

Revoke access by setting the cache inside the Revoke method in the HomeController:

var principal = HttpContext.User as ClaimsPrincipal;
var userId = principal?.Claims
  .First(c => c.Type == ClaimTypes.Name); 

_cache.Set("revoke-" + userId.Value, true);
return View();

After visiting the Revoke endpoint, the change does not have an immediate effect. After revocation, navigating home will show the debug log and redirect to Login. Note that landing in the Index page again will have a brand new auth cookie.

To register this event, be sure to set the EventsType in the CookieAuthenticationOptions. You will need to provide a scoped service to register this RevokeAuthenticationEvents. Both are set inside the ConfigureServices method in the Startup class.

For example:

options.EventsType = typeof(RevokeAuthenticationEvents);
services.AddScoped<RevokeAuthenticationEvents>();

The CookieValidatePrincipalContext in ValidatePrincipal can do more than revocation if necessary. This context has ReplacePrincipal to update the principal, then renew the cookie by setting ShouldRenew to true.

Session Store

Setting a JWT in the claims to have a convenient way to access identity data works well. However, every identity claim you put in the principal ends up in the auth cookie. If you inspect the cookie, you will notice it doubles in size with an access token. As you add more claims in the principal the auth cookie gets bigger. You may hit HTTP header limits in a prod environment with many auth cookies. In IIS, the default max limit is set to 8KB-16KB depending on the version. You can increase the limit, but this means bigger payloads per request because of the cookies.

There are many ways to quell this problem, like a user session to keep all JWTs out of the auth cookie. If you have current code that accesses the identity through the principal, then this is not ideal. Moving identity data out of the principal is risky because it may lead to a complete rewrite.

One alternative is to use the SessionStore found in CookieAuthenticationOptions. OWIN, for example, has a similar property. Implement the ITicketStore interface and find a way to persist data in the back-end. Setting the SessionStore property defines a container to store the identity across requests. Only a session identifier gets sent to the browser in the auth cookie.

Say you want to use in-memory persistence instead of the auth cookie:

public class InMemoryTicketStore : ITicketStore
{
  private readonly IMemoryCache _cache; 

  public InMemoryTicketStore(IMemoryCache cache)
  {
    _cache = cache;
  } 

  public Task RemoveAsync(string key)
  {
    _cache.Remove(key); 

    return Task.CompletedTask;
  } 

  public Task<AuthenticationTicket> RetrieveAsync(string key)
  {
    var ticket = _cache.Get<AuthenticationTicket>(key); 

    return Task.FromResult(ticket);
  } 

  public Task RenewAsync(string key, AuthenticationTicket ticket)
  {
    _cache.Set(key, ticket); 

    return Task.CompletedTask;
  } 

  public Task<string> StoreAsync(AuthenticationTicket ticket)
  {
    var key = ticket.Principal.Claims
      .First(c => c.Type == ClaimTypes.Name).Value; 

    _cache.Set(key, ticket); 

    return Task.FromResult(key);
  }
}

Set an instance of this class in SessionStore inside CookieAuthenticationOptions, these options are set in the ConfigureServices method in the Startup class. One caveat is getting an instance since it needs a provider from BuildServiceProvider. A temporary IoC container here feels hacky and pines after a better solution.

A better approach is to use the options pattern in ASP.NET Core. Post-configuration scenarios set or change options at startup. With this solution, you leverage dependency injection without reinventing the wheel.

To put in place this options pattern, implement IPostConfigureOptions<CookieAuthenticationOptions>:

public class ConfigureCookieAuthenticationOptions
  : IPostConfigureOptions<CookieAuthenticationOptions>
{
  private readonly ITicketStore _ticketStore; 

  public ConfigureCookieAuthenticationOptions(ITicketStore ticketStore)
  {
    _ticketStore = ticketStore;
  } 

  public void PostConfigure(string name,
           CookieAuthenticationOptions options)
  {
    options.SessionStore = _ticketStore;
  }
}

To register both InMemoryTicketStore and ConfigureCookieAuthenticationOptions, place this in ConfigureServices:

services.AddTransient<ITicketStore, InMemoryTicketStore>();
services.AddSingleton<IPostConfigureOptions<CookieAuthenticationOptions>,
  ConfigureCookieAuthenticationOptions>();

Make sure you make this change in the Startup class. If you peek inside Configure<CookiePolicyOptions>, for example, and crack open the code. Note the pattern; configuration runs through a singleton object and a lambda expression. ASP.NET Core uses this same options pattern under the hood. Now, firing this up in the browser and inspecting the auth cookie will have a much smaller footprint.

Conclusion

Implementing an auth cookie is seamless in ASP.NET Core 2.1. You configure cookie options, invoke middleware, and set identity claims. Sign in and sign out methods work based on an authentication scheme. Auth cookie options allow the app to react to back-end events and set a session store. The auth cookie is flexible enough to work well with any enterprise solution. 



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 2016 Hosting, ASP.NET Core 2.2.1 Hosting, ASP.NET MVC 6 Hosting and SQL 2017 Hosting.


Tag cloud

Sign in