-
Notifications
You must be signed in to change notification settings - Fork 409
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Regression tests: Token Type (#2932)
* Renamed ValidationParameters.TypeValidator to ValidationParameters.TokenTypeValidator * Removed log from TokenType validation * Added TokenTypeValidationError to create the exception and assign the invalid token type. Updated the token type validator to use it. * Adjusted the creation of SecurityTokenInvalidTypeException to return the correct invalid type when it is empty or null * Added regression/comparison tests around token type validation scenarios * Added test for valid scenario where there are no valid types specified * Return null for the invalid token type if the type is an empty string to keep considency with existing tests. * Updated renamed variable * Addressed post merge issues
- Loading branch information
Showing
13 changed files
with
206 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
src/Microsoft.IdentityModel.Tokens/Validation/Results/Details/TokenTypeValidationError.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Diagnostics; | ||
|
||
#nullable enable | ||
namespace Microsoft.IdentityModel.Tokens | ||
{ | ||
internal class TokenTypeValidationError : ValidationError | ||
{ | ||
protected string? _invalidTokenType; | ||
|
||
internal TokenTypeValidationError( | ||
MessageDetail messageDetail, | ||
Type exceptionType, | ||
StackFrame stackFrame, | ||
string? invalidTokenType) | ||
: base(messageDetail, ValidationFailureType.TokenTypeValidationFailed, exceptionType, stackFrame) | ||
{ | ||
_invalidTokenType = invalidTokenType; | ||
} | ||
|
||
internal override Exception GetException() | ||
{ | ||
if (ExceptionType == typeof(SecurityTokenInvalidTypeException)) | ||
{ | ||
SecurityTokenInvalidTypeException exception = new(MessageDetail.Message, InnerException) | ||
{ | ||
InvalidType = _invalidTokenType | ||
}; | ||
|
||
return exception; | ||
} | ||
|
||
return base.GetException(); | ||
} | ||
} | ||
} | ||
#nullable restore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
142 changes: 142 additions & 0 deletions
142
...dentityModel.JsonWebTokens.Tests/JsonWebTokenHandler.ValidateTokenAsyncTests.TokenType.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
#nullable enable | ||
using System.Threading.Tasks; | ||
using Microsoft.IdentityModel.TestUtils; | ||
using Microsoft.IdentityModel.Tokens; | ||
using Xunit; | ||
|
||
namespace Microsoft.IdentityModel.JsonWebTokens.Tests | ||
{ | ||
public partial class JsonWebTokenHandlerValidateTokenAsyncTests | ||
{ | ||
[Theory, MemberData(nameof(ValidateTokenAsync_TokenTypeTestCases), DisableDiscoveryEnumeration = true)] | ||
public async Task ValidateTokenAsync_TokenType(ValidateTokenAsyncTokenTypeTheoryData theoryData) | ||
{ | ||
var context = TestUtilities.WriteHeader($"{this}.ValidateTokenAsync_TokenType", theoryData); | ||
|
||
string jwtString = CreateTokenForTokenTypeValidation(theoryData.UseEmptyType, theoryData.CustomTokenType); | ||
|
||
await ValidateAndCompareResults(jwtString, theoryData, context); | ||
|
||
TestUtilities.AssertFailIfErrors(context); | ||
} | ||
|
||
public static TheoryData<ValidateTokenAsyncTokenTypeTheoryData> ValidateTokenAsync_TokenTypeTestCases | ||
{ | ||
get | ||
{ | ||
var theoryData = new TheoryData<ValidateTokenAsyncTokenTypeTheoryData>(); | ||
|
||
theoryData.Add(new ValidateTokenAsyncTokenTypeTheoryData("Valid_JwtToken") | ||
{ | ||
TokenValidationParameters = CreateTokenValidationParameters(), | ||
ValidationParameters = CreateValidationParameters(), | ||
}); | ||
|
||
theoryData.Add(new ValidateTokenAsyncTokenTypeTheoryData("Valid_UnknownTokenType_NoValidTokenTypes") | ||
{ | ||
// If there are no valid token types, any token type is valid | ||
CustomTokenType = "SomeUnknownType", | ||
TokenValidationParameters = CreateTokenValidationParameters(null), | ||
ValidationParameters = CreateValidationParameters(null), | ||
}); | ||
|
||
theoryData.Add(new ValidateTokenAsyncTokenTypeTheoryData("Valid_CustomToken_AddedAsValidTokenType") | ||
{ | ||
CustomTokenType = "PPT", | ||
TokenValidationParameters = CreateTokenValidationParameters(validTokenType: "PPT"), | ||
ValidationParameters = CreateValidationParameters(validTokenType: "PPT"), | ||
}); | ||
|
||
theoryData.Add(new ValidateTokenAsyncTokenTypeTheoryData("Invalid_CustomToken_NotAddedAsValidTokenType") | ||
{ | ||
CustomTokenType = "PPT", | ||
TokenValidationParameters = CreateTokenValidationParameters(), | ||
ValidationParameters = CreateValidationParameters(), | ||
ExpectedIsValid = false, | ||
ExpectedException = ExpectedException.SecurityTokenInvalidTypeException("IDX10257:"), | ||
}); | ||
|
||
theoryData.Add(new ValidateTokenAsyncTokenTypeTheoryData("Invalid_EmptyTokenType") | ||
{ | ||
UseEmptyType = true, | ||
TokenValidationParameters = CreateTokenValidationParameters(), | ||
ValidationParameters = CreateValidationParameters(), | ||
ExpectedIsValid = false, | ||
ExpectedException = ExpectedException.SecurityTokenInvalidTypeException("IDX10256:"), | ||
}); | ||
|
||
return theoryData; | ||
|
||
static TokenValidationParameters CreateTokenValidationParameters(string? validTokenType = "JWT") | ||
{ | ||
// only validate the signature and issuer signing key | ||
var tokenValidationParameters = new TokenValidationParameters() | ||
{ | ||
ValidateAudience = false, | ||
ValidateIssuer = false, | ||
ValidateLifetime = false, | ||
ValidateTokenReplay = false, | ||
ValidateIssuerSigningKey = false, | ||
RequireSignedTokens = false, | ||
}; | ||
|
||
if (validTokenType is not null) | ||
tokenValidationParameters.ValidTypes = [validTokenType]; | ||
|
||
return tokenValidationParameters; | ||
} | ||
|
||
static ValidationParameters CreateValidationParameters(string? validTokenType = "JWT") | ||
{ | ||
ValidationParameters validationParameters = new ValidationParameters(); | ||
|
||
// Skip all validations except token type | ||
validationParameters.AlgorithmValidator = SkipValidationDelegates.SkipAlgorithmValidation; | ||
validationParameters.AudienceValidator = SkipValidationDelegates.SkipAudienceValidation; | ||
validationParameters.IssuerSigningKeyValidator = SkipValidationDelegates.SkipIssuerSigningKeyValidation; | ||
validationParameters.IssuerValidatorAsync = SkipValidationDelegates.SkipIssuerValidation; | ||
validationParameters.LifetimeValidator = SkipValidationDelegates.SkipLifetimeValidation; | ||
validationParameters.SignatureValidator = SkipValidationDelegates.SkipSignatureValidation; | ||
validationParameters.TokenReplayValidator = SkipValidationDelegates.SkipTokenReplayValidation; | ||
|
||
if (validTokenType is not null) | ||
validationParameters.ValidTypes.Add(validTokenType); | ||
|
||
return validationParameters; | ||
} | ||
} | ||
} | ||
|
||
public class ValidateTokenAsyncTokenTypeTheoryData : ValidateTokenAsyncBaseTheoryData | ||
{ | ||
public ValidateTokenAsyncTokenTypeTheoryData(string testId) : base(testId) { } | ||
|
||
public bool UseEmptyType { get; set; } = false; | ||
|
||
public string? CustomTokenType { get; set; } = null; | ||
} | ||
|
||
// Custom JWT with empty string for type | ||
private static string emptyTypeJWT = "eyJ0eXAiOiIiLCJhbGciOiJub25lIn0.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWUsImlhdCI6MTcyOTY5NDI1OCwiZXhwIjoxNzI5Njk3ODU4fQ."; | ||
|
||
private static string CreateTokenForTokenTypeValidation(bool useEmptyType = false, string? tokenType = null) | ||
{ | ||
if (useEmptyType) | ||
return emptyTypeJWT; | ||
|
||
JsonWebTokenHandler jsonWebTokenHandler = new JsonWebTokenHandler(); | ||
|
||
SecurityTokenDescriptor securityTokenDescriptor = new SecurityTokenDescriptor | ||
{ | ||
Subject = Default.ClaimsIdentity, | ||
TokenType = tokenType ?? "JWT", | ||
}; | ||
|
||
return jsonWebTokenHandler.CreateToken(securityTokenDescriptor); | ||
} | ||
} | ||
} | ||
#nullable restore |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters