Skip to content

Serialize and deserialize actor token in claims identity#3219

Open
saurabhsathe-ms wants to merge 86 commits intodevfrom
ssathe/serializeClaimsIdentity
Open

Serialize and deserialize actor token in claims identity#3219
saurabhsathe-ms wants to merge 86 commits intodevfrom
ssathe/serializeClaimsIdentity

Conversation

@saurabhsathe-ms
Copy link
Copy Markdown
Contributor

@saurabhsathe-ms saurabhsathe-ms commented May 6, 2025

Serialize and deserialize actor token in claims identity

  • [*] You've read the Contributor Guide and Code of Conduct.
  • [*] You've included unit or integration tests for your change, where applicable.
  • [*] You've included inline docs for your change, where applicable.
  • [*] If any gains or losses in performance are possible, you've included benchmarks for your changes. More info
  • [*] There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Actor Token Serialization History

The JsonWebTokenHandler never actually supported actor token serialization—it wasn't removed at a specific point, but rather was never implemented when this newer handler was introduced. The older JwtSecurityTokenHandler has always correctly serialized the ClaimsIdentity. Actor property into the actort claim in JWTs. However, when JsonWebTokenHandler was created as a more performant alternative, the actor serialization logic was not ported over. The handler only processed individual claims from Subject.Claims and never handled the Subject.Actor property separately. This gap was reported in Issue #1840 ("[Bug] ClaimsIdentity Actor not serialized into JWTs"), and your PR #3219 addresses this by adding the missing functionality to bring JsonWebTokenHandler to feature parity with JwtSecurityTokenHandler.
File changes:

Act vs Actort

actort vs act Claims

Aspect act (RFC 8693) actort (Microsoft IdentityModel)
Standard RFC 8693 OAuth 2.0 Token Exchange Microsoft-specific / Legacy
Value Type JSON object with actor claims Serialized JWT string
Structure { "act": { "sub": "...", "iss": "..." } } "actort": "eyJhbG..." (JWT)
Nesting Supports nested act for delegation chains Recursive JWT parsing required

Example of act (RFC 8693):

{
  "sub": "user@example.com",
  "act": {
    "sub": "client@example.com"
  }
}

Note: actort predates RFC 8693 and is used in this library for backward compatibility. It maps to ClaimTypes.Actor when processing claims. For RFC 8693 compliance, the standard act claim is recommended.

Requirements

Serialization Requirements:

  1. The actor token can be in form of actort, act or may_act. We need to give the users the flexibility to be able to serialize it the way they want. Actort is serialized into unsigned JWT while act and may_act are serialized as JSON objects.
  2. Actor token can be supplied as ClaimsIdentity.Actor or in claims dictionary. If supplied in both then the actor token value in claims dictionary should be used.
  3. For nested actor tokens, we should limit the amount of nesting. The max depth that we allow should be 5. Customer should be able to set the value in range [1,5]
  4. User can specify their type of actor using the security token descriptor. By default identity model will look for "act" as per the https://www.rfc-editor.org/rfc/rfc8693.html

Deserialization Requirements

  1. Actort should be deserialized as unsigned JWT. Act and may_act should be deserialized as JSON objects.
  2. Customer should be able to set the deserialization depth (amount of nested deserializations) in range [1,5]
  3. We should have a default logic that deserializes the actor claim but customers should be able to deserialize the actor claim the way they want and we should provide a delegate for enabling customers for it.
  4. User can specify their type of actor using token validation parameters. By default identity model will look for "act" as per the https://www.rfc-editor.org/rfc/rfc8693.html

Approach:

  1. I added 2 parameters in SecurityTokenDescriptor and TokenValidationParameters class to enable users to specify the max depth of actor token serialization/deserialization and their actor type. These are MaxActorChainLength and ActorClaimType. ActorChainDepth is used by IdentityModel for recursive processing of the actor token
  2. TokenValidation parameters have an additional parameter now which is ActClaimRetrieverDelegate. This enables user to provide their own logic while converting the actor claim into ClaimsIdentityActor

Here’s a summary of all the changes made in this PR across the listed files:

Based on my review of the current diff in PR #3219, here is an updated summary of all the changes:


Summary of Changes in PR #3219

