Hi,
I am trying to create 2 separate swagger pages- one public and the other one private for internal use.
I was able to create separate pages using OperationProcessor but I am facing issues in restricting access to the private page. I tried to use a MessageHandler (DelegatingHandler) to check if the user is authenticated before the private swagger page is displayed. I followed the solution given for SwashBuckle on this page -
public class SwaggerAccessMessageHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
if (IsSwagger(request) && !Thread.CurrentPrincipal.Identity.IsAuthenticated)
{
var response = request.CreateResponse(HttpStatusCode.Unauthorized);
return Task.FromResult(response);
}
else
{
return base.SendAsync(request, cancellationToken);
}
}
private bool IsSwagger(HttpRequestMessage request)
{
return request.RequestUri.PathAndQuery.StartsWith("/swagger");
}
}
And I tried to register the Message Handler from the GlobalConfiguration in Global.asax.cs -
GlobalConfigurationMessageHandlers.Add(new SwaggerAccessMessageHandler());
Problem is that this message handler is not called when the swagger api is called( swagger page is displayed). However, this handler is called for the other apis present in the project.
Is there any other way to register the message handler in NSwag? If not, is there any other way to restrict the access to the private swagger page?
@jeremyVignelles wrote a middleware to do that (ASP.NET Core). I think you can easily write this as an OWIN middleware:
/// <summary>
/// The extension methods that extends <see cref="IApplicationBuilder" /> for authentication purposes
/// </summary>
public static class ApplicationBuilderExtensions
{
/// <summary>
/// Requires authentication for paths that starts with <paramref name="pathPrefix" />
/// </summary>
/// <param name="app">The application builder</param>
/// <param name="pathPrefix">The path prefix</param>
/// <returns>The application builder</returns>
public static IApplicationBuilder RequireAuthenticationOn(this IApplicationBuilder app, string pathPrefix)
{
return app.Use((context, next) =>
{
// First check if the current path is the swagger path
if (context.Request.Path.HasValue && context.Request.Path.Value.StartsWith(pathPrefix, StringComparison.InvariantCultureIgnoreCase))
{
// Secondly check if the current user is authenticated
if (!context.User.Identity.IsAuthenticated)
{
return context.ChallengeAsync();
}
}
return next();
});
}
}
Most helpful comment
@jeremyVignelles wrote a middleware to do that (ASP.NET Core). I think you can easily write this as an OWIN middleware: