question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

404 Not Found When accessing controller action annotated with [Authorize]

See original GitHub issue

Hi, I’ve been using openiddict since aspnet core 1.1 (working great), and decided to switch to aspnet core 2.0 recently. However, I am encountering some odd issue while I was migrating it. I am using password flow, and depending on the user role, I am trying to prohibit/allow user’s access to an action. In short, I keep getting 404 Not Found. Tested on aspnet core 1.1, but it works well.

core 1.1:

public class ValuesController : Controller
{
    [Authorize(Roles = "Admin")]
    [HttpGet("admin")]
    public string Admin()
    {
        return "success";
    }
}

startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<TestContext>(options =>
{
	options.UseSqlServer(Configuration.GetConnectionString("TestAPI"),
	 b => b.MigrationsAssembly("Test.API"));
	options.UseOpenIddict();
});    

services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
    // ...        
})
.AddEntityFrameworkStores<TestContext>()
.AddDefaultTokenProviders();

services.Configure<IdentityOptions>(options =>
{
	options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
	options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
	options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
});

services.AddOpenIddict(options =>
{              
	options.AddEntityFrameworkCoreStores<TestContext>();
	options.AddMvcBinders();
	options.EnableTokenEndpoint("/connect/token");
	options.AllowPasswordFlow();
	options.DisableHttpsRequirement();

	options.UseJsonWebTokens();
	options.AddEphemeralSigningKey();
});                  

services.AddMvc();        
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, TestDbInitializer seeder)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();

JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();

app.UseJwtBearerAuthentication(new JwtBearerOptions
{
	Authority = "http://localhost:50181/",
	Audience = "resource_server",
	RequireHttpsMetadata = false,
	TokenValidationParameters = new TokenValidationParameters
	{
		NameClaimType = OpenIdConnectConstants.Claims.Subject,
		RoleClaimType = OpenIdConnectConstants.Claims.Role
	}
});

app.UseIdentity();
app.UseOpenIddict();         
app.UseOAuthValidation();
app.UseMvcWithDefaultRoute();
}`

core 2.0

public class ValuesController : Controller
{
    [Authorize(Roles = "Admin")]
    [HttpGet("admin")]
    public string Admin()
    {
        return "success";
    }
}

startup.cs

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {          
        services.AddDbContext<TestContext>(options =>
        {
            options.UseSqlServer(Configuration.GetConnectionString("TestAPI"),
            b => b.MigrationsAssembly("TestAPI"));
            options.UseOpenIddict();
        });
		
        services.AddIdentity<ApplicationUser, IdentityRole>(options =>
        {
		    // ...
        })
            .AddEntityFrameworkStores<TestContext>()
            .AddDefaultTokenProviders();

      
        services.AddAuthentication()
            .AddOAuthValidation();

        services.Configure<IdentityOptions>(options =>
        {
            options.ClaimsIdentity.UserNameClaimType = OpenIdConnectConstants.Claims.Name;
            options.ClaimsIdentity.UserIdClaimType = OpenIdConnectConstants.Claims.Subject;
            options.ClaimsIdentity.RoleClaimType = OpenIdConnectConstants.Claims.Role;
        });

    
        services.AddOpenIddict(options =>
        {               
            options.AddEntityFrameworkCoreStores<TestContext>();
            options.AddMvcBinders();
            options.EnableTokenEndpoint("/connect/token");
            options.AllowPasswordFlow();
            options.DisableHttpsRequirement();

            options.UseJsonWebTokens();
            options.AddEphemeralSigningKey();
        });
        
        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, DbInitializer seeder)
    {
        app.UseDeveloperExceptionPage();

        JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
        JwtSecurityTokenHandler.DefaultOutboundClaimTypeMap.Clear();

		// Error saying it is deprecated
        app.UseJwtBearerAuthentication(new JwtBearerOptions
        {
            Authority = "http://localhost:50181/",
            Audience = "resource_server",
            RequireHttpsMetadata = false,
            TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = OpenIdConnectConstants.Claims.Subject,
                RoleClaimType = OpenIdConnectConstants.Claims.Role
            }
        });

        app.UseAuthentication();
        app.UseMvcWithDefaultRoute();
        app.UseWelcomePage();    
    }
}
}

Tested on aspnet core 1.1 using postman, /connect/token returns valid JWT token and /api/values/admin returns 200 OK with the return message “success”.

When testing with core 2.0, first I commented out

app.UseJwtBearerAuthentication section 
&& options.UseJsonWebTokens();
&& options.AddEphemeralSigningKey();

and /connect/token returns valid JWT token, but /api/values/admin returns 404 NOT FOUND.

I guess it is not recognizing [Authorize] annotation. Help is appreciated!

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

63reactions
kevinchaletcommented, Oct 29, 2017

Yo,

You’re seeing a 404 response because the cookies handler managed by Identity is trying to redirect you to the login page, for which you don’t have a controller.

To prevent that, decorate your API endpoints with [Authorize(AuthenticationSchemes = "Bearer")]. Alternatively, you can use path-based selection: https://stackoverflow.com/questions/46464469/how-to-configureservices-authentication-based-on-routes-in-asp-net-core-2-0/46475072#46475072.

1reaction
tplookercommented, Nov 5, 2017

@kkagill I could be wrong, but does the below work?

services.AddAuthentication(o =>
                {
                    o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                })
                .AddJwtBearer(options =>
                {
                    options.Audience = "resource-server";
                    options.Authority = Configuration["frontEndUrl"];
                    options.RequireHttpsMetadata = false;
                    options.IncludeErrorDetails = true;
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        NameClaimType = OpenIdConnectConstants.Claims.Subject,
                        RoleClaimType = OpenIdConnectConstants.Claims.Role
                    };
                })
Read more comments on GitHub >

github_iconTop Results From Across the Web

Web api core returns 404 when adding Authorize attribute
It happens when your API is not authorized and your redirect URL doesn't exist. When authentication fails, Web API will send a 401...
Read more >
why is 404 happened when i request action in a web API ...
when i set [Authorize] to controller , the request "/login/login",the response is "404 not found". when i delete [Authorize], ...
Read more >
How to handle 404 errors in ASP.NET Core MVC
A simple solution is to check for the HTTP status code 404 in the response. If found, you can redirect the control to...
Read more >
404 error when send request to web api controller
404 is "page not found". You are looking for a route that does not exist. As "j snooze" mentions, as part of the...
Read more >
Handling errors in ASP.NET Core Web API - DevTrends
This post looks at the best ways to handle exceptions, validation and other invalid requests such as 404s in ASP.NET Core Web API...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found