AzureAD / azure-activedirectory-identitymodel-extensions-for-dotnet

IdentityModel extensions for .Net
MIT License
1.03k stars 386 forks source link

[Bug] when read claims from JWT is skipping even claims and only reading odds. #2546

Open jmborroto opened 3 months ago

jmborroto commented 3 months ago

Which version of Microsoft.IdentityModel are you using? 7.5.0

Where is the issue?

Is this a new or an existing app? The app is on development.

Repro Attached is a UnitTest project which includes three tests:

  1. The first test is designed to fail in order to demonstrate the error.
  2. The second test includes additional claims to show that the library skips even-numbered claims, yet it passes because the extra claims help by making the real ones able to be read.
  3. The final test demonstrates other issues stemming from this error, such as failing to validate the Issuer, audience, or expiration. These issues depend on whether the preceding number of claims results in an even or odd total.

JWT token Test.zip

Expected behavior When claims are added to the token, all of them should be retrievable independen of the order or parity.

Actual behavior The library is skipping one claim in between. To be more precise, the odd-numbered claims are retrievable, while the even-numbered claims are skipped. It appears that everything was fine until version 7.3.1. However, if you test it with version 7.4 or higher, the bug will start to appear.

ArthurSett commented 3 months ago

Same problem. Every second claim is skipped, including the expiration date (which breaks the JWT logic). The JwtPayload.CreatePayload method uses Utf8JsonReader to parse the token and calls reader.Read() each time to read the value and keys forward. Therefore my first guess: it must be a misplaced “reader.Read()” in the code.

I debugged the parsing loop cycle in case of a custom claim-id/name and it led me to the first (reader index at first Entry.Key), second (first Entry.Value) and third (second Entry.Key) reader.Read() in one cycle. When the parsing cycle tries to parse the next key it gets value of the second Entry.

I reverted to 7.3.1 as @jmborroto said and it works again.

FuPingFranco commented 2 months ago

@jmborroto & @ArthurSett, issue is related to dependency mismatch on the test you provide, please update your transitive dependencies to match Version="7.5.0" for certain transitive dependencies.

Please try the following in on the JWT token Test.csproj.

  <ItemGroup>
    <PackageReference Include="coverlet.collector" Version="6.0.2">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.3" />
    <PackageReference Include="Microsoft.Extensions.Options" Version="8.0.2" />
    <PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="7.5.0" />
    <PackageReference Include="Microsoft.IdentityModel.Protocols" Version="7.5.0" />
    <PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="7.5.0" />
    <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.5.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
    <PackageReference Include="xunit" Version="2.7.0" />
    <PackageReference Include="xunit.runner.visualstudio" Version="2.5.7">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
  </ItemGroup>

Please confirm if this works to close this issue. Thanks!

jmborroto commented 2 months ago

This is a new project created only to add the test class and added the MI.JsonWebToken nugget package to make it easy to demonstrate, if any dependency that is needed is not included by default is because the nugget package is not configured to include the correct ones. That also caused issues in our big project where we first notice the issue so if the nugget package is not fix then anyone just installing the nugget package will have the same issue.

FuPingFranco commented 2 months ago

We are working on this issue but, we are tracking it on a separate issue here https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/2513 to avoid having multiple issues related to the same bug please refer to the status of https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/2513.

hahn-kev commented 1 month ago

Yikes I just ran into this when I installed Openiddict and it referneced a newer version of the identity model packages, but the Identity openIDConnect was an old version being referneced by Aspnet.Core JwtBearer. I hope this can get figured out so it's less painful to debug.

ItWorksOnMyMachine commented 3 weeks ago

I'm confused as to how to solve this. I have recently upgraded to .NET 8.0 and also upgraded the Microsofr.IdentityModel and System.IdentityModel packages. All of those packages are at 7.6.0 and I'm still experiencing this issue. Here are all of my packages.

<PackageReference Include="AWSSDK.AWSMarketplaceMetering" Version="3.7.300.103" />
<PackageReference Include="AWSSDK.MarketplaceEntitlementService" Version="3.7.302.20" />
<PackageReference Include="AWSSDK.RDS" Version="3.7.313.11" />
<PackageReference Include="AWSSDK.SSO" Version="3.7.300.103" />
<PackageReference Include="AWSSDK.SSOOIDC" Version="3.7.302.14" />
<PackageReference Include="Braintree" Version="5.25.0" />
<PackageReference Include="CustomerApi" Version="1.0.0-CI-20231122-210852" />
<PackageReference Include="Duende.IdentityServer.AspNetIdentity" Version="7.0.5" />
<PackageReference Include="EntityFramework6.Npgsql" Version="6.4.3" />
<PackageReference Include="EventApi" Version="1.0.0-CI-20231115-172843" />
<PackageReference Include="FluentValidation.AspNetCore" Version="11.3.0" />
<PackageReference Include="HtmlSanitizer" Version="8.0.865" />
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
<PackageReference Include="IdentityModel" Version="7.0.0" />
<PackageReference Include="MediaTypeMap.Core" Version="2.3.3" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" />
<PackageReference Include="Microsoft.AspNetCore.DataProtection.Extensions" Version="8.0.6" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.6" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.NewtonsoftJson" Version="8.0.6" />
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="3.1.32" />
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.10.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Features" Version="4.10.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="4.10.0" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.10.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Features" Version="4.10.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Scripting.Common" Version="4.10.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic" Version="4.10.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Features" Version="4.10.0" />
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="4.10.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.10.0" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.10.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Configuration.CommandLine" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="8.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="8.0.0" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="7.6.0" />
<PackageReference Include="Microsoft.TypeScript.MSBuild" Version="5.4.4">
  <PrivateAssets>all</PrivateAssets>
  <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Serilog.AspNetCore" Version="8.0.1" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="3.0.0" />
<PackageReference Include="Serilog.Enrichers.Sensitive" Version="1.7.3" />
<PackageReference Include="Serilog.Sinks.Datadog.Logs" Version="0.5.2" />
<PackageReference Include="System.IO.FileSystem.Watcher" Version="4.3.0" />
<PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Reactive.Linq" Version="6.0.1" />
<PackageReference Include="System.Xml.XmlSerializer" Version="4.3.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="8.0.2" />
<PackageReference Include="Mono.TextTemplating" Version="2.3.1" />
<PackageReference Include="Mono.TextTemplating.Roslyn" Version="2.3.1" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="SharpZipLib" Version="1.4.2" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.6.2" />
<PackageReference Include="Swashbuckle.AspNetCore.Annotations" Version="6.6.2" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="7.6.0" />
<PackageReference Include="Venminder.CQRS" Version="1.2.1" />
SamuelFormigheri commented 1 week ago

@ItWorksOnMyMachine , @jmborroto . I was experiencing this issue in a project that I upgraded from .net 6 to .net 8. I was able to fix these replacing the way I was reading the JWT. I was previously using System.IdentityModel.Tokens.Jwt and I replace it to Microsoft.IdentityModel.JsonWebTokens. I change the way I generate token to use JsonWebTokenHandler instead of JwtSecurityTokenHandler. And I did the same changes to read the claims from jwt token. Here's the code. Hope it helps.

public static IEnumerable<Claim> ReturnClaimsFromToken(string tk) { JsonWebTokenHandler tokenHandler = new JsonWebTokenHandler(); JsonWebToken jwtToken = tokenHandler.ReadJsonWebToken(tk); return jwtToken.Claims; }

The versions of packages are:

"Microsoft.IdentityModel.JsonWebTokens" Version="7.6.2" "Microsoft.IdentityModel.Tokens" Version="7.6.2"