C
C#16mo ago
S-IERRA

❔ ASP.NET always validates invalid JWT

I have a custom configuration for Asp.net where the JWT Token is stored in an http-only cookie, because of this there is 1 method in specific that is always returning 200 no matter if there is no actual JWT attached
public static void RegisterAuthorization(this IServiceCollection serviceCollection, IConfiguration configuration)
{
var jwtConfig = configuration.GetSection("Jwt").Get<JwtConfig>()!;
serviceCollection.Configure<JwtConfig>(configuration.GetSection("Jwt"));

serviceCollection.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = jwtConfig.Audience,
ValidIssuer = jwtConfig.Issuer,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.Key))
};

options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
context.Token = context.Request.Cookies["JwtToken"];

return Task.CompletedTask;
}
};
});

serviceCollection.AddAuthorization(options =>
{
options.AddPolicy(NumixAuthPolicy.Admin.ToString(), policy =>
policy.RequireClaim(ClaimTypes.Role, NumixRole.Administrator.ToString()));
});

serviceCollection.AddScoped(typeof(IAuthenticatorService), typeof(Authenticate));
}
public static void RegisterAuthorization(this IServiceCollection serviceCollection, IConfiguration configuration)
{
var jwtConfig = configuration.GetSection("Jwt").Get<JwtConfig>()!;
serviceCollection.Configure<JwtConfig>(configuration.GetSection("Jwt"));

serviceCollection.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = jwtConfig.Audience,
ValidIssuer = jwtConfig.Issuer,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtConfig.Key))
};

options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
context.Token = context.Request.Cookies["JwtToken"];

return Task.CompletedTask;
}
};
});

serviceCollection.AddAuthorization(options =>
{
options.AddPolicy(NumixAuthPolicy.Admin.ToString(), policy =>
policy.RequireClaim(ClaimTypes.Role, NumixRole.Administrator.ToString()));
});

