Team,
I have a custom authentication handler like this
public class MyAuthenticationSchemeOptions: AuthenticationSchemeOptions
{
}
public class MyAuthenticationHandler: AuthenticationHandler<MyAuthenticationSchemeOptions>
{
private ICacheProviderService _cacheService;
private readonly IConfiguration _configuration;
public MyAuthenticationHandler(
IOptionsMonitor<MyAuthenticationSchemeOptions> options,
ILoggerFactory logger,
UrlEncoder encoder,
ISystemClock clock,
ICacheProviderService cacheService,
IConfiguration configuration)
: base(options, logger, encoder, clock)
{
_cacheService = cacheService;
_configuration = configuration;
}
protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
if (!Request.Headers.ContainsKey("Header")){
Context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
//await Context.Response.WriteAsync("request doesn't contains header");
return AuthenticateResult.Fail("request doesn't contains header");
}
//further logic of success
}
public static class AuthenticateExtensions
{
public static AuthenticationBuilder AddAuth(this AuthenticationBuilder builder, Action<GlobalGroupAuthenticationSchemeOptions> configureOptions, string scheme)
{
return builder.AddScheme<MyAuthenticationSchemeOptions, MyAuthenticationHandler>(scheme,"abcd", configureOptions);
}
}
Controller is decorated with
[Authorize(AuthenticationSchemes = "MyAuthenticationScheme")]
Startup.cs
ConfigureServices(IServiceCollection services){
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "MyAuthenticationScheme";
options.DefaultChallengeScheme = "MyAuthenticationScheme";
}).AddAuth(x => { }, "MyAuthenticationScheme");
}
Configure(IApplicationBuilder app, IWebHostEnvironment env,ILogger<Startup> logger){
//Other logic is removed as not required here
app.UseRouting();
app.UseAuthorization();
}
This code returns only status code as Unauthorized. None of the error message returns in response if request doesn't have header. The moment I uncomment this line await Context.Response.WriteAsync("request doesn't contains header");
I immediately receive an unhandled exception. Any suggestion please on the way to return a message in response in the case of custom AuthenticationHandler service
info: Middleware.MyAuthenticationHandler[7]
MyAuthenticationScheme was not authenticated. Failure message: Authentication Header Not Found
fail: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[1]
An unhandled exception has occurred while executing the request.
System.InvalidOperationException: StatusCode cannot be set because the response has already started.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAlreadyStartedException(String value)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.set_StatusCode(Int32 value)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode(Int32 value)
at Microsoft.AspNetCore.Http.DefaultHttpResponse.set_StatusCode(Int32 value)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.HandleChallengeAsync(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.ChallengeAsync(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
warn: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware[2]
The response has already started, the error handler will not be executed.
fail: Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HM53499HNTTT", Request id "0HM53499HNTTT:00000002": An unhandled exception was thrown by the application.
System.InvalidOperationException: StatusCode cannot be set because the response has already started.
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ThrowResponseAlreadyStartedException(String value)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.set_StatusCode(Int32 value)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode(Int32 value)
at Microsoft.AspNetCore.Http.DefaultHttpResponse.set_StatusCode(Int32 value)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.HandleChallengeAsync(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.AuthenticationHandler`1.ChallengeAsync(AuthenticationProperties properties)
at Microsoft.AspNetCore.Authentication.AuthenticationService.ChallengeAsync(HttpContext context, String scheme, AuthenticationProperties properties)
at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.HandleException(HttpContext context, ExceptionDispatchInfo edi)
at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.<Invoke>g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
Thank you, i was implemented the Context.Response.OnStarting method but it was not working. You solution works.