nopcommerce middleware for redirect not execute the invokeAsync - nopcommerce

I try to add a redirect middleware for nopcommerce.
My middleware:
public class RedirectMiddleware
{
private readonly RequestDelegate _next;
public RedirectMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext context)
{
var currentUrl = context.Request.GetDisplayUrl().ToString().ToLower();
var newUrl = currentUrl.Replace("xy", "");
if (currentUrl.Contains("xy") && !string.IsNullOrEmpty(newUrl) && newUrl != context.Request.Path.Value)
{
var parsed = HttpUtility.UrlEncode(newUrl);
context.Request.Path = parsed;
//context.Response.StatusCode = 301;
context.Response.Redirect(parsed, true);
}
//or call the next middleware in the request pipeline
await _next(context);
}
}
NopStartup:
public void Configure(IApplicationBuilder application)
{
application.UseMiddleware<RedirectMiddleware>();
}
The InvokeAsync is never execute.
Have I forgotten something or do something wrong?

Related

Why is my hubconnection on but the method is not being fired?

I've set up signalr in my blazor server side application and for some reason this hubconnection is not being triggered, when the hubconnection is on, it completely ignores the BroadcastData method and doesnt even fire it:
private HubConnection hubConnection;
private string _hubUrl;
protected override async Task OnInitializedAsync()
{
string baseUrl = NavigationManager.BaseUri;
_hubUrl = baseUrl.TrimEnd('/') + SignalRHub.HubUrl;
_hubConnection = new HubConnectionBuilder()
.WithUrl(_hubUrl)
.Build();
hubConnection.On<ClientDTO>("BroadcastData", BroadcastData);
await hubConnection.StartAsync();
}
private void BroadcastData(ClientDTO payload)
{
dashboardData = payload;
StateHasChanged();
}
I have everything setup for this to be "working" but clearly it isn't working and I'm completely lost at what could be the problem... Please take a look at what I have so far and see if you can see what's going on:
Startup:
public Startup(IConfiguration configuration)
{
Configuration = configuration;
StartTimer();
}
private void StartTimer()
{
_timer = new System.Timers.Timer();
_timer.Interval = 5000;
_timer.Elapsed += TimerElapsed;
_timer.Start();
}
private void TimerElapsed(Object source, ElapsedEventArgs e)
{
Trigger();
}
public void Trigger()
{
try
{
using (HttpClient client = new HttpClient())
{
//Trigger on elapsed
var response = client.GetAsync(Configuration.GetConnectionString("ApiTriggerURL")).Result;
}
}
catch
{
Console.WriteLine("something terrible has happened...");
}
}
services.AddScoped(typeof(SignalRHub));
services.AddScoped<IHub, SignalRHub>();
services.AddScoped<HttpClient>();
services.AddSignalR();
services.AddResponseCompression(opts =>
{
opts.MimeTypes = ResponseCompressionDefaults.MimeTypes.Concat(
new[] { "application/octet-stream" });
});
public void Configure(IApplicationBuilde app, IWebHostEnvironment env)
{
app.UseResponseCompression();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
endpoints.MapHub<SignalRHub>(SignalRHub.HubUrl);
});
}
appsettings.json: (fyi, the trigger is working, the api endpoint is being hit as it returns a status 200 ok result)
"ConnectionStrings":
{
"ApiTriggerURL": "http://localhost:5000/api/SignalRHub/GetMyData"
}
Then we have my api controller: (here you can see the status 200 ok)
private readonly SignalRHub _signalRHub;
public SignalRHubController(SignalRHub signalRHub)
{
_signalRHub = signalRHub;
}
[HttpGet]
public ObjectResult GetMyData()
{
try
{
Task.WhenAll(_signalRHub.BroadcastData()); // Call hub broadcast method
return this.StatusCode((int)HttpStatusCode.OK, "trigger has been triggered");
}
catch
{
return this.StatusCode((int)HttpStatusCode.InternalServerError, "christ, the ting is broken fam");
}
}
When we look into the _signalRHub.BroadcastData(), we see this:
public class SignalRHub : Hub, IHub
{
private readonly ClientService _clientService;
readonly IHubContext<SignalRHub> _hubContext;
public const string HubUrl = "/chathub"; //this is being read in the startup in the endpoints
public SignalRHub(ClientService clientService, IHubContext<SignalRHub> hubContext)
{
_clientService = clientService;
_hubContext = hubContext;
}
public async Task BroadcastData()
{
var data = _clientService .GetDataAsync().Result;
await _hubContext.Clients.All.SendAsync("BroadcastData", data); //send data to all clients
}
}
And this in turn should basically do this signalrhub every x seconds (depending on timer)
I know my code is a whole load of madness, but please look pass this and help me to understand why this isn't working! Thank you in advance!
Try following:
hubConnection.On<ClientDTO>("BroadcastData", (payload)=>
BroadcastData(payload);
);
Instead of
hubConnection.On<ClientDTO>("BroadcastData", BroadcastData);

