404 Not Found When accessing controller action annotated with [Authorize]
See original GitHub issueHi, 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:
- Created 6 years ago
- Comments:6 (1 by maintainers)
Top GitHub Comments
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.@kkagill I could be wrong, but does the below work?