Should return 401 but is returning 404
See original GitHub issueHi!
I’m trying to test my web api when user has an invalid access token, but instead of 401, I’m getting an 404 result.
Here is my startup
public class Startup
{
private readonly IHostingEnvironment _environment;
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
_environment = env;
}
public IConfigurationRoot Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton(Configuration);
services.AddCors();
// Add framework services.
services.AddMvc();
services.AddAuthorization();
// Register the OpenIddict services.
// Note: use the generic overload if you need
// to replace the default OpenIddict entities.
services.AddOpenIddict()
// Register the Entity Framework stores.
.AddEntityFrameworkCoreStores<ApplicationDbContext>()
// Register the ASP.NET Core MVC binder used by OpenIddict.
// Note: if you don't call this method, you won't be able to
// bind OpenIdConnectRequest or OpenIdConnectResponse parameters.
.AddMvcBinders()
// .UseJsonWebTokens()
// Enable the token endpoint (required to use the password flow).
.EnableTokenEndpoint("/connect/token")
.EnableRevocationEndpoint("/connect/logout")
// Allow client applications to use the grant_type=password flow.
.AllowPasswordFlow()
.AllowRefreshTokenFlow()
// During development, you can disable the HTTPS requirement.
.DisableHttpsRequirement()
.SetAccessTokenLifetime(TimeSpan.FromHours(5))
.SetRefreshTokenLifetime(TimeSpan.FromHours(10))
// Register a new ephemeral key, that is discarded when the application
// shuts down. Tokens signed using this key are automatically invalidated.
// This method should only be used during development.
.AddEphemeralSigningKey();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
var iocContainer = new ApplicationIoCContainer(services, Configuration);
iocContainer.RegisterModules();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
loggerFactory.AddConsole(Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseCors(builder =>
// This will allow any request from any server. Tweak to fit your needs!
// The fluent API is pretty pleasant to work with.
builder.AllowAnyHeader()
.AllowAnyMethod()
.AllowAnyOrigin()
);
app.UseIdentity();
app.UseOAuthValidation();
app.UseOpenIddict();
app.UseMvc();
// Chamar apenas quando for criar as tabelas do banco
InitializeAsync(app.ApplicationServices, CancellationToken.None).GetAwaiter().GetResult();
}
private async Task InitializeAsync(IServiceProvider services, CancellationToken cancellationToken)
{
// Create a new service scope to ensure the database context is correctly disposed when this methods returns.
using (var scope = services.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
// ReSharper disable once MethodSupportsCancellation
await context.Database.EnsureCreatedAsync();
var manager = scope.ServiceProvider.GetRequiredService<OpenIddictApplicationManager<OpenIddictApplication>>();
if (await manager.FindByClientIdAsync("ClientId", cancellationToken) == null)
{
var application = new OpenIddictApplication
{
ClientId = "ClientId",
DisplayName = "Client name",
// I guess my error is here... but don't know how to resolve with an Api
LogoutRedirectUri = "http://localhost:5000/signout-oidc",
RedirectUri = "http://localhost:5000/signin-oidc"
};
await manager.CreateAsync(application, cancellationToken);
}
}
}
}
and this is the generated log
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/api/program/get-paged?page=1&pagesize=100
info: AspNet.Security.OAuth.Validation.OAuthValidationMiddleware[7]
Bearer was not authenticated. Failure message: Authentication failed because the access token was invalid.
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
Authorization failed for user: (null).
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
Executing ChallengeResult with authentication schemes ().
info: AspNet.Security.OAuth.Validation.OAuthValidationMiddleware[12]
AuthenticationScheme: Bearer was challenged.
info: Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware[12]
AuthenticationScheme: Identity.Application was challenged.
info: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[2]
Executed action Life.Platform.Api.Controllers.ProgramController.Get (Life.Platform.Api) in 55.8041ms
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 60.6096ms 302
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
Request starting HTTP/1.1 GET http://localhost:5000/Account/Login?ReturnUrl=%2Fapi%2Fprogram%2Fget-paged%3Fpage%3D1%26pagesize%3D100
info: AspNet.Security.OAuth.Validation.OAuthValidationMiddleware[7]
Bearer was not authenticated. Failure message: Authentication failed because the access token was invalid.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
Request finished in 5.0739ms 404
Looks like it’s using CookieMiddlware, but why? And, how can I just return a 401 result, when the user is unautenticated and 403 when user is unauthorized?
Thanks for your help! And congrats… This is a big tool!!!
Issue Analytics
- State:
- Created 7 years ago
- Comments:6 (1 by maintainers)
Top Results From Across the Web
Is it OK to return a HTTP 401 for a non existent resource ...
If the user does not have access to a resource, you should be returning 403, not 404. If the user is authenticated and...
Read more >Hands off that resource, HTTP status code 401 vs 403 vs 404
Returning a 404 Not Found means “the requested resource does not exists”. Actually, there's a subtlety, it could mean “the requested resource ...
Read more >The 404 response could also indicate a permissions ...
The reason why this happens instead of returning a 401 is that it would leak information to which the user is not privileged....
Read more >Is it OK to give status 404 to unauthorized users?
Certainly a valid argument for a 404. However, I don't think it's necessarily always appropriate to send a 404 - it depends on...
Read more >Handling Forbidden RESTful Requests: 401 vs. 403 vs. 404
If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
@weitzhandler, I’ve used following workaround:
If you call this in ConfigureServices method, it sets up the cookie to return 401 on redirection to login. I think this won’t be a good solution if you use this redirection somewhere else in a code. Otherwise - should work.
Glad you like it 😄
The behavior you’re seeing is caused by Identity, that replaces 401 responses by 302 responses. In your case, the login endpoint doesn’t exist, so you’re getting a 404 response.
If you’re not using cookies authentication, consider removing
app.UseIdentity();
.