HexaEightMiddleware 1.6.55

dotnet add package HexaEightMiddleware --version 1.6.55
NuGet\Install-Package HexaEightMiddleware -Version 1.6.55
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="HexaEightMiddleware" Version="1.6.55" />
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add HexaEightMiddleware --version 1.6.55
#r "nuget: HexaEightMiddleware, 1.6.55"
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install HexaEightMiddleware as a Cake Addin
#addin nuget:?package=HexaEightMiddleware&version=1.6.55

// Install HexaEightMiddleware as a Cake Tool
#tool nuget:?package=HexaEightMiddleware&version=1.6.55

HexaEight Middleware

How To Use This Library

Sample Middleware Code (Startup and Configuration Section)

public class Startup
{
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.Add(new ServiceDescriptor(typeof(HexaEightResource), new HexaEightResource("18ADCEA59T56FE1427ABC652763DFC47134BDFDBC", "https://tokenserverurl:8443")));
            services.AddSingleton<IAuthenticationService, AuthenticationMiddleware>();
            services.AddAuthentication();
            services.AddAuthorization();
            services.AddCors();
            services.AddControllers();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            //Enable CORS for all origns including credentials. We will validate the user agents in the authentication section
            app.UseCors(x => x
                .AllowAnyMethod()
                .AllowAnyHeader()
                .SetIsOriginAllowed(origin => true)
                .AllowCredentials());

            //Add HexaEight Middleware first in the pipeline so that valid request can be authenticated.

            app.UseMiddleware<HexaEightEngine.Middleware>();
            app.UseRouting();
            app.Use(async (context, next) =>
            {
                await next();

                if (context.Response.StatusCode == (int)HttpStatusCode.Unauthorized)
                {
                    context.Response.StatusCode = (int)HttpStatusCode.OK;
                    await context.Response.Body.WriteAsync(Encoding.UTF8.GetBytes("UnAuthorized - Access Denied"));
                }

            });

            app.UseAuthentication();
            app.UseAuthorization();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
}

Sample Weather Controller Code with Authorization for Get and Post

    public class WeatherForecast
    {
        public DateTime Date { get; set; }

        public int TemperatureC { get; set; }

        public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);

        public string Summary { get; set; }
        
        public bool isauthenticated { get; set; }
        public string loggedinuser { get; set; }
        public string location { get; set; }


    }

namespace HexaEight_Middleware_SampleDemo.Controllers
{
    [ApiController]
    [Route("[controller]")]
    public class WeatherForecastController : ControllerBase
    {
        private static readonly string[] Summaries = new[]
        {
            "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
        };


        private static readonly string[] locations = new[]
        {
            "Aberdeen", "Anacortes","Arlington", "Auburn","Battle Ground","Bellevue","Bellingham","Bonney Lake","Bothell","Bremerton","Burien"
        };

        private readonly ILogger<WeatherForecastController> _logger;

        public WeatherForecastController(ILogger<WeatherForecastController> logger)
        {
            _logger = logger;
        }

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                isauthenticated = false,
                loggedinuser = "",
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                location = locations[rng.Next(locations.Length)],
                 Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }

        [HttpGet("{resource}")]
        [Authorize(AuthenticationSchemes = "Bearer")]
        public IEnumerable<WeatherForecast> Get(string resource)
        {
            var rng = new Random();
                return Enumerable.Range(1, 1).Select(index => new WeatherForecast
                {
                    isauthenticated = true,
                    loggedinuser = HttpContext.User.Identity.Name.ToString(),
                    Date = DateTime.Now.AddDays(index),
                    TemperatureC = rng.Next(-20, 55),
                    location = resource,
                    Summary = Summaries[rng.Next(Summaries.Length)]
                })
                .ToArray();
        }


