Search code examples
asp.net-identity.net-5

ConfigureApplicationCookie loginPath no longer respected after changing default policy


I have an .NET 5 application that uses Identity as the primary login for users. I also have a series of API endpoints that require outside access so these are protected by a JWT token ("xx.xx.api") Authentication scheme. All of this works fine.

I wanted to have the internal endpoints to be able to respond to postman requests without having to login through the identity part of the application. So I have created a seperate JWT token (xxxxx.postman) that our internal postman can utilize. I have created a Policy through the "AuthorizationPolicyBuilder" that requires either a role or a specific claim, which is now my default policy. Everything apart from the "LoginPath"/"AccessDenied" set through the ConfigureApplicationCookie" seems to work after this change, the login cookie responds to changes to the timeout, but I cannot get these two to work with the new multi policy scheme.

Before the change, this code works and redirects users correctly to the login page, if they are Unauthenticated.

services.AddAuthorization(cfg =>
        {
            cfg.AddPolicy("xxxxx", opt => opt.RequireClaim("xxxxxxxClaim", "xx.xx.api"));
        });

        services.ConfigureApplicationCookie(options =>
        {
            // Cookie settings
            options.Cookie.HttpOnly = true;
            options.ExpireTimeSpan = TimeSpan.FromMinutes(60);

            options.LoginPath = "/Login";
            options.AccessDeniedPath = "/Login";
            options.SlidingExpiration = true;
        });

With the new Scheme in place, the application no longer redirects the unauthenticated user.

var multiSchemePolicy = new AuthorizationPolicyBuilder(
                IdentityConstants.ApplicationScheme,
                JwtBearerDefaults.AuthenticationScheme)
              .RequireAuthenticatedUser()
              .RequireAssertion(assert =>
                assert.User.HasClaim(claim => claim.Type == "xxxxxxxClaim" && claim.Value == "xxxxx.postman") ||
                assert.User.IsInRole("yyyyyyyyy"))
              .Build();

        services.AddAuthorization(cfg =>
        {
            cfg.DefaultPolicy = multiSchemePolicy;
            cfg.AddPolicy("xxxxx", opt => opt.RequireClaim("xxxxxxxxClaim", "xx.xx.api"));
        });

        services.ConfigureApplicationCookie(options =>
        {
            // Cookie settings
            options.Cookie.HttpOnly = true;
            options.ExpireTimeSpan = TimeSpan.FromMinutes(60);

            options.LoginPath = "/Login";
            options.AccessDeniedPath = "/Login";
            options.SlidingExpiration = true;
        });

I have found that I can make it work again by setting

app.UseStatusCodePages(async context => {
            var response = context.HttpContext.Response;

            if (response.StatusCode == (int)HttpStatusCode.Unauthorized)
            {
                response.Redirect("/login");
               }
        });

Not that it explains why the ConfigureApplicationCookie LoginPath is nolonger respected.

I would greatly appreciate if anyone could explain why this happens and whether or not my workaround is sound. Thanks!


Solution

  • I opted to answer my own question as this fixes the problem.

    app.UseStatusCodePages(async context => {
                var response = context.HttpContext.Response;
    
                if (response.StatusCode == (int)HttpStatusCode.Unauthorized)
                {
                    response.Redirect("/login");
                   }
            });