signalr : after Authentication i get error 400 (Bad Request) in client-side

after Task.CompletedTask i get error 400 (Bad Request) in "client-side"
What am I missing to go through the Authentication phase?
Server:
public class Startup : StartupBase
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = options.DefaultScheme;
options.DefaultChallengeScheme = options.DefaultScheme;
})
.AddJwtBearer(options =>
{
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Headers["Authorization"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken))
{
context.Token = accessToken.ToString().Substring("Token ".Length).Trim();
}
return Task.CompletedTask;
}
};
});
services.AddSignalR();
services.AddSingleton<IMongoDBService, MongoDBService>();
}
public override void Configure(IApplicationBuilder builder, IEndpointRouteBuilder routes, IServiceProvider serviceProvider)
{
builder.UseCors("CorsPolicy");
builder.UseAuthentication();
builder.UseEndpoints(endpoints =>
{
endpoints.MapHub<PrintEventsHub>("/Events/PrintEventsHub");
endpoints.MapHub<NotificationEventsHub>("/Events/NotificationEventsHub");
});
}
}
Hub:
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class NotificationEventsHub : Hub//, IPrinterEventsHub
{
private readonly ISession _session;
private readonly ITelegramServices _telegramServices;
private readonly ISaveEventToDBServices _saveEventToDBServices;
private readonly IHubContext<NotificationEventsHub> _Context;
private string ConnectionID;
public NotificationEventsHub(IHubContext<NotificationEventsHub> context,
ISession session,
ITelegramServices telegramServices,
ISaveEventToDBServices saveEventToDBServices)
{
_Context = context;
_session = session;
_telegramServices = telegramServices;
_saveEventToDBServices = saveEventToDBServices;
}
public override Task OnConnectedAsync()
{
ConnectionID = this.Context.ConnectionId;
var connectedUser = Context.User.Identity;
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
return base.OnDisconnectedAsync(exception);
}
public async Task GetNotificationMsg(string jsonStringNotification)
{
}
}
Client:
public static async Task<bool> SendPrinterEventToCloudManager()
{
var SignalRConnectionInfo = new SignalRConnectionInfo();
SignalRConnectionInfo.AccessToken = "test";
string _SignalRUrl =
"https://localhost:44300/Events/NotificationEventsHub";
try
{
HubConnection connection = new HubConnectionBuilder().WithUrl(_SignalRUrl,
o => o.AccessTokenProvider = () => Task.FromResult(SignalRConnectionInfo.AccessToken)).Build();
await connection.StartAsync();
await connection.InvokeAsync("GetNotificationMsg", "testmsg");
return true;
}
catch (Exception ex)
{
var msg = ex.Message;
return false;
}
}
i am try to use JwtBearer token and after i read the value what's next step to aprrove that the user Authentication?

.net core , how to handle route with extra leading slash

