aspnetcore
aspnetcore copied to clipboard
Minimal APIs : Endpoint route returning 404 not found.
Is there an existing issue for this?
- [X] I have searched the existing issues
Describe the bug
I have an ASP.NET Core 7 WebAPI that uses minimal APIs however some endpoint routes are returning 404 Not Found even when the routes have been correctly configured.
var customers = app.MapGroup("/api/customers");
//These two endpoints are returning 404 Not Found.
customers.MapGet("/", [Authorize] async (ICustomerService service) =>
{
return await service.GetAllAsync();
});
customers.MapGet("/{id}",
[Authorize] async (ICustomerService service, [FromRoute] string id) =>
{
var result = await service.GetByUserGuid(id);
if (result.Succeeded)
{
return new Result<Customer>() { Data = result.Data, Succeeded = true };
}
else
{
return new Result<Customer>() { Succeeded = result.Succeeded };
}
});
//These two are working just fine
app.MapPost("/api/login", [AllowAnonymous] async (ITokenService tokenService, [FromBody] TokenRequest request) =>
{
var res = await tokenService.LoginAsync(request);
if (res.Succeeded)
{
return new Result<TokenResponse>() { Succeeded = true, Message = res.Message, Data = res.Data };
}
else
{
return new Result<TokenResponse>() { Succeeded = false, Message = "Incorect credentials", Data = new
TokenResponse() };
}
});
app.MapPost("/api/register", [AllowAnonymous] async (IUserService service, [FromBody] RegisterRequest request) =>
{
return await service.RegisterAsync(request, request?.Origin);
});
Expected Behavior
No response
Steps To Reproduce
No response
Exceptions (if any)
No response
.NET Version
7.0.100
Anything else?
I discovered that removing [Authorize]
attribute works. Must be an issue with authorization so below is my JWT configuration.
internal static IServiceCollection AddJwtAuthentication(this IServiceCollection services, AppConfiguration appConfig)
{
var key = Encoding.ASCII.GetBytes(appConfig.Secret);
services
.AddAuthentication(authentication =>
{
authentication.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
authentication.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(bearer =>
{
bearer.RequireHttpsMetadata = false;
bearer.SaveToken = true;
bearer.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
RoleClaimType = ClaimTypes.Role,
ClockSkew = TimeSpan.Zero
};
bearer.Events = new JwtBearerEvents
{
OnAuthenticationFailed = c =>
{
if (c.Exception is SecurityTokenExpiredException)
{
c.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
c.Response.ContentType = "application/json";
var result = JsonConvert.SerializeObject(Result.Fail("Your Token Has Expired"));
return c.Response.WriteAsync(result);
}
else
{
c.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
c.Response.ContentType = "application/json";
var result = JsonConvert.SerializeObject(Result.Fail("An unhandled error has occurred."));
return c.Response.WriteAsync(result);
}
},
OnChallenge = context =>
{
context.HandleResponse();
if (!context.Response.HasStarted)
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
context.Response.ContentType = "application/json";
var result = JsonConvert.SerializeObject(Result.Fail("You are not Authorized."));
return context.Response.WriteAsync(result);
}
return Task.CompletedTask;
},
OnForbidden = context =>
{
context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
context.Response.ContentType = "application/json";
var result = JsonConvert.SerializeObject(Result.Fail("You are not authorized to access this resource."));
return context.Response.WriteAsync(result);
},
};
});
services.AddAuthorization();
return services;
}
Can you show the entire pipeline wire up?
Below is my Program.cs file. The same wire up works in .NET 6
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDatabase(connectionString);
builder.Services.AddJwtAuthentication(builder.Services.GetApplicationSettings(builder.Configuration));
builder.Services.AddInfrastructureServices();
builder.Services.RegisterSwagger();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.UseMiddleware<SignInMiddleware<User>>();
/* API ENDPOINTS */
app.MapEndpointRoutes();
app.SeedDatabase();
app.Run();
It's hard to tell where the 404 might be coming from. Maybe set breakpoints in the various JWT events?
I have tried setting breakpoints on each event. None of the breakpoints are reachable.
I will try to set up a minimalistic project to reproduce the bug.
@izzyjere one of the tricks I use to debug is adding a middleware to the pipeline at various places to see how for it got:
var builder = WebApplication.CreateBuilder(args);
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDatabase(connectionString);
builder.Services.AddJwtAuthentication(builder.Services.GetApplicationSettings(builder.Configuration));
builder.Services.AddInfrastructureServices();
builder.Services.RegisterSwagger();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.Use((context, next) =>
{
// Put a breakpoint here
return next(context);
});
app.UseAuthorization();
app.UseMiddleware<SignInMiddleware<User>>();
/* API ENDPOINTS */
app.MapEndpointRoutes();
app.SeedDatabase();
app.Run();
Thank you that worked I was able to detect the cause. Calling app.UseHttpsRedirection()
after app.UseAuthorization()
fixed the problem.
app.UseAuthentication();
app.UseAuthorization();
app.UseHttpsRedirection();
Why did you reopen this @davidfowl?
to let the bot close it
Is it because of the autolock on closed issues? How long does that take?
No idea
This issue has been resolved and has not had any activity for 1 day. It will be closed for housekeeping purposes.
See our Issue Management Policies for more information.