1. src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.CreateToken.cs

  • Actor Token Serialization Support:
    • Added isActorFound flag to track if actor claim exists in the Claims dictionary
    • Added logic to skip the actor claim during regular claims processing when it matches tokenDescriptor.ActorClaimType
    • Added new method WriteActorToken() that serializes actor tokens as JSON objects in the JWT payload
    • Added ValidateActorChainDepth() method to enforce maximum actor nesting depth
    • Added CreateActorTokenDescriptor() method that creates a SecurityTokenDescriptor for actor tokens from either Claims dictionary or Subject. Actor property
    • Claims dictionary actor takes precedence over Subject. Actor when both are present

2. src/Microsoft. IdentityModel. JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs

  • Actor Claim Deserialization Support:
    • Added using System.Text.Json import
    • Modified CreateClaimsIdentityWithMapping() and CreateClaimsIdentityPrivate() to handle both actorClaimType (configurable) and legacy "actort" claims
    • Added new private method CreateClaimsIdentityActor() that:
      • Handles standard act claims as JSON objects using TryGetPayloadValue<JsonElement>
      • Supports custom delegate (ActClaimRetrieverDelegate) for custom actor claim processing
      • Falls back to legacy JWT string parsing for actort claims using CanReadToken()/ReadToken()
    • Added new public static method CreateActorClaimsIdentityFromJsonElement() that:
      • Creates a CaseSensitiveClaimsIdentity from a JsonElement
      • Handles nested actor claims recursively
      • Enforces MaxActorChainLength limit
      • Processes array and complex claim types

3. src/Microsoft. IdentityModel.JsonWebTokens/LogMessages.cs

  • New Log Messages:
    • IDX14313: Maximum actor token depth reached during serialization/deserialization
    • IDX14314: Exception while using custom delegate to deserialize act claim
    • IDX14315: Actor claim is not a ClaimsIdentity (wrong type provided)

4. src/Microsoft.IdentityModel.JsonWebTokens/Microsoft.IdentityModel.JsonWebTokens.csproj

  • No functional change: Only a BOM (byte order mark) added at the file start

5. src/Microsoft.IdentityModel.JsonWebTokens/PublicAPI. Unshipped.txt

  • Added public API entry for CreateActorClaimsIdentityFromJsonElement static method

6. src/Microsoft.IdentityModel. Tokens/Delegates.cs

  • New Delegate:
    • Added ActClaimRetrieverDelegate - allows custom validation/conversion of the act claim JSON element to a ClaimsIdentity

7. src/Microsoft.IdentityModel.Tokens/InternalAPI. Unshipped.txt

  • Added internal API entries for:
    • EnableActClaimSupportSwitch constant
    • EnableActClaimSupport property
    • IDX11027 log message constant

8. src/Microsoft.IdentityModel.Tokens/LogMessages.cs

  • New Log Message:
    • IDX11027: Invalid JsonWebToken handler configuration parameter value

9. src/Microsoft.IdentityModel.Tokens/PublicAPI.Unshipped.txt

  • Public API Additions:
    • TokenValidationParameters.ActorChainDepth (get/set)
    • TokenValidationParameters.ActorClaimType (get/set)
    • TokenValidationParameters. MaxActorChainLength (get/set)
    • TokenValidationParameters. ActClaimRetrieverDelegate (get/set)
    • SecurityTokenDescriptor.ActorChainDepth (get/set)
    • SecurityTokenDescriptor.ActorClaimType (get/set)
    • SecurityTokenDescriptor.MaxActorChainLength (get/set)
    • ActClaimRetrieverDelegate delegate type

10. src/Microsoft.IdentityModel.Tokens/SecurityTokenDescriptor.cs

  • New Properties:
    • MaxActorChainLength: Maximum depth for nested actor tokens (default: 4, range: 0-4)
    • ActorClaimType: The claim type name for actor claims (default: "act", cannot be "actort" or empty)
    • ActorChainDepth: Internal tracking of current recursion depth during serialization
  • Added validation with ArgumentOutOfRangeException for invalid values

11. src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs

  • New Properties:
    • MaxActorChainLength: Maximum depth for nested actor tokens (default: 4, range: 0-4)
    • ActorClaimType: The claim type name for actor claims (default: "act", cannot be "actort" or empty)
    • ActorChainDepth: Internal tracking of current recursion depth during deserialization
    • ActClaimRetrieverDelegate: Custom delegate for converting actor claim JSON to ClaimsIdentity
  • Updated Clone() method to copy all new actor-related properties

