using System.Text; using Microsoft.Extensions.Options; using Microsoft.Extensions.Primitives; using Microsoft.Net.Http.Headers; using StopShopping.Services.Extensions; namespace StopShopping.Api.Middlewares; public class DevelopmentCookieMiddleware { public DevelopmentCookieMiddleware( RequestDelegate requestDelegate, IOptions options) { _next = requestDelegate; _appOptions = options.Value; } private readonly RequestDelegate _next; private readonly AppOptions _appOptions; public async Task InvokeAsync(HttpContext httpContext) { int? port = null; var origin = httpContext.Request.Headers[HeaderNames.Origin]; if (origin.Count > 0 && null != origin[0]) { Uri uri = new(origin[0]!); port = uri.Port; } else { var referer = httpContext.Request.Headers[HeaderNames.Referer]; if (referer.Count > 0 && null != referer[0]) { Uri uri = new(referer[0]!); port = uri.Port; } } if (port.HasValue) { var modified = ModifyCookie(httpContext.Request.Headers[HeaderNames.Cookie], port.Value); httpContext.Request.Headers[HeaderNames.Cookie] = modified; } httpContext.Response.OnStarting(() => { if (port.HasValue) { var cookieHeader = httpContext.Response.Headers[HeaderNames.SetCookie]; ModifyResponseCookie(cookieHeader, httpContext, port.Value); } return Task.CompletedTask; }); await _next(httpContext); } private void ModifyResponseCookie(StringValues cookieHeader, HttpContext httpContext, int port) { foreach (var cookieItem in cookieHeader) { if (cookieItem != null) { var cookies = cookieItem.Split(';'); foreach (var item in cookies) { if (null != item) { var pairs = item.Split('='); if (2 == pairs.Length) { if (pairs[0].Trim() == _appOptions.CSRFCookieName) { var val = pairs[1]; httpContext.Response.Cookies.Delete(pairs[0]); httpContext.Response.Cookies.Append($"{_appOptions.CSRFCookieName}_{port}", val); } else if (pairs[0].Trim() == HttpExtensions.REFRESH_TOKEN_COOKIE_KEY) { var val = pairs[1]; httpContext.Response.Cookies.Delete(pairs[0]); httpContext.Response.Cookies.Append($"{HttpExtensions.REFRESH_TOKEN_COOKIE_KEY}_{port}", val); } } } } } } } private StringValues ModifyCookie(StringValues cookie, int port) { List result = []; var csrfCookieName = $"{_appOptions.CSRFCookieName}_{port}"; var refreshTokenCookieName = $"{HttpExtensions.REFRESH_TOKEN_COOKIE_KEY}_{port}"; foreach (var cookieItem in cookie) { if (null != cookieItem) { StringBuilder itemBuilder = new(); var cookies = cookieItem.Split(';'); foreach (var item in cookies) { if (null != item) { var pairs = item.Split('='); if (pairs.Length == 2) { if (0 != itemBuilder.Length) itemBuilder.Append(';'); if (pairs[0].Trim() == csrfCookieName) { itemBuilder.Append(_appOptions.CSRFCookieName); itemBuilder.Append('='); itemBuilder.Append(pairs[1].Trim()); } else if (pairs[0].Trim() == refreshTokenCookieName) { itemBuilder.Append(HttpExtensions.REFRESH_TOKEN_COOKIE_KEY); itemBuilder.Append('='); itemBuilder.Append(pairs[1].Trim()); } else { itemBuilder.Append(item); } } else { itemBuilder.Append(item); } } } result.Add(itemBuilder.ToString()); } } return new StringValues(result.ToArray()); } }