I need to handle an incoming request which is of the form:
//ohif/study/1.1/series
Note the exta slash at the front
My controller signature is:
[Route("ohif/study/{studyUid}/series")]
[HttpGet]
public IActionResult GetStudy(string studyUid)
If I modify the incoming request to /ohif/study/1.1/series it works fine
however when I use //ohif/study/1.1/series, the route is not hit
Additionally I also tried: [Route("/ohif/study/{studyUid}/series")]
and [Route("//ohif/study/{studyUid}/series")]
Both fail. I unfortunately cannot change the incoming request as it is from an external application. Is there some trick to handle this route? I am working in .NET Core 3.0.
Update NOTE:
I have logging activated and I see that asp.net core is analyzing the route, I have the message:
No candidates found for the request path '//ohif/study/1.1/series'
for the logger Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware
What about the middleware to handle double slash?
app.Use((context, next) =>
{
if (context.Request.Path.Value.StartsWith("//"))
{
context.Request.Path = new PathString(context.Request.Path.Value.Replace("//", "/"));
}
return next();
});
Rewrite the URL at the web server-level, e.g. for IIS, you can use the URL Rewrite Module to automatically redirect //ohif/study/1.1/series to /ohif/study/1.1/series. This isn't a job for your application.
I took Ravi's answer and fleshed out a middleware. The middleware is nice because it is encapsulated, easily testable, can inject a logger, more readable, etc.
app.UseDoubleSlashHandler();
The code and tests:
public class DoubleSlashMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<DoubleSlashMiddleware> _logger;
public DoubleSlashMiddleware(RequestDelegate next, ILogger<DoubleSlashMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task InvokeAsync(HttpContext context)
{
_logger.LogInformation($"Invoking {nameof(DoubleSlashMiddleware)} on {context.Request.Path}");
context.Request.Path = context.Request.Path.FixDoubleSlashes();
// Call the next delegate/middleware in the pipeline.
await _next(context);
}
}
public static class DoubleSlashMiddlewareExtensions
{
public static IApplicationBuilder UseDoubleSlashHandler(
this IApplicationBuilder builder)
{
return builder.UseMiddleware<DoubleSlashMiddleware>();
}
}
[TestClass()]
public class DoubleSlashMiddlewareTests
{
private DoubleSlashMiddleware _sut;
private ILogger<DoubleSlashMiddleware> _logger;
private bool _calledNextMiddlewareInPipeline;
[TestInitialize()]
public void TestInitialize()
{
_logger = Substitute.For<ILogger<DoubleSlashMiddleware>>();
Task Next(HttpContext _)
{
_calledNextMiddlewareInPipeline = true;
return Task.CompletedTask;
}
_sut = new DoubleSlashMiddleware(Next, _logger);
}
[TestMethod()]
public async Task InvokeAsync()
{
// Arrange
_calledNextMiddlewareInPipeline = false;
// Act
await _sut.InvokeAsync(new DefaultHttpContext());
// Assert
_logger.ReceivedWithAnyArgs(1).LogInformation(null);
Assert.IsTrue(_calledNextMiddlewareInPipeline);
}
}
String method to do the replacement:
public static class RoutingHelper
{
public static PathString FixDoubleSlashes(this PathString path)
{
if (string.IsNullOrWhiteSpace(path.Value))
{
return path;
}
if (path.Value.Contains("//"))
{
return new PathString(path.Value.Replace("//", "/"));
}
return path;
}
}
[TestClass()]
public class RoutingHelperTests
{
[TestMethod()]
[DataRow(null, null)]
[DataRow("", "")]
[DataRow("/connect/token", "/connect/token")]
[DataRow("//connect/token", "/connect/token")]
[DataRow("/connect//token", "/connect/token")]
[DataRow("//connect//token", "/connect/token")]
[DataRow("/connect///token", "/connect/token")]
public void FixDoubleSlashes(string input, string expected)
{
// Arrange
var path = new PathString(input);
// Act
var actual = path.FixDoubleSlashes();
// Assert
Assert.AreEqual(expected, actual.Value);
}
}

ASP.NET core 2 act as reverse proxy usering rewrite middleware