12. test/Microsoft.IdentityModel.JsonWebTokens. Tests/ActorClaimsTests.cs (New Files)

  • ActClaimDeserializationTests: Comprehensive tests for actor claim deserialization including:

    • Basic JSON element to ClaimsIdentity conversion
    • Nested actor handling
    • Multi-level nesting with depth limits
    • Array and complex type handling
    • Custom delegate support
    • Exception handling for max depth exceeded
    • End-to-end ValidateTokenAsync tests with actors
    • Legacy actort JWT string handling
  • ActClaimSerializationTests: Comprehensive tests for actor claim serialization including:

    • Actor in Claims dictionary serialization
    • Actor in Subject.Actor serialization
    • Claims dictionary takes precedence over Subject. Actor
    • Nested actor serialization
    • MaxActorChainLength validation and enforcement
    • Exception handling for exceeding max depth

13. test/Microsoft.IdentityModel.TestUtils/ValidationDelegates.cs

  • Added static ActClaimRetrieverDelegate implementation for testing purposes (returns null)

14. test/Microsoft.IdentityModel. Tokens.Tests/TokenValidationParametersTests.cs

  • Increased ExpectedPropertyCount from 62 to 66
  • Added test entries for new properties: ActorClaimType, ActorChainDepth, MaxActorChainLength
  • Updated CreateTokenValidationParameters() to set ActClaimRetrieverDelegate

Key Notes

No AppContext Switch Changes: The current diff does not include any changes to AppContextSwitches. cs. The EnableActClaimSupportSwitch referenced in the API files appears to be documented but the actual implementation in AppContextSwitches.cs is not part of this diff.

Summary: This PR adds comprehensive support for serializing and deserializing actor claims (act) in JWT tokens using JsonWebTokenHandler, with configurable nesting depth limits, custom delegate support for deserialization, and backward compatibility with legacy actort claims.
Fixes #1840

@saurabhsathe-ms saurabhsathe-ms marked this pull request as ready for review May 6, 2025 16:41
@saurabhsathe-ms saurabhsathe-ms requested a review from a team as a code owner May 6, 2025 16:41
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2025

Summary

Summary
Generated on: 5/6/2025 - 4:45:08 PM
Coverage date: 5/6/2025 - 4:35:01 PM - 5/6/2025 - 4:44:42 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2025

Summary

Summary
Generated on: 5/6/2025 - 4:53:03 PM
Coverage date: 5/6/2025 - 4:42:26 PM - 5/6/2025 - 4:52:37 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2025

Summary

Summary
Generated on: 5/6/2025 - 4:56:18 PM
Coverage date: 5/6/2025 - 4:45:49 PM - 5/6/2025 - 4:55:52 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

@saurabhsathe-ms saurabhsathe-ms changed the title Ssathe/serialize claims identity Ssathe/Serialize actor token in claims identity May 6, 2025
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2025

Summary

Summary
Generated on: 5/6/2025 - 6:42:30 PM
Coverage date: 5/6/2025 - 6:32:21 PM - 5/6/2025 - 6:42:05 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

@saurabhsathe-ms saurabhsathe-ms requested a review from Copilot May 6, 2025 20:01
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR implements logic to serialize nested actor tokens within the claims identity and introduces a static property to control the maximum allowed nesting depth.

  • Added a static property MaxActorChainLength to control recursion depth with appropriate validations.
  • Updated token creation logic to handle nested actor tokens from either the Claims dictionary or the Subject.
  • Extended API documentation and logging with a new log message for exceeding the maximum actor chain depth.

Reviewed Changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.

File Description
src/Microsoft.IdentityModel.JsonWebTokens/PublicAPI.Unshipped.txt Added API entries for the new MaxActorChainLength property.
src/Microsoft.IdentityModel.JsonWebTokens/LogMessages.cs Added log message IDX14313 for exceeding maximum actor chain depth.
src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.CreateToken.cs Added logic to serialize nested actor tokens, including new parameters and recursion checks.
Files not reviewed (1)
  • src/Microsoft.IdentityModel.JsonWebTokens/Microsoft.IdentityModel.JsonWebTokens.csproj: Language not supported

Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.CreateToken.cs Outdated
@saurabhsathe-ms saurabhsathe-ms requested a review from Copilot May 6, 2025 20:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds functionality to serialize actor tokens within the claims identity while limiting recursion through a maximum actor chain depth. Key changes include:

  • Introducing the MaxActorChainLength static property to control nested actor token depth.
  • Updating CreateToken, WriteJwsPayload, and AddSubjectClaims methods to handle actor token serialization.
  • Adding a new log message (IDX14313) to indicate when the actor token chain exceeds the allowed maximum depth.

Reviewed Changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 2 comments.

