Critical Developers

Programmers Knowledge Base

Globally Encrypt Decrypt Query string in ASP.Net core using Middleware

Like HttpModule in ASP.Net Webform we have Middleware in ASP.Net Core.

So lets create a custom middleware which will encrypt/ decrypt querystring globally.

With this approach, Just take care of TempData because we are redirecting a request twice here so would recommend if you are using tempdata use its Keep Method to preserve it on your RazorPage. Lets start-

Step-1: Create a custom middleware

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions;
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MyDemos.CustomMiddlewares
{
    // Ref-https://docs.microsoft.com/en-us/aspnet/core/migration/http-modules?view=aspnetcore-3.1
    public class EncryptDecryptQueryStringsMiddleware
    {
        private const string PARAMETER_NAME = "_enc";
        private const string ENCRYPTION_KEY = "key";
        private static ASCIIEncoding encoding;
        private static IHttpContextAccessor _httpContextAccessor;
        private readonly IDataProtector _protector;
        private readonly RequestDelegate _next;
        public EncryptDecryptQueryStringsMiddleware(IHttpContextAccessor httpContextAccessor, IDataProtectionProvider provider, RequestDelegate next)
        {
            encoding = new ASCIIEncoding();
            _httpContextAccessor = httpContextAccessor;
            _protector = provider.CreateProtector
("YOURSECRETKEY");
            _next = next;
        }
        public async Task Invoke(HttpContext context)
        {
            if (UriHelper.GetEncodedUrl(context.Request).Contains("?"))
            {
                string contextQuery = GetAbsoluteUri().Query.ToString();
                //
                if (contextQuery.Contains(PARAMETER_NAME))
                {
                    var enc = context.Request.Query[PARAMETER_NAME];
                    enc = _protector.Unprotect(enc);
                    QueryString queryString = new QueryString(enc);
                    context.Request.QueryString = queryString;
                }
                else if (context.Request.Method == "GET")
                {
                    if (contextQuery != "")
                    {
                        string encryptedQuery = _protector.Protect(contextQuery);
                        string redirectToPagePath = context.Request.Path.Value + "?" + PARAMETER_NAME + "=" + encryptedQuery;
                        context.Response.Redirect(redirectToPagePath);
                    }
                }
            }
            await _next.Invoke(context);
        }
        #region Utils
        private static Uri GetAbsoluteUri()
        {
            var request = _httpContextAccessor.HttpContext.Request;
            UriBuilder uriBuilder = new UriBuilder();
            uriBuilder.Scheme = request.Scheme;
            uriBuilder.Host = request.Host.Host;
            uriBuilder.Path = request.Path.ToString();
            uriBuilder.Query = request.QueryString.ToString();
            return uriBuilder.Uri;
        }

        #endregion
    }
    public static class QueryStringMiddlewareExtensions
    {
        public static IApplicationBuilder UseEncryptDecryptQueryStringsMiddleware(this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<EncryptDecryptQueryStringsMiddleware>();
        }
    }
}

Step-2: Use/Inject middleware in Startup.cs

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                //app.UseStatusCodePagesWithRedirects("/Error/{0}");
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            //
            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseEncryptDecryptQueryStringsMiddleware();
            //
            app.UseRouting();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapRazorPages();
            });
        }
Thats it !!

Encrypt Decrypt in ASP.Net Core

Here we will discuss encryption and decryption with an example in asp.net core.
We use Protect() and Unprotect() methods of IDataProtector interface in ASP.Net Core to encrypt and decrypt respectively.
Using IDataProtector we can encrypt/decrypt querystring, any sensitive data, connection string and etc.
So Lets start,

Create a class as shown below:-

using Microsoft.AspNetCore.DataProtection;
namespace MyDemo
{
    public class CustomIDataProtection
    {
        private readonly IDataProtector _protector;
        public CustomIDataProtection(IDataProtectionProvider provider)
        {
            _protector = provider.CreateProtector("YOURSECRETKEY"); // you can pass any string as key
        }
        public string ProtectData(string data)
        {
            return _protector.Protect(data);
        }
        public string UnProtectData(string data)
        {
            return _protector.Unprotect(data);
        }
    }
}

Now In your PageModel or Controller use above class as shown below:-

    public class IndexModel : PageModel
    {
        private readonly CustomIDataProtection _protector;
        public IndexModel(CustomIDataProtection provider)
        {
            _protector = provider;
        }
        public void OnGet()
        {
	string encrypted= _protector.ProtectData("mysensitivedata");
	string decrypted= _protector.UnProtectData(encrypted);
        }
   }

Thats it !!