        [HttpPost("{resource}")]
        [Authorize(AuthenticationSchemes = "Bearer")]
        public async Task<IEnumerable<WeatherForecast>> Post(string resource)
        {

            string body = "";
            using (StreamReader stream = new StreamReader(HttpContext.Request.Body))
            {
                body = await stream.ReadToEndAsync();
            }
            body = body.ToString().TrimEnd('\0').Trim();

            var rng = new Random();
            return Enumerable.Range(1, 1).Select(index => new WeatherForecast
            {
                isauthenticated = true,
                loggedinuser = HttpContext.User.Identity.Name.ToString(),
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                location = body,
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }


    }
}

Sample Authentication Middleware Code For Additional Authorization

public class AuthenticationMiddleware : IAuthenticationService
{
        static string ComputeSHA512(string s)
        {
            StringBuilder sb = new StringBuilder();
            using (SHA512 sha512 = SHA512.Create())
            {
                byte[] hashValue = sha512.ComputeHash(Encoding.UTF8.GetBytes(s));
                foreach (byte b in hashValue)
                {
                    sb.Append($"{b:X2}");
                }
            }

            return sb.ToString();
        }
        public Task<AuthenticateResult> AuthenticateAsync(HttpContext context, string scheme)
        {
            try
            {
                if (context.User.Identity.IsAuthenticated && context.User.Identity.AuthenticationType == "HexaEight Identity")
                {

                    try
                    {
                        // Check 1: Weed out MITM. This will ensure replaying the same request through some other orign wont work.
                        // Note: This Check wont work for desktop and mobile client apps since orign is expected to be null. Use Check 2 to validate the request
                        if (ComputeSHA512(context.Request.Headers["Origin"].FirstOrDefault().Trim().Replace("https://", "").Replace("http://", "").ToLower()) != context.User.Claims.FirstOrDefault(c => c.Type == "OriginHash").Value)
                        {
                            return Task.FromResult(AuthenticateResult.Fail("UnAuthorized Request - Access Denied"));
                        }
                    }
                    catch { }

                    // Check 2: Validate if the request origniated through list a list of accepted user agents/client applications hash values.
                    // For example if you are expecting api requests from www.client.com, www.thirdparty.com you will add the 512 hash of www.client.com to below list.
                    // For Mobile and Desktop apps, generate the 512 Hash of the executuable and add it below.
                    var listofclienthashes = new string[] { "B5E57824692A50458E29E1E35FCAFE1F55DE18C35DBE0901B5AF887BAC068D08E3B34CEA2B722395D0E4CDFC1292D5E8950894D9FFFB48E834026789CC5F1DCA" };

                    if (!listofclienthashes.Any(s => s.Contains(context.User.Claims.FirstOrDefault(c => c.Type == "OriginHash").Value)))
                    {
                        return Task.FromResult(AuthenticateResult.Fail("UnAuthorized User Agent - Access Denied"));
                    }

                    // Check3 : Validate if the request is more than X seconds, if so reject the request.
                    // The below test tests to see if the request is received after 10 seconds, if so the requst is rejected
                    if (Int64.Parse((context.User.Claims.FirstOrDefault(c => c.Type == "RequestReceivedAt").Value)) - Int64.Parse((context.User.Claims.FirstOrDefault(c => c.Type == "RequestTimeStamp").Value)) > 10)
                    {
                        return Task.FromResult(AuthenticateResult.Fail("Expired Request - Access Denied"));
                    }

                    // TBD -> Check 4 : While Check3 will Prevent most replay attacks, using a  bloom filter based on 'RequestHash' value available in the user claims, can repel all replay attacks

                    AuthenticationTicket at = new AuthenticationTicket(context.User, "HexaEight");
                    return Task.FromResult(AuthenticateResult.Success(at));
                }
                return Task.FromResult(AuthenticateResult.Fail("UnAuthorized"));
            }
            catch
            {
                return Task.FromResult(AuthenticateResult.Fail("UnAuthorized"));
            }


        }

        public Task ChallengeAsync(HttpContext context, string scheme, AuthenticationProperties properties)
        {
            context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
            return Task.CompletedTask;
        }

        public Task ForbidAsync(HttpContext context, string scheme, AuthenticationProperties properties)
        {
            throw new NotImplementedException();
        }

        public Task SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties)
        {

            return Task.CompletedTask;
        }

        public Task SignOutAsync(HttpContext context, string scheme, AuthenticationProperties properties)
        {
            throw new NotImplementedException();
        }
}



NOTE: Please be aware that, at the moment, HexaEight Middleware accommodates Controller responses ONLY in Array or IEnumerable formats.

Product Compatible and additional computed target framework versions.
.NET net5.0 is compatible.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.0 is compatible.  netcoreapp3.1 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.6.55 84 5/4/2024
1.6.54 92 5/4/2024
1.6.53 75 4/18/2024
1.6.52 62 4/18/2024
1.6.51 75 4/17/2024
1.6.50 84 4/16/2024
1.6.49 213 3/1/2024
1.6.48 486 11/2/2023
1.6.47 388 11/2/2023
1.6.46 432 11/1/2023
1.6.45 420 10/29/2023
1.6.44 392 10/28/2023
1.6.43 449 10/15/2023
1.6.42 496 9/27/2023
1.6.41 503 9/18/2023
1.6.40 522 9/13/2023
1.6.39 556 8/21/2023
1.6.38 532 8/20/2023
1.6.37 572 6/12/2023
1.6.35 526 5/14/2023
1.6.34 641 5/14/2023
1.6.33 599 5/14/2023
1.6.32 631 3/29/2023
1.6.31 649 3/29/2023
1.6.30 675 3/28/2023
1.6.29 669 3/28/2023
1.6.28 677 2/18/2023
1.6.27 687 2/14/2023
1.6.26 717 2/12/2023
1.6.25 735 2/5/2023
1.6.24 732 2/3/2023
1.6.23 706 2/2/2023
1.6.22 723 2/2/2023
1.6.21 687 1/31/2023
1.6.20 726 1/29/2023
1.6.19 727 1/29/2023
1.6.18 716 1/29/2023
1.6.17 708 1/29/2023
1.6.16 748 1/26/2023
1.6.15 735 1/22/2023
1.6.14 672 1/21/2023
1.6.13 701 1/21/2023
1.6.12 765 1/21/2023
1.6.11 739 1/18/2023
1.6.10 767 1/15/2023
1.6.9 700 1/15/2023
1.6.8 753 1/15/2023