dotnet / aspnetcore

ASP.NET Core is a cross-platform .NET framework for building modern cloud-based web applications on Windows, Mac, or Linux.
https://asp.net
MIT License
35.3k stars 9.96k forks source link

NET 8 minimal API: Error in AspNetCore.Authentication.JwtBearer 8.0.0 #52388

Closed true-perfect-code closed 4 months ago

true-perfect-code commented 10 months ago

Is there an existing issue for this?

Describe the bug

Authentication via JWT in minimal API works with nuget Microsoft.AspNetCore.Authentication.JwtBearer 7.0.145 but not with Microsoft.AspNetCore.Authentication.JwtBearer 8.0.0

Expected Behavior

The error message is Error: response status is 401 content-length: 0 date: Mon,27 Nov 2023 08:51:14 GMT server: Kestrel www-authenticate: Bearer error="invalid_token"

The error message can be reproduced via the attached GitHub project by optionally changing nuget from version 7.014 to 8.0.0 and vice versa.

Steps To Reproduce

GitHub Repository: https://github.com/true-perfect-code/WebApiNet8_minimalAPI

Exceptions (if any)

No response

.NET Version

NET 8

Anything else?

No response

eirikurharaldsson commented 10 months ago

I,m also having this issue with version 8 of AspNetCore.Authentication.JwtBearer, ground cause seems to be in the OpenIdConnect package dependency going from version 6 to 7.

https://github.com/dotnet/aspnetcore/issues/52330

halter73 commented 7 months ago

@true-perfect-code https://github.com/true-perfect-code/WebApiNet8_minimalAPI is now returning a 404. Are you still having an issue? If so, can you put the repro app back up?

There was a breaking change in .NET 8 that was announced in https://learn.microsoft.com/en-us/dotnet/core/compatibility/aspnet-core/8.0/securitytoken-events. You can revert to the previous JwtSecurityToken behavior rather than the new JsonWebToken behavior if it's breaking your app. Everything that was supported by JwtSecurityToken should be supported by JsonWebToken, but you may need to update your code following the guidance in the "Recommended action" section of the breaking change announcement.

true-perfect-code commented 7 months ago

Hi Stephen (@halter73 ), I'm Justin from perfect-code.

I have looked at the reported problem from Daniel (also from perfect-code) and the problem still exists. Since almost no one else is reporting the same problem, I assume that the error must be ours and we missed to configure the code correctly.

I have created a new project and uploaded it to GitHub. When I use NuGet version 7.0.14, my WebApi (minimal API) runs without any problems:

image

image

image

image

If I then send a query to WebApi Server, I get the answer

image

image

If I now update NuGet to 8.0.2, make the adjustment in the code described in your link and test everything, I get an error message. It does not work.

image

image

image

You can find the project on GitHub at https://github.com/true-perfect-code/JwtBearer_Problem

As written, I assume that something is configured incorrectly here and hope that you can quickly explain this to us so that we can close this item.

Thank you very much Justin

true-perfect-code commented 5 months ago

Hello @halter73 , is there anything new? Is it a bigger problem after all?

Regards tpc

Lorthirash commented 5 months ago

I have the same problem and i can't solve Here is my code: https://github.com/Lorthirash/JWTBEARERNET8

it is work jwtbearer version 7 but new 8+ doesn't work. How can is solve the problem? please help.

halter73 commented 4 months ago

@true-perfect-code It looks like the issue was an invalid "iat" claim. RFC 7519 Section 4.1.6 states that it "MUST be a number containing a NumericDate value" where "NumericDate" is Unix Time.

https://datatracker.ietf.org/doc/html/rfc7519#section-4.1.6

So new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()) should instead be new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString()), so "iat": "5/29/2024 10:00:52 PM" becomes "iat": "1717020577"

If you update your appsettings.Development.json to include "Information" level logging for "Microsoft.AspNetCore", you would see the following in the log output when trying to use a token with an invalid "iat" claim:

info: Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerHandler[1]
      Failed to validate the token.
      Microsoft.IdentityModel.Tokens.SecurityTokenMalformedException: IDX14100: JWT is not well formed, there are no dots (.).
The token needs to be in JWS or JWE Compact Serialization Format. (JWS): 'EncodedHeader.EndcodedPayload.EncodedSignature'. (JWE): 'EncodedProtectedHeader.EncodedEncryptedKey.EncodedInitializationVector.EncodedCiphertext.EncodedAuthenticationTag'.
       ---> System.ArgumentException: IDX14101: Unable to decode the payload '[PII of type 'Microsoft.IdentityModel.Logging.SecurityArtifact' is hidden. For more details, see https://aka.ms/IdentityModel/PII.]' as Base64Url encoded string.
       ---> System.Text.Json.JsonException: IDX11020: The JSON value of type: 'String', could not be converted to 'JsonTokenType.Number'. Reading: 'Microsoft.IdentityModel.JsonWebTokens.JsonWebToken.iat', Position: '52', CurrentDepth: '1', BytesConsumed: '75'.
         at Microsoft.IdentityModel.Tokens.Json.JsonSerializerPrimitives.ReadLong(Utf8JsonReader& reader, String propertyName, String className, Boolean read)
         at Microsoft.IdentityModel.JsonWebTokens.JsonWebToken.CreatePayloadClaimSet(Byte[] bytes, Int32 length)
         at Microsoft.IdentityModel.Tokens.Base64UrlEncoding.Decode[T](String input, Int32 offset, Int32 length, Func`3 action)
         at Microsoft.IdentityModel.JsonWebTokens.JsonWebToken.CreateClaimSet(String rawString, Int32 startIndex, Int32 length, Func`3 action)
         at Microsoft.IdentityModel.JsonWebTokens.JsonWebToken.ReadToken(String encodedJson)
         --- End of inner exception stack trace ---
         at Microsoft.IdentityModel.JsonWebTokens.JsonWebToken.ReadToken(String encodedJson)
         at Microsoft.IdentityModel.JsonWebTokens.JsonWebToken..ctor(String jwtEncodedString)
         at Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ReadToken(String token, TokenValidationParameters validationParameters)
         --- End of inner exception stack trace ---

The relevant bit here is "The JSON value of type: 'String', could not be converted to 'JsonTokenType.Number'. Reading: 'Microsoft.IdentityModel.JsonWebTokens.JsonWebToken.iat'".

The part about "JWT is not well formed, there are no dots (.)." appears to be a red herring because the token does indeed have dots. Someone has already reported that this seems to get over reported any time there's a failure in JsonWebTokenHandler.ValidateToken at https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/2058. I'll update that thread with this example and see if we can improve the Exception message.

dotnet-policy-service[bot] commented 4 months ago

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.

true-perfect-code commented 4 months ago

@halter73 Thank you very much, it works. Our prediction was correct, it was our mistake. Thank you once again.