aspnet / Mvc

[Archived] ASP.NET Core MVC is a model view controller framework for building dynamic web sites with clean separation of concerns, including the merged MVC, Web API, and Web Pages w/ Razor. Project moved to https://github.com/aspnet/AspNetCore

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Return 401 on invalid jwt token instead of login page.

ronaldpostmagnaversum opened this issue · comments

Is this a Bug or Feature request?:

Bug ( or misconfiguration )

Steps to reproduce (preferably a link to a GitHub repo with a repro project):

This is the link to a test project:
https://github.com/ronaldpostmagnaversum/razor-pages-mixed-authentication

Description of the problem:

I am having a problem configuring authentication for a razor-pages app that also has an api.
I want to have cookie authentication for the razor pages and jwt tokens for the api.
The problem is that I can use this mixed authentication and it validates correctly, but when the jwt token is not valid the api returns the login page with a 200 status, instead of a 401.
When I turn off the cookie authentication everything works fine. Can somebody tell me if there is something wrong with the configuration or if this is a bug?
Thanks in advance.

ConfigureServices:

services.AddMvc(config =>
            {
                var policy = new AuthorizationPolicyBuilder(IdentityConstants.ApplicationScheme,
                                                            JwtBearerDefaults.AuthenticationScheme)
                                 .RequireAuthenticatedUser()
                                 .Build();
                config.Filters.Add(new AuthorizeFilter(policy));
            }).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

Configure:

app.UseMvc(config =>
            {
                var defaultPolicy = new AuthorizationPolicyBuilder(new[]
                        { IdentityConstants.ApplicationScheme,
                          JwtBearerDefaults.AuthenticationScheme })
                    .RequireAuthenticatedUser()
                    .Build();
            });

On the controller I have this attribute:

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]

Version of Microsoft.AspNetCore.Mvc or Microsoft.AspNetCore.App or Microsoft.AspNetCore.All:

Microsoft.AspNetCore.App 2.1.1

commented

Thanks for contacting us, @ronaldpostmagnaversum.
@javiercn, can you please look into this? Thanks!

@ronaldpostmagnaversum The best way to achieve your scenario is to use an authentication policy provider on top of your cookies and jwt authentication schemes.

@HaoK Can you point him to a sample on how to achieve this?

Sure take a look at this sample https://github.com/aspnet/AuthSamples/tree/master/samples/PathSchemeSelection which is switching between schemes based on request path as an example

Hi @HaoK and @javiercn,

Thanks for the answers and the reference to the sample project. I fixed it using the ForwardDefaultSelector and tell it to use 'Bearer' AuthHandler on the api path like this:

options.ForwardDefaultSelector = ctx =>
{
return ctx.Request.Path.StartsWithSegments("/api") ? "Bearer" : null;
};

I am still wondering if it should work when setting the authentication scheme on the controllers. Is this a bug or does it only work without Razor Pages?

Since you likely have the cookie authentication set as the default in order for your mixed authentication setup to work, the cookie authentication handler is responsible of handing the default challenge request and redirects to your login page. You can affect that behavior in a few ways; try one of the solutions mentioned in this Stack Overflow question.

Thanks @poke for the information. I can't seem to get it working trying the solutions on StackOverflow. I will leave it using the "ForwardDefaultSelector" option as this is a sufficient solution for now.

I believe is because you have both schemes in the global auth filter and one of them is going to fail when sending JWTs

@HaoK can confirm. I don’t remember the exact behavior

Yeah you can't mix cookies and bearer since they do completely different things on challenges, bearer wants to return a 401, and cookies wants to return a 302 to the login page, so only one of them can successfully challenge

Closing as there's no more action to be taken here