Serialize and deserialize actor token in claims identity#3219
Serialize and deserialize actor token in claims identity#3219saurabhsathe-ms wants to merge 86 commits intodevfrom
Conversation
… update also involves serializing logic for Subject Actors
…king aot functionality or back compatibility
… the method we created
…tcase. Testcases need more modifications
…Added new test case to test serialization precedence
… working after fixing a bug in how claims dictionary was processed
… testcase ot now expect he new exception expected.
SummarySummary
CoverageMicrosoft.IdentityModel.JsonWebTokens - 80.3%
|
SummarySummary
CoverageMicrosoft.IdentityModel.JsonWebTokens - 80.3%
|
SummarySummary
CoverageMicrosoft.IdentityModel.JsonWebTokens - 80.3%
|
SummarySummary
CoverageMicrosoft.IdentityModel.JsonWebTokens - 80.3%
|
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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
SummarySummary
CoverageMicrosoft.IdentityModel.JsonWebTokens - 80.3%
|
…t I will need for deserialization as well
SummarySummary
CoverageMicrosoft.IdentityModel.JsonWebTokens - 80.3%
|
SummarySummary
CoverageMicrosoft.IdentityModel.JsonWebTokens - 80.3%
|
|
@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: and so on. 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. |
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>
Sounds good 👍🏻 I guess I got confused by the name of the existing Count on me to give it a try when the nightly builds are available 👍🏻 |
Serialize and deserialize actor token in claims identity
Actor Token Serialization History
The
JsonWebTokenHandlernever 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 olderJwtSecurityTokenHandlerhas always correctly serialized theClaimsIdentity. Actorproperty into theactortclaim in JWTs. However, whenJsonWebTokenHandlerwas created as a more performant alternative, the actor serialization logic was not ported over. The handler only processed individual claims fromSubject.Claimsand never handled theSubject.Actorproperty 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 bringJsonWebTokenHandlerto feature parity withJwtSecurityTokenHandler.File changes:
Act vs Actort
actortvsactClaimsact(RFC 8693)actort(Microsoft IdentityModel){ "act": { "sub": "...", "iss": "..." } }"actort": "eyJhbG..."(JWT)actfor delegation chainsExample of
act(RFC 8693):{ "sub": "user@example.com", "act": { "sub": "client@example.com" } }Note:
actortpredates RFC 8693 and is used in this library for backward compatibility. It maps toClaimTypes.Actorwhen processing claims. For RFC 8693 compliance, the standardactclaim is recommended.Requirements
Serialization Requirements:
Deserialization Requirements
Approach:
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
isActorFoundflag to track if actor claim exists in the Claims dictionarytokenDescriptor.ActorClaimTypeWriteActorToken()that serializes actor tokens as JSON objects in the JWT payloadValidateActorChainDepth()method to enforce maximum actor nesting depthCreateActorTokenDescriptor()method that creates a SecurityTokenDescriptor for actor tokens from either Claims dictionary or Subject. Actor property2. src/Microsoft. IdentityModel. JsonWebTokens/JsonWebTokenHandler.ValidateToken.cs
using System.Text.JsonimportCreateClaimsIdentityWithMapping()andCreateClaimsIdentityPrivate()to handle bothactorClaimType(configurable) and legacy"actort"claimsCreateClaimsIdentityActor()that:actclaims as JSON objects usingTryGetPayloadValue<JsonElement>ActClaimRetrieverDelegate) for custom actor claim processingactortclaims usingCanReadToken()/ReadToken()CreateActorClaimsIdentityFromJsonElement()that:CaseSensitiveClaimsIdentityfrom a JsonElementMaxActorChainLengthlimit3. src/Microsoft. IdentityModel.JsonWebTokens/LogMessages.cs
IDX14313: Maximum actor token depth reached during serialization/deserializationIDX14314: Exception while using custom delegate to deserialize act claimIDX14315: Actor claim is not a ClaimsIdentity (wrong type provided)4. src/Microsoft.IdentityModel.JsonWebTokens/Microsoft.IdentityModel.JsonWebTokens.csproj
5. src/Microsoft.IdentityModel.JsonWebTokens/PublicAPI. Unshipped.txt
CreateActorClaimsIdentityFromJsonElementstatic method6. src/Microsoft.IdentityModel. Tokens/Delegates.cs
ActClaimRetrieverDelegate- allows custom validation/conversion of theactclaim JSON element to aClaimsIdentity7. src/Microsoft.IdentityModel.Tokens/InternalAPI. Unshipped.txt
EnableActClaimSupportSwitchconstantEnableActClaimSupportpropertyIDX11027log message constant8. src/Microsoft.IdentityModel.Tokens/LogMessages.cs
IDX11027: Invalid JsonWebToken handler configuration parameter value9. src/Microsoft.IdentityModel.Tokens/PublicAPI.Unshipped.txt
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)ActClaimRetrieverDelegatedelegate type10. src/Microsoft.IdentityModel.Tokens/SecurityTokenDescriptor.cs
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 serializationArgumentOutOfRangeExceptionfor invalid values11. src/Microsoft.IdentityModel.Tokens/TokenValidationParameters.cs
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 deserializationActClaimRetrieverDelegate: Custom delegate for converting actor claim JSON to ClaimsIdentityClone()method to copy all new actor-related properties12. test/Microsoft.IdentityModel.JsonWebTokens. Tests/ActorClaimsTests.cs (New Files)
ActClaimDeserializationTests: Comprehensive tests for actor claim deserialization including:
ValidateTokenAsynctests with actorsactortJWT string handlingActClaimSerializationTests: Comprehensive tests for actor claim serialization including:
13. test/Microsoft.IdentityModel.TestUtils/ValidationDelegates.cs
ActClaimRetrieverDelegateimplementation for testing purposes (returns null)14. test/Microsoft.IdentityModel. Tokens.Tests/TokenValidationParametersTests.cs
ExpectedPropertyCountfrom 62 to 66ActorClaimType,ActorChainDepth,MaxActorChainLengthCreateTokenValidationParameters()to setActClaimRetrieverDelegateKey Notes
No AppContext Switch Changes: The current diff does not include any changes to
AppContextSwitches. cs. TheEnableActClaimSupportSwitchreferenced in the API files appears to be documented but the actual implementation inAppContextSwitches.csis not part of this diff.Summary: This PR adds comprehensive support for serializing and deserializing actor claims (
act) in JWT tokens usingJsonWebTokenHandler, with configurable nesting depth limits, custom delegate support for deserialization, and backward compatibility with legacyactortclaims.Fixes #1840