File Description
src/Microsoft.IdentityModel.JsonWebTokens/PublicAPI.Unshipped.txt Added getters/setters for MaxActorChainLength in the public API
src/Microsoft.IdentityModel.JsonWebTokens/LogMessages.cs Added new log message for serialization depth errors
src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.CreateToken.cs Updated token creation logic to include actor token serialization
Files not reviewed (1)
  • src/Microsoft.IdentityModel.JsonWebTokens/Microsoft.IdentityModel.JsonWebTokens.csproj: Language not supported

Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.CreateToken.cs Outdated
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.CreateToken.cs Outdated
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2025

Summary

Summary
Generated on: 5/6/2025 - 8:25:28 PM
Coverage date: 5/6/2025 - 8:15:01 PM - 5/6/2025 - 8:25:03 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2025

Summary

Summary
Generated on: 5/7/2025 - 5:37:47 AM
Coverage date: 5/7/2025 - 5:27:07 AM - 5/7/2025 - 5:37:22 AM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 7, 2025

Summary

Summary
Generated on: 5/7/2025 - 5:15:49 PM
Coverage date: 5/7/2025 - 5:05:19 PM - 5/7/2025 - 5:15:21 PM
Parser: MultiReport (60x Cobertura)
Assemblies: 1
Classes: 7
Files: 2
Line coverage: 80.3% (620 of 772)
Covered lines: 620
Uncovered lines: 152
Coverable lines: 772
Total lines: 483
Branch coverage: 67.8% (228 of 336)
Covered branches: 228
Total branches: 336
Method coverage: Feature is only available for sponsors

Coverage

Microsoft.IdentityModel.JsonWebTokens - 80.3%
Name Line Branch
Microsoft.IdentityModel.JsonWebTokens 80.3% 67.8%
Microsoft.IdentityModel.JsonWebTokens.JwtTokenUtilities 100%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated 80.3% 67.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F12A1AEDDDFE32BA
DF4DBFF323AF1BCB48B9F9721B7CD3E05F5E034CF225E3DF8__CreateJwsRegex_0
81.4% 67.6%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJweRegex_1
79.2% 68%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F334844C618E00D3
CEC5D3FE0D00CF0141BBEE98635313BB2CB8D3921464CE05A__CreateJwsRegex_0
81.4% 67.6%

@saurabhsathe-ms saurabhsathe-ms requested a review from sruke May 7, 2025 18:52
Comment thread src/Microsoft.IdentityModel.Tokens/SecurityTokenDescriptor.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/SecurityTokenDescriptor.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs Outdated
@saurabhsathe-ms
Copy link
Copy Markdown
Contributor Author

@kevinchalet here is a brief summary of whats happening and what will happen once this PR is merged:

actor token was being converted into unsigned jwt, so the claims would be like:
tid:xyz
actor: unsigned-jwt
client:xczxcz

and so on.
Then the whole token was encoded into a signed JWT which means actor token encoded twice. Hence when you decrypted the token, the actor claim was an unsigned JWT to be decrypted again.

Now after per my PR, the act claim would be first converted in a JSON object and then encoded. So when you decrypt the token and extract claims, the actor would be deserialized into JSON object not an unsigned JWT.

saurabhsathe-ms and others added 6 commits April 6, 2026 10:26
Co-authored-by: Westin Musser <127992899+westin-m@users.noreply.github.com>
Co-authored-by: Westin Musser <127992899+westin-m@users.noreply.github.com>
Co-authored-by: Westin Musser <127992899+westin-m@users.noreply.github.com>
Co-authored-by: Westin Musser <127992899+westin-m@users.noreply.github.com>
Co-authored-by: Westin Musser <127992899+westin-m@users.noreply.github.com>
Co-authored-by: Westin Musser <127992899+westin-m@users.noreply.github.com>
@kevinchalet
Copy link
Copy Markdown
Contributor

kevinchalet commented Apr 6, 2026

Now after per my PR, the act claim would be first converted in a JSON object and then encoded. So when you decrypt the token and extract claims, the actor would be deserialized into JSON object not an unsigned JWT.

Sounds good 👍🏻

I guess I got confused by the name of the existing WriteJwsPayload method, that actually writes a JSON object and not a token (to be honest, the name of that method is a bit confusing as the "JWS payload" is actually an arbitrary sequence of octets in the spec).

Count on me to give it a try when the nightly builds are available 👍🏻

Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs Outdated
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs Outdated
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs Outdated
Comment thread src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/SecurityTokenDescriptor.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs Outdated
Comment thread src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] ClaimsIdentity Actor not serialized into JWTs

8 participants