Search code examples
asp.net-core.net-coreasp.net-core-middleware

Redirect to login from .NET Core auth middleware


I have an ASP.NET Core 8 MVC app, and I'm using auth middleware to authenticate and ensure that an access token (JWT) resides in the cookies.

Working to make sure that when an action with an [Authorize] attribute, and the token (authentication) and a specific cookie (authorization) don't exist, the user is redirected to a login page to re-authenticate.

How would I go about re-directing the user to the /login page given the below code?

public static IApplicationBuilder UseAuth(this IApplicationBuilder app)
{
    app.UseAuthentication();
    app.Use(async (ctx, next) =>
    {
        if (ctx.Request.Headers.ContainsKey(AuthorizationHeader))
        {
            ctx.Request.Headers.Remove(AuthorizationHeader);
        }

        if (ctx.Request.Cookies.ContainsKey(AccessTokenCookieName))
        {
            var authenticateResult = await ctx.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);

            if (authenticateResult.Succeeded && authenticateResult.Principal is not null)
            {
                ctx.User = authenticateResult.Principal;
            }

            var path = ctx.Request.Path;
        }
        else
        {
            // REDIRECT TO LOGIN?
        }

        await next();
    });

    return app;
}

Thank you in advance for any insight you can provide.


Solution

  • In ASP.NET Core, you typically manage redirection to a login page when authorization fails by configuring the authentication services and the challenge response in the Startup.cs or Program.cs file, not directly in the middleware. However, if you want to handle this within a custom middleware, you can do so by checking if the authentication result was unsuccessful and then redirecting the user accordingly. Something like this.

    var authenticateResult = await ctx.AuthenticateAsync(JwtBearerDefaults.AuthenticationScheme);
    
    if (authenticateResult.Succeeded && authenticateResult.Principal is not null)
    {
       ctx.User = authenticateResult.Principal;
       await next();
    }
    else
    {
       if (!ctx.Request.Path.StartsWithSegments("/login"))
       {
         ctx.Response.Redirect($"/login?ReturnUrl={Uri.EscapeDataString(ctx.Request.Path + ctx.Request.QueryString)}");
       }
       else
       {
         await next(); 
         delegate/middleware in the pipeline
       }
    }