3 November, 2023

ASP.NET 4.x Notes

Request Header

private void ConfigureAuth(IAppBuilder builder)
{
  builder.Use((context, next) =>
  {
    if (context?.Request?.Headers["X-Teach"] == null)
    {
      context.Request.Headers.Add("X-Teach", new[] { "something" });
    }
    return next.Invoke();
  });
}

Security

Remove information from requests in Web.config:

<system.web>
  <httpRuntime maxRequestLength="12288" enableVersionHeader="false" targetFramework="4.7.2" />
</system.web>
<system.webServer>
  <security>
    <requestFiltering removeServerHeader="true" />
  </security>
  <httpProtocol>
    <customHeaders>
      <remove name="X-Powered-By" />
    </customHeaders>
  </httpProtocol>
</system.webServer>

In Global.asax remove X-AspNetMvc-Version

MvcHandler.DisableMvcResponseHeader = true;

Add Content-Security-Policy header in Web.config:

<system.webServer>
  <httpProtocol>
    <customHeaders>
      <add name="Content-Security-Policy" value="frame-ancestors 'none'" />
    </customHeaders>
  </httpProtocol>
</system.webServer>
<system.web>
  <httpCookies sameSite="Strict" requireSSL="true" />
<system.web>

Regedit check which .NET Framework is installed HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full

CORS for Angular Client

Old SignalR documentation https://docs.microsoft.com/en-us/aspnet/signalr/overview/guide-to-the-api/hubs-api-guide-javascript-client

using System.Web.Http.Cors;

public static class WebApiConfig {
  public static void Register(HttpConfiguration aConfig) {
    config.EnableCors(new EnableCorsAttribute("http://localhost:4200", "*", "*"));
  }
}

QR Code Generator

Using the QRCoder package. GitHub https://github.com/codebude/QRCoder

[HttpGet]
public HttpResponseMessage QrCode()
{
    using (var stream = new MemoryStream())
    using (var gen = new QRCodeGenerator())
    using (var qrCode = new QRCode(gen.CreateQrCode("https://tea.ch/", QRCodeGenerator.ECCLevel.Q)))
    {
        qrCode.GetGraphic(10).Save(stream, ImageFormat.Png);
        var result = new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new ByteArrayContent(stream.ToArray())
        };

        result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
        {
            FileName = "teach-qr-code.png"
        };

        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

        return result;
    }
}

TOTP

NuGet Otp.NET.

using OtpNet;
//...
var secret = Base32Encoding.ToString(KeyGeneration.GenerateRandomKey(20));

//...
var totp = new Totp(Base32Encoding.ToBytes(secret));
var isValid = totp.VerifyTotp(totpCode, out long windowMatched, new VerificationWindow(previous: 1, future: 1));

/* Optional: when we want to find the exact window:
var now = DateTime.UtcNow;
var window = Math.Floor((now - new DateTime(1970, 1, 1)).TotalSeconds / 30);
var nowTotpCode = totp.ComputeTotp(now);

// windowMatched == window // -1 +1
*/