Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sending Response body in JwtBearerEvents.OnAuthenticationFailed

Tags:

asp.net-core

I have a .NET Core 2.0 application using OAuth Bearer Auth with an Azure AD V2 endpoint. I want to the exception message to be returned to the user if there is a 500 error. I have the following code to do that:

            options.Events = new JwtBearerEvents
            {
                // This used to be options.Notifications = new OpenIdConnectAuthenticationNotifications
                OnTokenValidated = AzureAdAuthCallbacks.TokenValidated,
                OnAuthenticationFailed = async context =>
                {
                    context.Response.ContentType = "text/plain";
                    await context.Response.WriteAsync(context.Exception.Message);
                }
            };
        }

When validation fails, that code does execute, but the response dosn't get returned. I get a stack trace.

This is the message:

System.InvalidOperationException: StatusCode cannot be set because the response has already started.

With this line of note:

at WebCsProj.Infrastructure.RequestMetadataMiddelware.<>c.<b__0_0>d.MoveNext() in C:\Users\justin.dearing\source\repos\my-solution\WebCsProj\Infrastructure\RequestMetadataMiddelware.cs:line XXX

However, that piece of middleware finishes successfully:

public static class RequestMetadataMiddelware
{
    public static IApplicationBuilder UseRequestMetadataExtractor(this IApplicationBuilder app)
    {
        return app.Use(async (context, next) =>
        {
            // I don't set a status code here.
            // Some code that works is here
            await next.Invoke(); // The debugger indicates the code makes it here:
        });
    }
}

What can I do to debug this or what is the right way to set the response? Is there a way to stop the middle-ware chain from executing in OnAuthenticationFailed?

like image 822
Justin Dearing Avatar asked Mar 28 '18 14:03

Justin Dearing


1 Answers

You can write the response body after invoking the next middleware using OnStarting method:

OnAuthenticationFailed = context =>
{
    context.Response.OnStarting(async () =>
    {
        context.Response.ContentType = "text/plain";
        await context.Response.WriteAsync(context.Exception.Message);
    });

    return Task.CompletedTask;
}
like image 125
Andriy Tolstoy Avatar answered Nov 19 '22 04:11

Andriy Tolstoy