serviceCollection.AddScoped(typeof(IAuthenticatorService), typeof(Authenticate));
}
57 Replies
S-IERRA
S-IERRAOP16mo ago
When a different jwt token requests data of a diferent id it returns an empty array but 200
[Authorize]
[HttpPost("fetch-transactions")]
[ProducesResponseType(200)]
[ProducesResponseType(401)]
public async Task<IActionResult> FetchTransactions([FromClaim(NumixClaims.NumixId)] Guid numixId)
{
DateTimeOffset now = DateTimeOffset.UtcNow.AddYears(-10);
List<BasicNumixTransaction> completedTransactions = await _saleAnalytics.FetchDbTransactions(startDate: now, paymentStatus: PaymentStatus.Success, userId: numixId);

return Ok(JsonSerializer.Serialize(completedTransactions, JsonHelper.JsonSerializerOptions));
}
[Authorize]
[HttpPost("fetch-transactions")]
[ProducesResponseType(200)]
[ProducesResponseType(401)]
public async Task<IActionResult> FetchTransactions([FromClaim(NumixClaims.NumixId)] Guid numixId)
{
DateTimeOffset now = DateTimeOffset.UtcNow.AddYears(-10);
List<BasicNumixTransaction> completedTransactions = await _saleAnalytics.FetchDbTransactions(startDate: now, paymentStatus: PaymentStatus.Success, userId: numixId);

return Ok(JsonSerializer.Serialize(completedTransactions, JsonHelper.JsonSerializerOptions));
}
Florian Voß
Florian Voß16mo ago
are you sure it returns 200 even with no JWT? shouldn't be possible 🤔 . I assume you still had a JWT stored somewhere that authenticated you, is that possible? How about using expiration on the JWT? accept JWT only for 24 hours or smth and include check for expiration date in your policy maybe
S-IERRA
S-IERRAOP16mo ago
Yes, let me show you
Florian Voß
Florian Voß16mo ago
not sure how you would show this to me. What exactly does options.Save = true mean? where does it save the JWT?
S-IERRA
S-IERRAOP16mo ago
so its fetched from a cookie which is currently set
S-IERRA
S-IERRAOP16mo ago
also sure just a sec
S-IERRA
S-IERRAOP16mo ago
I remove the cookie / log out and seems to still be allowing it
S-IERRA
S-IERRAOP16mo ago
it doesnt really allowt o fetch other ids but
S-IERRA
S-IERRAOP16mo ago
Possibly like you said this
S-IERRA
S-IERRAOP16mo ago
let me check
S-IERRA
S-IERRAOP16mo ago
Florian Voß
Florian Voß16mo ago
I guess a JWT might have been saved there from your last auth
S-IERRA
S-IERRAOP16mo ago
just a sec cuz i gotta remeber the passoword
S-IERRA
S-IERRAOP16mo ago
no still no
S-IERRA
S-IERRAOP16mo ago
S-IERRA
S-IERRAOP16mo ago
S-IERRA
S-IERRAOP16mo ago
both are 200s
Florian Voß
Florian Voß16mo ago
Not sure if this will help us find out but when you go in browser into dev tools where you use swagger onto Application, can you find a JWT token in cookies there? Not sure what name the cookie would have, any cookie value that starts with "ey..."?
S-IERRA
S-IERRAOP16mo ago
S-IERRA
S-IERRAOP16mo ago
im thinking could it be because of this
S-IERRA
S-IERRAOP16mo ago
S-IERRA
S-IERRAOP16mo ago
S-IERRA
S-IERRAOP16mo ago
i mean its old and wont work now anyway but im thinking now it could be smthn to do with one of my middlewares but i dont think thats the case weird because it seems like its skipping over auth completly for this specific method
Florian Voß
Florian Voß16mo ago
this seems to add the Token to request in Swagger I would guess this request here contains a token this one does not
S-IERRA
S-IERRAOP16mo ago
yes thats before log out yes
S-IERRA
S-IERRAOP16mo ago
S-IERRA
S-IERRAOP16mo ago
for some reason its skipping authorization
Florian Voß
Florian Voß16mo ago
have you tried adding the name of your auth policy on the attribute? it should apply it anyway but I'm not sure
S-IERRA
S-IERRAOP16mo ago
that auth policy breaks everything and puts everything on 403 so i dont use it anymore
Florian Voß
Florian Voß16mo ago
then the one you'd like to be using
S-IERRA
S-IERRAOP16mo ago
thats the thing there isnt any policy
Florian Voß
Florian Voß16mo ago
in the middleware you have shown to me there was 🤷‍♂️
S-IERRA
S-IERRAOP16mo ago
let me check that could be why oh this
S-IERRA
S-IERRAOP16mo ago
S-IERRA
S-IERRAOP16mo ago
its not used anywhere i just removed it
Florian Voß
Florian Voß16mo ago
yep okay
S-IERRA
S-IERRAOP16mo ago
seems like a bug within asp but im not sure
Florian Voß
Florian Voß16mo ago
very unlikely more likely that you and me are both being harold
S-IERRA
S-IERRAOP16mo ago
probably
Kouhai
Kouhai16mo ago
Do you have AllowAnonymous on your controller? @S-IERRA
S-IERRA
S-IERRAOP16mo ago
yes
S-IERRA
S-IERRAOP16mo ago
S-IERRA
S-IERRAOP16mo ago
but shouldnt authorise on the method its self over write this?
Kouhai
Kouhai16mo ago
No, it's the other way around afaik
S-IERRA
S-IERRAOP16mo ago
I ll try unlinking that allow anonymous on all other methods Inlining
Kouhai
Kouhai16mo ago
You don't need to inline it
S-IERRA
S-IERRAOP16mo ago
and remove it from the class
Kouhai
Kouhai16mo ago
As long as the controller doesn't have Authorize it will allow Anonymouse accsess by default
S-IERRA
S-IERRAOP16mo ago
im thinking for some reason allow anounymous is over writing that access controller below which wouldnt make sense but it could be ok that was indeed the case i assume this is a ASP.NET bug possibly someone from asp.net team could investigate?
Kouhai
Kouhai16mo ago
I don't think it's a bug tbh
S-IERRA
S-IERRAOP16mo ago
i mean allow anon on class shouldnt over write authorize on method
SinFluxx
SinFluxx16mo ago
Kouhai
Kouhai16mo ago
^
S-IERRA
S-IERRAOP16mo ago
oh shit alright thanks thats good to know
SinFluxx
SinFluxx16mo ago
It seems a more likely scenario you'd have Authorize on your controller and AllowAnonymous on a specific method
S-IERRA
S-IERRAOP16mo ago
yes i see now thanks
Accord
Accord16mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server