Skip to content

Endpoint with AllowAnonymous() returns 401 when API version is unsupported or unspecified #1131

Open
@naegelejd

Description

@naegelejd

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

I am using Minimal APIs with Asp.Versioning.Mvc 8.1.0.

I have Authentication and Authorization enabled with default JWT-Bearer Authentication scheme and default Authorization policy (the only requirement is DenyAnonymousAuthorizationRequirement).

As expected, with Authentication/Authorization disabled, I get a 400 Bad Request response when I provide an invalid API version in a client request (or omit the API version altogether).

However, if I enable Authentication/Authorization, and use .AllowAnonymous() to bypass the authorization requirement on an endpoint, I get a 401 Unauthorized response for the same requests.

Is this the expected behavior? Either way, is there a way to work around this so that we can return a 401 response?

Expected Behavior

When I use .AllowAnonymous() on an endpoint, I expect to receive a 401 Bad Request when a client request omits the API version or provides an invalid API version.

Steps To Reproduce

Minimal server to reproduce:

using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using Asp.Versioning;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddAuthentication().AddJwtBearer();

builder.Services.AddAuthorization();
builder.Services.AddOptions<AuthorizationOptions>().Configure((authOptions) =>
{
    authOptions.FallbackPolicy = new AuthorizationPolicyBuilder().RequireAuthenticatedUser().Build();
});


builder.Services.AddApiVersioning(options =>
{
    options.ApiVersionReader = new QueryStringApiVersionReader("api-version");
});

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

var api = app.NewVersionedApi();
api.MapGet("/foo", () => "Hello World!").AllowAnonymous().HasApiVersion(1.0);

app.Run();

Demo:

$ curl -i http://localhost:5080/foo?api-version=1.0
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Date: Tue, 22 Apr 2025 20:49:15 GMT
Server: Kestrel
Transfer-Encoding: chunked

$ curl -i http://localhost:5080/foo?api-version=1.1
HTTP/1.1 401 Unauthorized
Content-Length: 0
Date: Tue, 22 Apr 2025 20:49:18 GMT
Server: Kestrel
WWW-Authenticate: Bearer

$ curl -i http://localhost:5080/foo
HTTP/1.1 401 Unauthorized
Content-Length: 0
Date: Tue, 22 Apr 2025 20:49:29 GMT
Server: Kestrel
WWW-Authenticate: Bearer

Exceptions (if any)

No response

.NET Version

9.0.102

Anything else?

No response

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions