diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/IDWebErrorMessage.cs b/src/Microsoft.Identity.Web.TokenAcquisition/IDWebErrorMessage.cs
index 12a59bda6..e21d33406 100644
--- a/src/Microsoft.Identity.Web.TokenAcquisition/IDWebErrorMessage.cs
+++ b/src/Microsoft.Identity.Web.TokenAcquisition/IDWebErrorMessage.cs
@@ -51,6 +51,8 @@ internal static class IDWebErrorMessage
public const string MicrosoftIdentityWebChallengeUserException = "IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. " +
"See https://aka.ms/ms-id-web/ca_incremental-consent. ";
public const string ProvidedAuthenticationSchemeIsIncorrect = "IDW10503: Cannot determine the cloud Instance. The provided authentication scheme was '{0}'. Microsoft.Identity.Web inferred '{1}' as the authentication scheme. Available authentication schemes are '{2}'. See https://aka.ms/id-web/authSchemes. ";
+ public const string InvalidAssertion = "IDW10504: Invalid assertion: contains unsupported character(s).";
+ public const string InvalidSubAssertion = "IDW10505: Invalid sub_assertion: contains unsupported character(s).";
// Encoding IDW10600 = "IDW10600:"
public const string InvalidBase64UrlString = "IDW10601: Invalid Base64URL string. ";
diff --git a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs
index d51917375..89ae878f3 100644
--- a/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs
+++ b/src/Microsoft.Identity.Web.TokenAcquisition/TokenAcquisition.cs
@@ -783,6 +783,10 @@ private void NotifyCertificateSelection(MergedOptions mergedOptions, IConfidenti
// Special case when the OBO inbound token is composite (for instance PFT)
if (dict.ContainsKey(assertionConstant) && dict.ContainsKey(subAssertionConstant))
{
+
+ // Check assertion and sub_assertion passed from merging extra query parameters to ensure they do not contain unsupported character(s).
+ CheckAssertionsForInjectionAttempt(dict[assertionConstant], dict[subAssertionConstant]);
+
builder.OnBeforeTokenRequest((data) =>
{
// Replace the assertion and adds sub_assertion with the values from the extra query parameters
@@ -831,6 +835,20 @@ private void NotifyCertificateSelection(MergedOptions mergedOptions, IConfidenti
}
}
+ ///
+ /// Checks assertion and sub_assertion passed from merging extra query parameters to ensure they do not contain unsupported characters.
+ ///
+ /// The assertion.
+ /// The sub_assertion.
+ private static void CheckAssertionsForInjectionAttempt(string assertion, string subAssertion)
+ {
+ if (!assertion.IsNullOrEmpty() || !subAssertion.IsNullOrEmpty())
+ {
+ if (!assertion.IsNullOrEmpty() && assertion.Contains('&', StringComparison.InvariantCultureIgnoreCase)) throw new ArgumentException(IDWebErrorMessage.InvalidAssertion, nameof(assertion));
+ if (!subAssertion.IsNullOrEmpty() && (subAssertion.Contains('&', StringComparison.InvariantCultureIgnoreCase))) throw new ArgumentException(IDWebErrorMessage.InvalidSubAssertion, nameof(subAssertion));
+ }
+ }
+
private static string? GetActualToken(SecurityToken? validatedToken)
{
JwtSecurityToken? jwtSecurityToken = validatedToken as JwtSecurityToken;