From 37cfe171f9e79bb9338c16aae0a5a4dfce46fe96 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Wed, 26 Jul 2023 19:06:05 -0400 Subject: [PATCH] Remove unnecessary string.Split in JsonWebTokenHandler.CanReadToken (#2175) We can count the number of periods instead of allocating a string for each segment and a string[] to store them all in. --- .../JsonWebTokenHandler.cs | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs index 7b82d6c088..61165331c3 100644 --- a/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs +++ b/src/Microsoft.IdentityModel.JsonWebTokens/JsonWebTokenHandler.cs @@ -162,17 +162,28 @@ public virtual bool CanReadToken(string token) return false; } - // Set the maximum number of segments to MaxJwtSegmentCount + 1. This controls the number of splits and allows detecting the number of segments is too large. - // For example: "a.b.c.d.e.f.g.h" => [a], [b], [c], [d], [e], [f.g.h]. 6 segments. - // If just MaxJwtSegmentCount was used, then [a], [b], [c], [d], [e.f.g.h] would be returned. 5 segments. - int tokenPartCount = JwtTokenUtilities.CountJwtTokenPart(token, JwtConstants.MaxJwtSegmentCount + 1); - if (tokenPartCount == JwtConstants.JwsSegmentCount) - return JwtTokenUtilities.RegexJws.IsMatch(token); - else if (tokenPartCount == JwtConstants.JweSegmentCount) - return JwtTokenUtilities.RegexJwe.IsMatch(token); - - LogHelper.LogInformation(LogMessages.IDX14107); - return false; + // Count the number of segments, which is the number of periods + 1. We can stop when we've encountered + // more segments than the maximum we know how to handle. + int pos = 0; + int segmentCount = 1; // TODO: Use MemoryExtensions.Count in .NET 8 + while (segmentCount <= JwtConstants.MaxJwtSegmentCount && ((pos = token.IndexOf('.', pos)) >= 0)) + { + pos++; + segmentCount++; + } + + switch (segmentCount) + { + case JwtConstants.JwsSegmentCount: + return JwtTokenUtilities.RegexJws.IsMatch(token); + + case JwtConstants.JweSegmentCount: + return JwtTokenUtilities.RegexJwe.IsMatch(token); + + default: + LogHelper.LogInformation(LogMessages.IDX14107); + return false; + } } ///