patbef-ServiceInside/ServiceInside/Filter/TrustedHeader.cs

245 lines
9.6 KiB
C#
Raw Normal View History

2024-01-29 16:26:54 +01:00
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Primitives;
using ServiceInside.Controllers;
using ServiceShared;
using ServiceShared.Https;
using ServiceShared.Models.Response;
using ServiceShared.Models.Response.Exception;
namespace ServiceInside.Filter
{
public class TrustedHeader : ActionFilterAttribute, IAsyncResultFilter, IAsyncAuthorizationFilter
{
private static Log.Types _LogType = Log.Types.INFO;
/// <summary>
/// Sets the log type
/// </summary>
/// <param name="Log.Types">Log.Types</param>
public static void SetLog(Log.Types logType)
{
_LogType = logType;
}
/// <summary>
/// Validates request header
/// </summary>
/// <param name="context">Current context</param>
/// <returns></returns>
public virtual async Task OnAuthorizationAsync(AuthorizationFilterContext context)
{
if (context.HttpContext == null ||
context.HttpContext.Request == null ||
context.HttpContext.Request.Headers == null ||
context.HttpContext.Request.Body == null ||
context.HttpContext.Request.ContentLength <= 0 ||
!context.HttpContext.Request.Headers.ContainsKey("User-Agent") ||
!context.HttpContext.Request.Headers.ContainsKey("Content-Type") ||
!context.HttpContext.Request.Headers.ContainsKey("Client-Hash") ||
!context.HttpContext.Request.Headers.ContainsKey("Client-Key") ||
!context.HttpContext.Request.IsHttps)
{
context.Result = new JsonResult(new InvalidClientException());
return;
}
// User Agent validator
StringValues userAgent = new StringValues();
if (!context.HttpContext.Request.Headers.TryGetValue("User-Agent", out userAgent) ||
!Request.ValidUserAgent(userAgent))
{
context.Result = new JsonResult(new InvalidClientException());
return;
}
// Content Type validator
StringValues contentType = new StringValues();
if (!context.HttpContext.Request.Headers.TryGetValue("Content-Type", out contentType) ||
contentType.ToString() != "application/json")
{
context.Result = new JsonResult(new InvalidClientException());
return;
}
// Client hash validator
StringValues clientHash = new StringValues();
if (!context.HttpContext.Request.Headers.TryGetValue("Client-Hash", out clientHash) ||
!Request.ValidHeaderHash(clientHash.ToString()))
{
context.Result = new JsonResult(new InvalidClientException());
return;
}
// Client Public Key validator
StringValues clientKey = new StringValues();
if (!context.HttpContext.Request.Headers.TryGetValue("Client-Key", out clientKey))
{
context.Result = new JsonResult(new InvalidClientException());
return;
}
try
{
// check if valid base64 encoded
byte[] publicKey = Convert.FromBase64String(clientKey.ToString());
}
catch
{
context.Result = new JsonResult(new InvalidClientException());
}
// Check if client signature in headers
if (context.RouteData != null &&
context.RouteData.Values != null &&
context.RouteData.Values.ContainsKey("controller"))
{
string controllerName = (string?)context.RouteData.Values["controller"];
if (!string.IsNullOrEmpty(controllerName) && controllerName.ToLower() != "exchange")
{
if (!context.HttpContext.Request.Headers.ContainsKey("Client-Signature") ||
!context.HttpContext.Request.Headers.ContainsKey("Client-Signature-Key"))
{
context.Result = new JsonResult(new InvalidClientException());
return;
}
}
}
}
/// <summary>
/// Logs request in debug mode
/// </summary>
/// <param name="context"></param>
/// <param name="next"></param>
/// <returns></returns>
public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
{
if (_LogType == Log.Types.DEBUG)
{
string headers = "";
foreach (var header in context.HttpContext.Request.Headers)
{
headers += header.Key + "=" + header.Value + "\r\n";
}
string message = "";
if (context != null &&
context.HttpContext != null &&
context.HttpContext.Connection != null &&
context.HttpContext.Connection.RemoteIpAddress != null)
{
message = context.HttpContext.Connection.RemoteIpAddress.ToString() + " " +
context.ActionDescriptor.DisplayName + "\r\nHeaders:" + headers;
}
Log.Debug(message);
}
await next();
}
/// <summary>
/// Adds Trusted Headers to the response
/// </summary>
/// <param name="context"></param>
public override void OnActionExecuted(ActionExecutedContext context)
{
base.OnActionExecuted(context);
if (context != null && context.HttpContext != null && context.HttpContext.Response != null &&
context.HttpContext.Response.Headers != null && context.Controller != null)
{
BaseController controller = (BaseController)context.Controller;
string signatureData = null;
if (context.Result != null)
{
JsonResult jsonResult = (JsonResult)context.Result;
if (jsonResult != null && jsonResult.Value != null && jsonResult.Value.GetType() == typeof(EncryptedResponse))
{
EncryptedResponse encryptedResponse = ((EncryptedResponse)jsonResult.Value);
if (!string.IsNullOrEmpty(encryptedResponse.encrypted_content))
{
signatureData = encryptedResponse.encrypted_content;
}
else
{
signatureData = encryptedResponse.descriptor;
}
}
}
// User Agent
if (!context.HttpContext.Response.Headers.ContainsKey("User-Agent"))
{
context.HttpContext.Response.Headers.Add("User-Agent", "BefundAppServer");
}
else
{
context.HttpContext.Response.Headers["User-Agent"] = "BefundAppServer";
}
// Content Type
if (!context.HttpContext.Response.Headers.ContainsKey("Content-Type"))
{
context.HttpContext.Response.Headers.Add("Content-Type", "application/json");
}
else
{
context.HttpContext.Response.Headers["Content-Type"] = "application/json";
}
// Server Hash
if (!context.HttpContext.Response.Headers.ContainsKey("Server-Hash"))
{
context.HttpContext.Response.Headers.Add("Server-Hash", Request.GeServerHash());
}
else
{
context.HttpContext.Response.Headers["Server-Hash"] = Request.GeServerHash();
}
// Server Key
if (!context.HttpContext.Response.Headers.ContainsKey("Server-Key"))
{
context.HttpContext.Response.Headers.Add("Server-Key", controller.GetServerPublicKey());
}
else
{
context.HttpContext.Response.Headers["Server-Key"] = controller.GetServerPublicKey();
}
if(!string.IsNullOrEmpty(signatureData))
{
// Server Signature
if (!context.HttpContext.Response.Headers.ContainsKey("Server-Signature"))
{
context.HttpContext.Response.Headers.Add("Server-Signature", controller.GetServerSignature(signatureData));
}
else
{
context.HttpContext.Response.Headers["Server-Signature"] = controller.GetServerSignature(signatureData);
}
// Server Signature Key
if (!context.HttpContext.Response.Headers.ContainsKey("Server-Signature-Key"))
{
context.HttpContext.Response.Headers.Add("Server-Signature-Key", controller.GetServerSignatureKey());
}
else
{
context.HttpContext.Response.Headers["Server-Signature-Key"] = controller.GetServerSignatureKey();
}
}
}
}
}
}