I'm struggling to make my asp.net core 2 app act like a reverse proxy using URL Rewrite rules.
I have the following in my startup.cs:
var rewriteRules = new RewriteOptions()
.AddRedirectToHttps();
.AddRewrite(#"^POC/(.*)", "http://192.168.7.73:3001/$1", true);
app.UseRewriter(rewriteRules);
The rewrite rule is exactly as it is in my IIS settings (which I'm trying to replace with this method) which works fine.
I'm assuming it has something to do with forwarding the headers maybe? Or maybe I just don't understand how the Rewrite Middleware is supposed to work, if you want the requests to be forwarded instead of just rewritten relative to current hostname.
A reverse proxy can be emulated/implemeted within a middleware :
First the startup class where we add a IUrlRewriter service and the ProxyMiddleware.
public class Startup
{
private readonly IConfiguration _configuration;
public Startup(IConfiguration configuration)
{
_configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IUrlRewriter>(new SingleRegexRewriter(#"^/POC/(.*)", "http://192.168.7.73:3001/$1"));
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseRewriter(new RewriteOptions().AddRedirectToHttps());
app.UseMiddleware<ProxyMiddleware>();
}
}
Next we will create a basic implementation of IUrlRewriter. The RewriteUri method must transform the HttpContext into an absolute Uri. Or null if the url should not be redirected in the middleware.
public interface IUrlRewriter
{
Task<Uri> RewriteUri(HttpContext context);
}
public class SingleRegexRewriter : IUrlRewriter
{
private readonly string _pattern;
private readonly string _replacement;
private readonly RegexOptions _options;
public SingleRegexRewriter(string pattern, string replacement)
: this(pattern, replacement, RegexOptions.None) { }
public SingleRegexRewriter(string pattern, string replacement, RegexOptions options)
{
_pattern = pattern ?? throw new ArgumentNullException(nameof(pattern));
_replacement = replacement ?? throw new ArgumentNullException(nameof(pattern));
_options = options;
}
public Task<Uri> RewriteUri(HttpContext context)
{
string url = context.Request.Path + context.Request.QueryString;
var newUri = Regex.Replace(url, _pattern, _replacement);
if (Uri.TryCreate(newUri, UriKind.Absolute, out var targetUri))
{
return Task.FromResult(targetUri);
}
return Task.FromResult((Uri)null);
}
}
And then the Middleware (stolen from an old verison of aspnet proxy repo) and customized. It get the IUrlRewrite service as parameter of Invoke method.
The pipeline is :
Try rewrite url
Create a HttpRequestMessage
Copy Request Header and content
Send the request
Copy response header
Copy response content
done
Et voila
public class ProxyMiddleware
{
private static readonly HttpClient _httpClient = new HttpClient(new HttpClientHandler()
{
AllowAutoRedirect = false,
MaxConnectionsPerServer = int.MaxValue,
UseCookies = false,
});
private const string CDN_HEADER_NAME = "Cache-Control";
private static readonly string[] NotForwardedHttpHeaders = new[] { "Connection", "Host" };
private readonly RequestDelegate _next;
private readonly ILogger<ProxyMiddleware> _logger;
public ProxyMiddleware(
RequestDelegate next,
ILogger<ProxyMiddleware> logger)
{
_next = next;
_logger = logger;
}
public async Task Invoke(HttpContext context, IUrlRewriter urlRewriter)
{
var targetUri = await urlRewriter.RewriteUri(context);
if (targetUri != null)
{
var requestMessage = GenerateProxifiedRequest(context, targetUri);
await SendAsync(context, requestMessage);
return;
}
await _next(context);
}
private async Task SendAsync(HttpContext context, HttpRequestMessage requestMessage)
{
using (var responseMessage = await _httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead, context.RequestAborted))
{
context.Response.StatusCode = (int)responseMessage.StatusCode;
foreach (var header in responseMessage.Headers)
{
context.Response.Headers[header.Key] = header.Value.ToArray();
}
foreach (var header in responseMessage.Content.Headers)
{
context.Response.Headers[header.Key] = header.Value.ToArray();
}
context.Response.Headers.Remove("transfer-encoding");
if (!context.Response.Headers.ContainsKey(CDN_HEADER_NAME))
{
context.Response.Headers.Add(CDN_HEADER_NAME, "no-cache, no-store");
}
await responseMessage.Content.CopyToAsync(context.Response.Body);
}
}
private static HttpRequestMessage GenerateProxifiedRequest(HttpContext context, Uri targetUri)
{
var requestMessage = new HttpRequestMessage();
CopyRequestContentAndHeaders(context, requestMessage);
requestMessage.RequestUri = targetUri;
requestMessage.Headers.Host = targetUri.Host;
requestMessage.Method = GetMethod(context.Request.Method);
return requestMessage;
}
private static void CopyRequestContentAndHeaders(HttpContext context, HttpRequestMessage requestMessage)
{
var requestMethod = context.Request.Method;
if (!HttpMethods.IsGet(requestMethod) &&
!HttpMethods.IsHead(requestMethod) &&
!HttpMethods.IsDelete(requestMethod) &&
!HttpMethods.IsTrace(requestMethod))
{
var streamContent = new StreamContent(context.Request.Body);
requestMessage.Content = streamContent;
}
foreach (var header in context.Request.Headers)
{
if (!NotForwardedHttpHeaders.Contains(header.Key))
{
if (header.Key != "User-Agent")
{
if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray()) && requestMessage.Content != null)
{
requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value.ToArray());
}
}
else
{
string userAgent = header.Value.Count > 0 ? (header.Value[0] + " " + context.TraceIdentifier) : string.Empty;
if (!requestMessage.Headers.TryAddWithoutValidation(header.Key, userAgent) && requestMessage.Content != null)
{
requestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, userAgent);
}
}
}
}
}
private static HttpMethod GetMethod(string method)
{
if (HttpMethods.IsDelete(method)) return HttpMethod.Delete;
if (HttpMethods.IsGet(method)) return HttpMethod.Get;
if (HttpMethods.IsHead(method)) return HttpMethod.Head;
if (HttpMethods.IsOptions(method)) return HttpMethod.Options;
if (HttpMethods.IsPost(method)) return HttpMethod.Post;
if (HttpMethods.IsPut(method)) return HttpMethod.Put;
if (HttpMethods.IsTrace(method)) return HttpMethod.Trace;
return new HttpMethod(method);
}
}
Bonus : some other Rewriter
public class PrefixRewriter : IUrlRewriter
{
private readonly PathString _prefix;
private readonly string _newHost;
public PrefixRewriter(PathString prefix, string newHost)
{
_prefix = prefix;
_newHost = newHost;
}
public Task<Uri> RewriteUri(HttpContext context)
{
if (context.Request.Path.StartsWithSegments(_prefix))
{
var newUri = context.Request.Path.Value.Remove(0, _prefix.Value.Length) + context.Request.QueryString;
var targetUri = new Uri(_newHost + newUri);
return Task.FromResult(targetUri);
}
return Task.FromResult((Uri)null);
}
}
public class MergeRewriter : IUrlRewriter
{
private readonly List<IUrlRewriter> _rewriters = new List<IUrlRewriter>();
public MergeRewriter()
{
}
public MergeRewriter(IEnumerable<IUrlRewriter> rewriters)
{
if (rewriters == null) throw new ArgumentNullException(nameof(rewriters));
_rewriters.AddRange(rewriters);
}
public MergeRewriter Add(IUrlRewriter rewriter)
{
if (rewriter == null) throw new ArgumentNullException(nameof(rewriter));
_rewriters.Add(rewriter);
return this;
}
public async Task<Uri> RewriteUri(HttpContext context)
{
foreach (var rewriter in _rewriters)
{
var targetUri = await rewriter.RewriteUri(context);
if(targetUri != null)
{
return targetUri;
}
}
return null;
}
}
// In Statup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IUrlRewriter>(new MergeRewriter()
.Add(new PrefixRewriter("/POC/API", "http://localhost:1234"))
.Add(new SingleRegexRewriter(#"^/POC/(.*)", "http://192.168.7.73:3001/$1")));
}
Edit
I found a project to do same but with way more other feature https://github.com/damianh/ProxyKit as a nuget package

Secure swagger docs page with username and password Asp Net Core 2.1

I am using Asp.Net Core 2.1 Web Api with Swashbuckle.aspnetcore.swagger
I want to secure api documentation page with username and password before granting access.
Sample documention page
To make sure its not accessible by the public
I have found a solution on GitHub and applied it to my project. its working as expected.
Below code copied from https://github.com/domaindrivendev/Swashbuckle.WebApi/issues/384#issuecomment-410117400
public class SwaggerBasicAuthMiddleware
{
private readonly RequestDelegate next;
public SwaggerBasicAuthMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task InvokeAsync(HttpContext context)
{
//Make sure we are hitting the swagger path, and not doing it locally as it just gets annoying :-)
if (context.Request.Path.StartsWithSegments("/swagger") && !this.IsLocalRequest(context))
{
string authHeader = context.Request.Headers["Authorization"];
if (authHeader != null && authHeader.StartsWith("Basic "))
{
// Get the encoded username and password
var encodedUsernamePassword = authHeader.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries)[1]?.Trim();
// Decode from Base64 to string
var decodedUsernamePassword = Encoding.UTF8.GetString(Convert.FromBase64String(encodedUsernamePassword));
// Split username and password
var username = decodedUsernamePassword.Split(':', 2)[0];
var password = decodedUsernamePassword.Split(':', 2)[1];
// Check if login is correct
if (IsAuthorized(username, password))
{
await next.Invoke(context);
return;
}
}
// Return authentication type (causes browser to show login dialog)
context.Response.Headers["WWW-Authenticate"] = "Basic";
// Return unauthorized
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
}
else
{
await next.Invoke(context);
}
}
public bool IsAuthorized(string username, string password)
{
// Check that username and password are correct
return username.Equals("SpecialUser", StringComparison.InvariantCultureIgnoreCase)
&& password.Equals("SpecialPassword1");
}
public bool IsLocalRequest(HttpContext context)
{
//Handle running using the Microsoft.AspNetCore.TestHost and the site being run entirely locally in memory without an actual TCP/IP connection
if (context.Connection.RemoteIpAddress == null && context.Connection.LocalIpAddress == null)
{
return true;
}
if (context.Connection.RemoteIpAddress.Equals(context.Connection.LocalIpAddress))
{
return true;
}
if (IPAddress.IsLoopback(context.Connection.RemoteIpAddress))
{
return true;
}
return false;
}
}
public static class SwaggerAuthorizeExtensions
{
public static IApplicationBuilder UseSwaggerAuthorized(this IApplicationBuilder builder)
{
return builder.UseMiddleware<SwaggerBasicAuthMiddleware>();
}
}
In Startup.cs
app.UseAuthentication(); //Ensure this like is above the swagger stuff
app.UseSwaggerAuthorized();
app.UseSwagger();
app.UseSwaggerUI();
Copied from mguinness's answer on Github:
In .NET Core you use middleware, instead of a DelegatingHandler:
public class SwaggerAuthorizedMiddleware
{
private readonly RequestDelegate _next;
public SwaggerAuthorizedMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
if (context.Request.Path.StartsWithSegments("/swagger")
&& !context.User.Identity.IsAuthenticated)
{
context.Response.StatusCode = StatusCodes.Status401Unauthorized;
return;
}
await _next.Invoke(context);
}
}
You will also need an extension method to help adding to pipeline:
public static class SwaggerAuthorizeExtensions
{
public static IApplicationBuilder UseSwaggerAuthorized(this IApplicationBuilder builder)
{
return builder.UseMiddleware<SwaggerAuthorizedMiddleware>();
}
}
Then add to Configure method in Startup.cs just before using Swagger:
app.UseSwaggerAuthorized();
app.UseSwagger();
app.UseSwaggerUi();
There's also a variant solution posted there how to do it with basic auth.

Resources