From 1517cddc2231ab3a0981d72e5c4e802f68e98fe9 Mon Sep 17 00:00:00 2001
From: joegoldman2 <147369450+joegoldman2@users.noreply.github.com>
Date: Tue, 18 Jun 2024 21:23:42 +0000
Subject: [PATCH 1/5] Add a constant for the profile scope in
OpenIdConnectScope class (#2647)
Co-authored-by: joegoldman2 <147369450+joegoldman@users.noreply.github.com>
---
.../OpenIdConnectScope.cs | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/OpenIdConnectScope.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/OpenIdConnectScope.cs
index 6a3c753e77..c32880eaaf 100644
--- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/OpenIdConnectScope.cs
+++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/OpenIdConnectScope.cs
@@ -37,10 +37,15 @@ public static class OpenIdConnectScope
public const string OpenIdProfile = "openid profile";
///
- /// Indicates phone profile scope see: https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims.
+ /// Indicates phone scope see: https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims.
///
public const string Phone = "phone";
+ ///
+ /// Indicates profile scope see: https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims.
+ ///
+ public const string Profile = "profile";
+
///
/// Indicates user_impersonation scope for Azure Active Directory.
///
From bd2bf8e7098e54b83729c716c30ca29aade7dc31 Mon Sep 17 00:00:00 2001
From: kellyyangsong <69649063+kellyyangsong@users.noreply.github.com>
Date: Tue, 18 Jun 2024 14:35:19 -0700
Subject: [PATCH 2/5] Rm SkipAuthenticationTagLengthValidation and
UseShortNameForRsaOaepKey App Context Switches (#2644)
* rm app context switches
* update tests
* update changelog
---
CHANGELOG.md | 2 +-
.../AuthenticatedEncryptionProvider.cs | 9 +--
.../LogMessages.cs | 2 +-
.../X509EncryptingCredentials.cs | 14 +---
.../JsonWebTokenHandlerTests.cs | 50 +-------------
.../EncryptingCredentialsTests.cs | 8 +--
.../MultiThreadingTests.cs | 4 +-
.../X509EncryptingCredentialsTests.cs | 8 +--
...tyTokenHandlerTests.WithContextSwitches.cs | 66 -------------------
9 files changed, 16 insertions(+), 147 deletions(-)
delete mode 100644 test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTests.WithContextSwitches.cs
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f1991880f9..5a9f0c8101 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,7 +5,7 @@ See the [releases](https://github.com/AzureAD/azure-activedirectory-identitymode
### Breaking changes:
- IdentityModel 8x no longer supports .net461, which has reached end of life and is no longer supported. See issue [#2544](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/2544) for details.
- Two IdentityModel extension dlls `Microsoft.IdentityModel.KeyVaultExtensions` and `Microsoft.IdentityModel.ManagedKeyVaultSecurityKey` were using ADAL, which is no longer supported . The affected packages have been removed, as the replacement is to use [Microsoft.Identity.Web](https://github.com/AzureAD/microsoft-identity-web/wiki/Certificates). See issue [#2454](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/2454) for details.
-- `AppContext.SetSwitch` which were included in IdentityModel 7x, have been removed and are the default in IdentityModel 8x. The result is a more performant IdentityModel by default. See issue [#2629](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/2629) for details.
+- `AppContext.SetSwitch` which were included in IdentityModel 7x, have been removed and are the default in IdentityModel 8x. The result is a more performant IdentityModel by default. See issue [#2629](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/2629) and https://aka.ms/IdentityModel8x for details.
7.6.1
=====
diff --git a/src/Microsoft.IdentityModel.Tokens/Encryption/AuthenticatedEncryptionProvider.cs b/src/Microsoft.IdentityModel.Tokens/Encryption/AuthenticatedEncryptionProvider.cs
index b6b063936d..b9459a1af8 100644
--- a/src/Microsoft.IdentityModel.Tokens/Encryption/AuthenticatedEncryptionProvider.cs
+++ b/src/Microsoft.IdentityModel.Tokens/Encryption/AuthenticatedEncryptionProvider.cs
@@ -33,7 +33,6 @@ private struct AuthenticatedKeys
private DecryptionDelegate DecryptFunction;
private EncryptionDelegate EncryptFunction;
private const string _className = "Microsoft.IdentityModel.Tokens.AuthenticatedEncryptionProvider";
- internal const string _skipValidationOfAuthenticationTagLength = "Switch.Microsoft.IdentityModel.SkipAuthenticationTagLengthValidation";
///
/// Initializes a new instance of the class used for encryption and decryption.
@@ -167,8 +166,7 @@ private AuthenticatedEncryptionResult EncryptWithAesCbc(byte[] plaintext, byte[]
private byte[] DecryptWithAesCbc(byte[] ciphertext, byte[] authenticatedData, byte[] iv, byte[] authenticationTag)
{
// Verify authentication Tag
- if (ShouldValidateAuthenticationTagLength()
- && SymmetricSignatureProvider.ExpectedSignatureSizeInBytes.TryGetValue(Algorithm, out int expectedTagLength)
+ if (SymmetricSignatureProvider.ExpectedSignatureSizeInBytes.TryGetValue(Algorithm, out int expectedTagLength)
&& expectedTagLength != authenticationTag.Length)
throw LogHelper.LogExceptionMessage(new SecurityTokenDecryptionFailedException(
LogHelper.FormatInvariant(LogMessages.IDX10625, authenticationTag.Length, expectedTagLength, Base64UrlEncoder.Encode(authenticationTag), Algorithm)));
@@ -197,11 +195,6 @@ private byte[] DecryptWithAesCbc(byte[] ciphertext, byte[] authenticatedData, by
}
}
- private static bool ShouldValidateAuthenticationTagLength()
- {
- return !(AppContext.TryGetSwitch(_skipValidationOfAuthenticationTagLength, out bool skipValidation) && skipValidation);
- }
-
private AuthenticatedKeys CreateAuthenticatedKeys()
{
ValidateKeySize(Key, Algorithm);
diff --git a/src/Microsoft.IdentityModel.Tokens/LogMessages.cs b/src/Microsoft.IdentityModel.Tokens/LogMessages.cs
index d54c07479c..689b2ccb9d 100644
--- a/src/Microsoft.IdentityModel.Tokens/LogMessages.cs
+++ b/src/Microsoft.IdentityModel.Tokens/LogMessages.cs
@@ -136,7 +136,7 @@ internal static class LogMessages
// public const string IDX10622 = "IDX10622:";
// public const string IDX10623 = "IDX10623:";
// public const string IDX10624 = "IDX10624:";
- public const string IDX10625 = "IDX10625: Failed to verify the authenticationTag length, the actual tag length '{0}' does not match the expected tag length '{1}'. authenticationTag: '{2}', algorithm: '{3}' See: https://aka.ms/IdentityModel/SkipAuthenticationTagLengthValidation";
+ public const string IDX10625 = "IDX10625: Failed to verify the authenticationTag length, the actual tag length '{0}' does not match the expected tag length '{1}'. authenticationTag: '{2}', algorithm: '{3}'.";
// public const string IDX10627 = "IDX10627:";
public const string IDX10628 = "IDX10628: Cannot set the MinimumSymmetricKeySizeInBits to less than '{0}'.";
public const string IDX10630 = "IDX10630: The '{0}' for signing cannot be smaller than '{1}' bits. KeySize: '{2}'.";
diff --git a/src/Microsoft.IdentityModel.Tokens/X509EncryptingCredentials.cs b/src/Microsoft.IdentityModel.Tokens/X509EncryptingCredentials.cs
index ec0f483dd8..6a92eaedaa 100644
--- a/src/Microsoft.IdentityModel.Tokens/X509EncryptingCredentials.cs
+++ b/src/Microsoft.IdentityModel.Tokens/X509EncryptingCredentials.cs
@@ -11,8 +11,6 @@ namespace Microsoft.IdentityModel.Tokens
///
public class X509EncryptingCredentials : EncryptingCredentials
{
- internal const string _useShortNameForRsaOaepKey = "Switch.Microsoft.IdentityModel.UseShortNameForRsaOaepKey";
-
///
/// Designed to construct based on a x509 certificate.
///
@@ -23,7 +21,7 @@ public class X509EncryptingCredentials : EncryptingCredentials
///
/// if 'certificate' is null.
public X509EncryptingCredentials(X509Certificate2 certificate)
- : this(certificate, GetEncryptionAlgorithm(), SecurityAlgorithms.DefaultSymmetricEncryptionAlgorithm)
+ : this(certificate, SecurityAlgorithms.RsaOAEP, SecurityAlgorithms.DefaultSymmetricEncryptionAlgorithm)
{
}
@@ -50,15 +48,5 @@ public X509Certificate2 Certificate
get;
private set;
}
-
- private static string GetEncryptionAlgorithm()
- {
- return ShouldUseShortNameForRsaOaepKey() ? SecurityAlgorithms.RsaOAEP : SecurityAlgorithms.DefaultAsymmetricKeyWrapAlgorithm;
- }
-
- private static bool ShouldUseShortNameForRsaOaepKey()
- {
- return AppContext.TryGetSwitch(_useShortNameForRsaOaepKey, out var useKeyWrap) && useKeyWrap;
- }
}
}
diff --git a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTests.cs b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTests.cs
index bd041cac2f..6b67a4f4e3 100644
--- a/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTests.cs
+++ b/test/Microsoft.IdentityModel.JsonWebTokens.Tests/JsonWebTokenHandlerTests.cs
@@ -4190,10 +4190,9 @@ public static TheoryData IncludeSecurityTokenOnFailureTes
}
[Theory, MemberData(nameof(ValidateAuthenticationTagLengthTheoryData))]
- public void ValidateTokenAsync_ModifiedAuthNTag(CreateTokenTheoryData theoryData)
+ public async Task ValidateTokenAsync_ModifiedAuthNTag(CreateTokenTheoryData theoryData)
{
// arrange
- AppContext.SetSwitch(AuthenticatedEncryptionProvider._skipValidationOfAuthenticationTagLength, theoryData.EnableAppContextSwitch);
var payload = new JObject()
{
{ JwtRegisteredClaimNames.Email, "Bob@contoso.com" },
@@ -4217,9 +4216,7 @@ public void ValidateTokenAsync_ModifiedAuthNTag(CreateTokenTheoryData theoryData
var jweWithExtraCharacters = jwe + "_cannoli_hunts_truffles_";
// act
- // calling ValidateTokenAsync.Result to prevent tests from sharing app context switch property
- // normally, we would want to await ValidateTokenAsync().ConfigureAwait(false)
- var tokenValidationResult = jsonWebTokenHandler.ValidateTokenAsync(jweWithExtraCharacters, theoryData.ValidationParameters).Result;
+ var tokenValidationResult = await jsonWebTokenHandler.ValidateTokenAsync(jweWithExtraCharacters, theoryData.ValidationParameters).ConfigureAwait(false);
// assert
Assert.Equal(theoryData.IsValid, tokenValidationResult.IsValid);
@@ -4281,47 +4278,6 @@ public static TheoryData ValidateAuthenticationTagLengthT
ValidIssuer = "http://Default.Issuer.com",
},
IsValid = false
- },
- new("A128CBC-HS256_SkipTagLengthValidationAppContextSwitchOn_IsValid")
- {
- EnableAppContextSwitch = true,
- Algorithm = SecurityAlgorithms.Aes128CbcHmacSha256,
- EncryptingCredentials = new EncryptingCredentials(KeyingMaterial.RsaSecurityKey_2048, SecurityAlgorithms.RsaPKCS1, SecurityAlgorithms.Aes128CbcHmacSha256),
- ValidationParameters = new TokenValidationParameters
- {
- TokenDecryptionKey = KeyingMaterial.JsonWebKeyRsa256SigningCredentials.Key,
- IssuerSigningKey = Default.SymmetricSigningKey256,
- ValidAudience = "http://Default.Audience.com",
- ValidIssuer = "http://Default.Issuer.com",
- },
- IsValid = true
- },
- new("A192CBC-HS384_SkipTagLengthValidationAppContextSwitchOn_IsValid")
- {
- EnableAppContextSwitch = true,
- Algorithm = SecurityAlgorithms.Aes192CbcHmacSha384,
- EncryptingCredentials = new EncryptingCredentials(KeyingMaterial.RsaSecurityKey_2048, SecurityAlgorithms.RsaPKCS1, SecurityAlgorithms.Aes192CbcHmacSha384),
- ValidationParameters = new TokenValidationParameters
- {
- TokenDecryptionKey = KeyingMaterial.JsonWebKeyRsa256SigningCredentials.Key,
- IssuerSigningKey = Default.SymmetricSigningKey256,
- ValidAudience = "http://Default.Audience.com",
- ValidIssuer = "http://Default.Issuer.com",
- },
- IsValid = true
- },
- new("A256CBC-HS512_SkipTagLengthValidationAppContextSwitchOn_IsValid")
- {
- EnableAppContextSwitch = true,
- EncryptingCredentials = new EncryptingCredentials(KeyingMaterial.RsaSecurityKey_2048, SecurityAlgorithms.RsaPKCS1, SecurityAlgorithms.Aes256CbcHmacSha512),
- ValidationParameters = new TokenValidationParameters
- {
- TokenDecryptionKey = signingCredentials512.Key,
- IssuerSigningKey = Default.SymmetricSigningKey256,
- ValidAudience = "http://Default.Audience.com",
- ValidIssuer = "http://Default.Issuer.com",
- },
- IsValid = true
}
};
}
@@ -4370,8 +4326,6 @@ public CreateTokenTheoryData(string testId) : base(testId)
public IEnumerable ExpectedDecryptionKeys { get; set; }
public Dictionary ExpectedClaims { get; set; }
-
- public bool EnableAppContextSwitch { get; set; } = false;
}
// Overrides CryptoProviderFactory.CreateAuthenticatedEncryptionProvider to create AuthenticatedEncryptionProviderMock that provides AesGcm encryption.
diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/EncryptingCredentialsTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/EncryptingCredentialsTests.cs
index 7b44f1b844..ad787f01d4 100644
--- a/test/Microsoft.IdentityModel.Tokens.Tests/EncryptingCredentialsTests.cs
+++ b/test/Microsoft.IdentityModel.Tokens.Tests/EncryptingCredentialsTests.cs
@@ -57,7 +57,7 @@ public static TheoryData ConstructorATheoryData
new EncryptingCredentialsTheoryData
{
Key = null,
- Alg = SecurityAlgorithms.RsaOaepKeyWrap,
+ Alg = SecurityAlgorithms.RsaOAEP,
Enc = SecurityAlgorithms.Aes128CbcHmacSha256,
ExpectedException = ExpectedException.ArgumentNullException("IDX10000: The parameter 'key'"),
TestId = "NullKey"
@@ -73,7 +73,7 @@ public static TheoryData ConstructorATheoryData
new EncryptingCredentialsTheoryData
{
Key = Default.AsymmetricEncryptionKeyPublic,
- Alg = SecurityAlgorithms.RsaOaepKeyWrap,
+ Alg = SecurityAlgorithms.RsaOAEP,
Enc = String.Empty,
ExpectedException = ExpectedException.ArgumentNullException("IDX10000: The parameter 'enc'"),
TestId = "EmptyEncString"
@@ -89,7 +89,7 @@ public static TheoryData ConstructorATheoryData
new EncryptingCredentialsTheoryData
{
Key = Default.AsymmetricEncryptionKeyPublic,
- Alg = SecurityAlgorithms.RsaOaepKeyWrap,
+ Alg = SecurityAlgorithms.RsaOAEP,
Enc = null,
ExpectedException = ExpectedException.ArgumentNullException("IDX10000: The parameter 'enc'"),
TestId = "NullEncString"
@@ -97,7 +97,7 @@ public static TheoryData ConstructorATheoryData
new EncryptingCredentialsTheoryData
{
Key = Default.AsymmetricEncryptionKeyPublic,
- Alg = SecurityAlgorithms.RsaOaepKeyWrap,
+ Alg = SecurityAlgorithms.RsaOAEP,
Enc = SecurityAlgorithms.Aes128CbcHmacSha256,
TestId = "ValidTest"
}
diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/MultiThreadingTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/MultiThreadingTests.cs
index f1b5d636b6..6352fc6fe4 100644
--- a/test/Microsoft.IdentityModel.Tokens.Tests/MultiThreadingTests.cs
+++ b/test/Microsoft.IdentityModel.Tokens.Tests/MultiThreadingTests.cs
@@ -121,7 +121,7 @@ public static TheoryData MultiThreadingCreateAndVerify
{
Claims = Default.PayloadDictionary,
SigningCredentials = new SigningCredentials(KeyingMaterial.RsaSecurityKey_2048, SecurityAlgorithms.RsaSha256, SecurityAlgorithms.Sha256),
- EncryptingCredentials = new EncryptingCredentials(KeyingMaterial.RsaSecurityKey_2048, SecurityAlgorithms.RsaOaepKeyWrap, SecurityAlgorithms.Aes128CbcHmacSha256)
+ EncryptingCredentials = new EncryptingCredentials(KeyingMaterial.RsaSecurityKey_2048, SecurityAlgorithms.RsaOAEP, SecurityAlgorithms.Aes128CbcHmacSha256)
};
var tokenValidationParametersEncryptedRsaKW = new TokenValidationParameters
@@ -174,7 +174,7 @@ public static TheoryData MultiThreadingCreateAndVerify
{
Claims = Default.PayloadDictionary,
SigningCredentials = new SigningCredentials(KeyingMaterial.RsaSecurityKeyCng_2048, SecurityAlgorithms.RsaSha256, SecurityAlgorithms.Sha256),
- EncryptingCredentials = new EncryptingCredentials(KeyingMaterial.RsaSecurityKeyCng_2048, SecurityAlgorithms.RsaOaepKeyWrap, SecurityAlgorithms.Aes128CbcHmacSha256)
+ EncryptingCredentials = new EncryptingCredentials(KeyingMaterial.RsaSecurityKeyCng_2048, SecurityAlgorithms.RsaOAEP, SecurityAlgorithms.Aes128CbcHmacSha256)
};
var tokenValidationParametersEncryptedRsaKWCng = new TokenValidationParameters
diff --git a/test/Microsoft.IdentityModel.Tokens.Tests/X509EncryptingCredentialsTests.cs b/test/Microsoft.IdentityModel.Tokens.Tests/X509EncryptingCredentialsTests.cs
index 6590737fca..2dee4d2e62 100644
--- a/test/Microsoft.IdentityModel.Tokens.Tests/X509EncryptingCredentialsTests.cs
+++ b/test/Microsoft.IdentityModel.Tokens.Tests/X509EncryptingCredentialsTests.cs
@@ -42,7 +42,7 @@ public static TheoryData ConstructorsTheory
new X509EncryptingCredentialsTheoryData
{
Certificate = null,
- Alg = SecurityAlgorithms.RsaOaepKeyWrap,
+ Alg = SecurityAlgorithms.RsaOAEP,
Enc = SecurityAlgorithms.Aes128CbcHmacSha256,
ExpectedException = ExpectedException.ArgumentNullException("IDX10000: The parameter 'certificate'"),
TestId = "NullCertificate"
@@ -58,7 +58,7 @@ public static TheoryData ConstructorsTheory
new X509EncryptingCredentialsTheoryData
{
Certificate = Default.Certificate,
- Alg = SecurityAlgorithms.RsaOaepKeyWrap,
+ Alg = SecurityAlgorithms.RsaOAEP,
Enc = String.Empty,
ExpectedException = ExpectedException.ArgumentNullException("IDX10000: The parameter 'enc'"),
TestId = "EmptyEncString"
@@ -74,7 +74,7 @@ public static TheoryData ConstructorsTheory
new X509EncryptingCredentialsTheoryData
{
Certificate = Default.Certificate,
- Alg = SecurityAlgorithms.RsaOaepKeyWrap,
+ Alg = SecurityAlgorithms.RsaOAEP,
Enc = null,
ExpectedException = ExpectedException.ArgumentNullException("IDX10000: The parameter 'enc'"),
TestId = "NullEncString"
@@ -82,7 +82,7 @@ public static TheoryData ConstructorsTheory
new X509EncryptingCredentialsTheoryData
{
Certificate = Default.Certificate,
- Alg = SecurityAlgorithms.RsaOaepKeyWrap,
+ Alg = SecurityAlgorithms.RsaOAEP,
Enc = SecurityAlgorithms.Aes128CbcHmacSha256,
TestId = "ValidTest"
}
diff --git a/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTests.WithContextSwitches.cs b/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTests.WithContextSwitches.cs
deleted file mode 100644
index 7e87575e11..0000000000
--- a/test/System.IdentityModel.Tokens.Jwt.Tests/JwtSecurityTokenHandlerTests.WithContextSwitches.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-
-using Microsoft.IdentityModel.JsonWebTokens;
-using Microsoft.IdentityModel.TestUtils;
-using Microsoft.IdentityModel.Tokens;
-using Xunit;
-
-namespace System.IdentityModel.Tokens.Jwt.Tests
-{
- [CollectionDefinition("JwtSecurityTokenHandlerTestsWithContextSwitches", DisableParallelization = true)]
- public class JwtSecurityTokenHandlerTestsWithContextSwitches
- {
- [Theory]
- [InlineData(SecurityAlgorithms.RsaOAEP, true)]
- [InlineData(SecurityAlgorithms.RsaOaepKeyWrap, false)]
- public void JwtSecurityTokenHandler_CreateToken_AddShortFormMappingForRsaOAEP(string algorithm, bool useShortNameForRsaOaepKey)
- {
- AppContext.SetSwitch(X509EncryptingCredentials._useShortNameForRsaOaepKey, useShortNameForRsaOaepKey);
- var encryptingCredentials = new X509EncryptingCredentials(Default.Certificate);
- JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
-
- JwtSecurityToken token = CreateJwtSecurityToken(tokenHandler, encryptingCredentials);
-
- Assert.Equal(token.Header.Alg, algorithm);
-
- AppContext.SetSwitch(X509EncryptingCredentials._useShortNameForRsaOaepKey, false);
- }
-
- [Theory]
- [InlineData(SecurityAlgorithms.RsaOAEP, true)]
- [InlineData(SecurityAlgorithms.RsaOaepKeyWrap, false)]
- public void JsonWebTokenHandler_CreateToken_AddShortFormMappingForRsaOAEP(string algorithm, bool useShortNameForRsaOaepKey)
- {
- AppContext.SetSwitch(X509EncryptingCredentials._useShortNameForRsaOaepKey, useShortNameForRsaOaepKey);
- var encryptingCredentials = new X509EncryptingCredentials(Default.Certificate);
- JsonWebTokenHandler tokenHandler = new JsonWebTokenHandler();
-
- JsonWebToken jsonToken = new JsonWebToken(CreateJwtSecurityTokenAsString(tokenHandler, encryptingCredentials));
-
- Assert.Equal(jsonToken.Alg, algorithm);
-
- AppContext.SetSwitch(X509EncryptingCredentials._useShortNameForRsaOaepKey, false);
- }
-
- private JwtSecurityToken CreateJwtSecurityToken(JwtSecurityTokenHandler tokenHandler, X509EncryptingCredentials encryptingCredentials)
- {
- return tokenHandler.CreateJwtSecurityToken(CreateTokenDescriptor(encryptingCredentials));
- }
-
- private string CreateJwtSecurityTokenAsString(JsonWebTokenHandler tokenHandler, X509EncryptingCredentials encryptingCredentials)
- {
- return tokenHandler.CreateToken(CreateTokenDescriptor(encryptingCredentials));
- }
-
- private SecurityTokenDescriptor CreateTokenDescriptor(X509EncryptingCredentials encryptingCredentials)
- {
- return new SecurityTokenDescriptor
- {
- Issuer = Default.Issuer,
- SigningCredentials = Default.AsymmetricSigningCredentials,
- EncryptingCredentials = encryptingCredentials,
- };
- }
- }
-}
From caf123fb476d29f61ef79ee58d6583e0a155bbd6 Mon Sep 17 00:00:00 2001
From: sruthikeerthi <73967733+sruke@users.noreply.github.com>
Date: Tue, 18 Jun 2024 23:08:42 -0700
Subject: [PATCH 3/5] Revert PR2597 to reduce allocations (#2649)
Co-authored-by: Sruthi Keerthi Rangavajhula (from Dev Box)
---
.../AadIssuerValidator/AadIssuerValidator.cs | 24 +++++------------
.../AadTokenValidationParametersExtension.cs | 27 ++++++++-----------
.../AadIssuerValidatorTests.cs | 24 -----------------
.../AadSigningKeyIssuerValidatorTests.cs | 15 -----------
4 files changed, 17 insertions(+), 73 deletions(-)
delete mode 100644 test/Microsoft.IdentityModel.Validators.Tests/AadIssuerValidatorTests.cs
diff --git a/src/Microsoft.IdentityModel.Validators/AadIssuerValidator/AadIssuerValidator.cs b/src/Microsoft.IdentityModel.Validators/AadIssuerValidator/AadIssuerValidator.cs
index 445671d134..323718cc84 100644
--- a/src/Microsoft.IdentityModel.Validators/AadIssuerValidator/AadIssuerValidator.cs
+++ b/src/Microsoft.IdentityModel.Validators/AadIssuerValidator/AadIssuerValidator.cs
@@ -13,6 +13,7 @@
using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens;
+using static Microsoft.IdentityModel.Validators.AadIssuerValidator;
namespace Microsoft.IdentityModel.Validators
{
@@ -382,31 +383,18 @@ private ConfigurationManager CreateConfigManager(
}
}
- internal static bool IsValidIssuer(string validIssuerTemplate, string tenantId, string actualIssuer)
+ private static bool IsValidIssuer(string validIssuerTemplate, string tenantId, string actualIssuer)
{
- if (string.IsNullOrEmpty(validIssuerTemplate) || string.IsNullOrEmpty(actualIssuer) || string.IsNullOrEmpty(tenantId))
+ if (string.IsNullOrEmpty(validIssuerTemplate))
return false;
- ReadOnlySpan validIssuerTemplateSpan = validIssuerTemplate.AsSpan();
- ReadOnlySpan actualIssuerSpan = actualIssuer.AsSpan();
- int indexOfTenantIdTemplate = validIssuerTemplate.IndexOf(TenantIdTemplate, StringComparison.Ordinal);
-
- if (indexOfTenantIdTemplate >= 0 && actualIssuer.Length > indexOfTenantIdTemplate)
+ if (validIssuerTemplate.Contains(TenantIdTemplate))
{
- // ensure the first part of the validIssuerTemplate matches the first part of actualIssuer
- if (!validIssuerTemplateSpan.Slice(0, indexOfTenantIdTemplate).SequenceEqual(actualIssuerSpan.Slice(0, indexOfTenantIdTemplate)))
- return false;
-
- // ensure that actualIssuer contains the tenantId from indexOfTenantIdTemplate for the length of tenantId.Length
- if (!actualIssuerSpan.Slice(indexOfTenantIdTemplate, tenantId.Length).SequenceEqual(tenantId.AsSpan()))
- return false;
-
- // ensure the second halves are equal
- return validIssuerTemplateSpan.Slice(indexOfTenantIdTemplate + TenantIdTemplate.Length).SequenceEqual(actualIssuerSpan.Slice(indexOfTenantIdTemplate + tenantId.Length));
+ return validIssuerTemplate.Replace(TenantIdTemplate, tenantId) == actualIssuer;
}
else
{
- return validIssuerTemplateSpan.SequenceEqual(actualIssuerSpan);
+ return validIssuerTemplate == actualIssuer;
}
}
diff --git a/src/Microsoft.IdentityModel.Validators/AadTokenValidationParametersExtension.cs b/src/Microsoft.IdentityModel.Validators/AadTokenValidationParametersExtension.cs
index 5335284168..d745bf124c 100644
--- a/src/Microsoft.IdentityModel.Validators/AadTokenValidationParametersExtension.cs
+++ b/src/Microsoft.IdentityModel.Validators/AadTokenValidationParametersExtension.cs
@@ -76,36 +76,31 @@ internal static bool ValidateIssuerSigningKey(SecurityKey securityKey, SecurityT
#if NET6_0_OR_GREATER
if (!string.IsNullOrEmpty(tokenIssuer) && !tokenIssuer.Contains(tenantIdFromToken, StringComparison.Ordinal))
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidIssuerException(LogHelper.FormatInvariant(LogMessages.IDX40004, LogHelper.MarkAsNonPII(tokenIssuer), LogHelper.MarkAsNonPII(tenantIdFromToken))));
+
+ // creating an effectiveSigningKeyIssuer is required as signingKeyIssuer might contain {tenantid}
+ var effectiveSigningKeyIssuer = signingKeyIssuer.Replace(AadIssuerValidator.TenantIdTemplate, tenantIdFromToken, StringComparison.Ordinal);
+ var v2TokenIssuer = openIdConnectConfiguration.Issuer?.Replace(AadIssuerValidator.TenantIdTemplate, tenantIdFromToken, StringComparison.Ordinal);
#else
if (!string.IsNullOrEmpty(tokenIssuer) && !tokenIssuer.Contains(tenantIdFromToken))
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidIssuerException(LogHelper.FormatInvariant(LogMessages.IDX40004, LogHelper.MarkAsNonPII(tokenIssuer), LogHelper.MarkAsNonPII(tenantIdFromToken))));
+
+ // creating an effectiveSigningKeyIssuer is required as signingKeyIssuer might contain {tenantid}
+ var effectiveSigningKeyIssuer = signingKeyIssuer.Replace(AadIssuerValidator.TenantIdTemplate, tenantIdFromToken);
+ var v2TokenIssuer = openIdConnectConfiguration.Issuer?.Replace(AadIssuerValidator.TenantIdTemplate, tenantIdFromToken);
#endif
- // comparing effectiveSigningKeyIssuer with v2TokenIssuer is required because of the following scenario:
+
+ // comparing effectiveSigningKeyIssuer with v2TokenIssuer is required as well because of the following scenario:
// 1. service trusts /common/v2.0 endpoint
// 2. service receieves a v1 token that has issuer like sts.windows.net
// 3. signing key issuers will never match sts.windows.net as v1 endpoint doesn't have issuers attached to keys
// v2TokenIssuer is the representation of Token.Issuer (if it was a v2 issuer)
- if (!AadIssuerValidator.IsValidIssuer(signingKeyIssuer, tenantIdFromToken, tokenIssuer)
- && !AadIssuerValidator.IsValidIssuer(signingKeyIssuer, tenantIdFromToken, openIdConnectConfiguration.Issuer))
- {
- int templateStartIndex = signingKeyIssuer.IndexOf(AadIssuerValidator.TenantIdTemplate, StringComparison.Ordinal);
- string effectiveSigningKeyIssuer = templateStartIndex > -1 ? CreateIssuer(signingKeyIssuer, AadIssuerValidator.TenantIdTemplate, tenantIdFromToken, templateStartIndex) : signingKeyIssuer;
+ if (effectiveSigningKeyIssuer != tokenIssuer && effectiveSigningKeyIssuer != v2TokenIssuer)
throw LogHelper.LogExceptionMessage(new SecurityTokenInvalidIssuerException(LogHelper.FormatInvariant(LogMessages.IDX40005, LogHelper.MarkAsNonPII(tokenIssuer), LogHelper.MarkAsNonPII(effectiveSigningKeyIssuer))));
- }
}
return true;
}
- internal static string CreateIssuer(string issuer, string tenantIdTemplate, string tenantId, int templateStartIndex)
- {
-#if NET6_0_OR_GREATER
- return string.Concat(issuer.AsSpan(0, templateStartIndex), tenantId, issuer.AsSpan(templateStartIndex + tenantIdTemplate.Length, issuer.Length - tenantIdTemplate.Length - templateStartIndex));
-#else
- return string.Concat(issuer.Substring(0, templateStartIndex), tenantId, issuer.Substring(templateStartIndex + tenantIdTemplate.Length));
-#endif
- }
-
///
/// Validates the issuer signing key certificate.
///
diff --git a/test/Microsoft.IdentityModel.Validators.Tests/AadIssuerValidatorTests.cs b/test/Microsoft.IdentityModel.Validators.Tests/AadIssuerValidatorTests.cs
deleted file mode 100644
index 4e05268f1f..0000000000
--- a/test/Microsoft.IdentityModel.Validators.Tests/AadIssuerValidatorTests.cs
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
-// Licensed under the MIT License.
-using Xunit;
-
-namespace Microsoft.IdentityModel.Validators.Tests
-{
- public class AadIssuerValidatorTests
- {
- [Theory]
- [InlineData(ValidatorConstants.AadInstance + AadIssuerValidator.TenantIdTemplate, ValidatorConstants.AadInstance + ValidatorConstants.TenantIdAsGuid, true)]
- [InlineData(ValidatorConstants.AadInstancePPE + AadIssuerValidator.TenantIdTemplate, ValidatorConstants.AadInstance + ValidatorConstants.TenantIdAsGuid, false)]
- [InlineData(ValidatorConstants.AadInstance + AadIssuerValidator.TenantIdTemplate, ValidatorConstants.AadInstance + ValidatorConstants.B2CTenantAsGuid, false)]
- [InlineData("", ValidatorConstants.AadInstance + ValidatorConstants.TenantIdAsGuid, false)]
- [InlineData(ValidatorConstants.AadInstance + AadIssuerValidator.TenantIdTemplate, "", false)]
- public static void IsValidIssuer_CanValidateTemplatedIssuers(string templatedIssuer, string issuer, bool expectedResult)
- {
- // act
- var result = AadIssuerValidator.IsValidIssuer(templatedIssuer, ValidatorConstants.TenantIdAsGuid, issuer);
-
- // assert
- Assert.Equal(expectedResult, result);
- }
- }
-}
diff --git a/test/Microsoft.IdentityModel.Validators.Tests/AadSigningKeyIssuerValidatorTests.cs b/test/Microsoft.IdentityModel.Validators.Tests/AadSigningKeyIssuerValidatorTests.cs
index b979f7c49e..e768a2372f 100644
--- a/test/Microsoft.IdentityModel.Validators.Tests/AadSigningKeyIssuerValidatorTests.cs
+++ b/test/Microsoft.IdentityModel.Validators.Tests/AadSigningKeyIssuerValidatorTests.cs
@@ -325,21 +325,6 @@ public static TheoryData ValidateIssuerSigningKey
}
}
- [Fact]
- public static void CreateIssuer_ReturnsExpectedIssuer()
- {
- // arrange
- var issuerTemplate = "{tenantId}";
- var issuer = ValidatorConstants.AadInstance + issuerTemplate;
- int templateStartIndex = issuer.IndexOf(issuerTemplate);
-
- // act
- var result = AadTokenValidationParametersExtension.CreateIssuer(issuer, issuerTemplate, ValidatorConstants.TenantIdAsGuid, templateStartIndex);
-
- // assert
- Assert.Equal(ValidatorConstants.AadInstance + ValidatorConstants.TenantIdAsGuid, result);
- }
-
private static OpenIdConnectConfiguration GetConfigurationMock()
{
var config = new OpenIdConnectConfiguration();
From 0183521b0f127a214aa28cfb8385acfef8c4aa22 Mon Sep 17 00:00:00 2001
From: joegoldman2 <147369450+joegoldman2@users.noreply.github.com>
Date: Wed, 19 Jun 2024 15:02:46 +0000
Subject: [PATCH 4/5] Add additional metadata parameters to
OpenIdConnectConfiguration (#2646)
Co-authored-by: joegoldman2 <147369450+joegoldman@users.noreply.github.com>
---
.../OpenIdConnectConfiguration.cs | 72 +++++++++++++++++++
.../OpenIdConnectConfigurationSerializer.cs | 40 +++++++++++
.../OpenIdProviderMetadataNames.cs | 8 +++
.../OpenIdConfigData.cs | 8 +++
.../OpenIdConnectConfigurationTests.cs | 15 +++-
.../OpenIdConnectMetadata.json | 4 ++
6 files changed, 145 insertions(+), 2 deletions(-)
diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs
index 36fb436a61..c513056b7d 100644
--- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs
+++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Configuration/OpenIdConnectConfiguration.cs
@@ -23,6 +23,9 @@ public class OpenIdConnectConfiguration : BaseConfiguration
// these are used to lazy create
private Dictionary _additionalData;
private ICollection _acrValuesSupported;
+ private ICollection _authorizationEncryptionAlgValuesSupported;
+ private ICollection _authorizationEncryptionEncValuesSupported;
+ private ICollection _authorizationSigningAlgValuesSupported;
private ICollection _backchannelAuthenticationRequestSigningAlgValuesSupported;
private ICollection _backchannelTokenDeliveryModesSupported;
private ICollection _claimsSupported;
@@ -146,6 +149,24 @@ public OpenIdConnectConfiguration(string json)
#endif
public string AuthorizationEndpoint { get; set; }
+ ///
+ /// Gets the collection of 'authorization_encryption_alg_values_supported'
+ ///
+ [JsonPropertyName(OpenIdProviderMetadataNames.AuthorizationEncryptionAlgValuesSupported)]
+ public ICollection AuthorizationEncryptionAlgValuesSupported =>
+ _authorizationEncryptionAlgValuesSupported ??
+ Interlocked.CompareExchange(ref _authorizationEncryptionAlgValuesSupported, new Collection(), null) ??
+ _authorizationEncryptionAlgValuesSupported;
+
+ ///
+ /// Gets the collection of 'authorization_encryption_enc_values_supported'
+ ///
+ [JsonPropertyName(OpenIdProviderMetadataNames.AuthorizationEncryptionEncValuesSupported)]
+ public ICollection AuthorizationEncryptionEncValuesSupported =>
+ _authorizationEncryptionEncValuesSupported ??
+ Interlocked.CompareExchange(ref _authorizationEncryptionEncValuesSupported, new Collection(), null) ??
+ _authorizationEncryptionEncValuesSupported;
+
///
/// Gets or sets the 'authorization_response_iss_parameter_supported'
///
@@ -155,6 +176,15 @@ public OpenIdConnectConfiguration(string json)
#endif
public bool AuthorizationResponseIssParameterSupported { get; set; }
+ ///
+ /// Gets the collection of 'authorization_signing_alg_values_supported'
+ ///
+ [JsonPropertyName(OpenIdProviderMetadataNames.AuthorizationSigningAlgValuesSupported)]
+ public ICollection AuthorizationSigningAlgValuesSupported =>
+ _authorizationSigningAlgValuesSupported ??
+ Interlocked.CompareExchange(ref _authorizationSigningAlgValuesSupported, new Collection(), null) ??
+ _authorizationSigningAlgValuesSupported;
+
///
/// Gets or sets the 'backchannel_authentication_endpoint'.
///
@@ -622,6 +652,15 @@ public OpenIdConnectConfiguration(string json)
Interlocked.CompareExchange(ref _tokenEndpointAuthSigningAlgValuesSupported, new Collection(), null) ??
_tokenEndpointAuthSigningAlgValuesSupported;
+ ///
+ /// Gets or sets the 'tls_client_certificate_bound_access_tokens'
+ ///
+ [JsonPropertyName(OpenIdProviderMetadataNames.TlsClientCertificateBoundAccessTokens)]
+#if NET6_0_OR_GREATER
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
+#endif
+ public bool TlsClientCertificateBoundAccessTokens { get; set; }
+
///
/// Gets the collection of 'ui_locales_supported'
///
@@ -681,6 +720,39 @@ public bool ShouldSerializeAcrValuesSupported()
return AcrValuesSupported.Count > 0;
}
+ ///
+ /// Gets a bool that determines if the 'authorization_encryption_alg_values_supported' (AuthorizationEncryptionAlgValuesSupported) property should be serialized.
+ /// This is used by Json.NET in order to conditionally serialize properties.
+ ///
+ /// true if 'authorization_encryption_alg_values_supported' (AuthorizationEncryptionAlgValuesSupported) is not empty; otherwise, false.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool ShouldSerializeAuthorizationEncryptionAlgValuesSupported()
+ {
+ return AuthorizationEncryptionAlgValuesSupported.Count > 0;
+ }
+
+ ///
+ /// Gets a bool that determines if the 'authorization_encryption_enc_values_supported' (AuthorizationEncryptionEncValuesSupported) property should be serialized.
+ /// This is used by Json.NET in order to conditionally serialize properties.
+ ///
+ /// true if 'authorization_encryption_enc_values_supported' (AuthorizationEncryptionEncValuesSupported) is not empty; otherwise, false.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool ShouldSerializeAuthorizationEncryptionEncValuesSupported()
+ {
+ return AuthorizationEncryptionEncValuesSupported.Count > 0;
+ }
+
+ ///
+ /// Gets a bool that determines if the 'authorization_signing_alg_values_supported' (AuthorizationSigningAlgValuesSupported) property should be serialized.
+ /// This is used by Json.NET in order to conditionally serialize properties.
+ ///
+ /// true if 'authorization_signing_alg_values_supported' (AuthorizationSigningAlgValuesSupported) is not empty; otherwise, false.
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool ShouldSerializeAuthorizationSigningAlgValuesSupported()
+ {
+ return AuthorizationSigningAlgValuesSupported.Count > 0;
+ }
+
///
/// Gets a bool that determines if the 'backchannel_token_delivery_modes_supported' (BackchannelTokenDeliveryModesSupported) property should be serialized.
/// This is used by Json.NET in order to conditionally serialize properties.
diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs
index 9e99a0899d..cffe63744f 100644
--- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs
+++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/Json/OpenIdConnectConfigurationSerializer.cs
@@ -39,7 +39,10 @@ public static readonly
{
"ACR_VALUES_SUPPORTED",
"AUTHORIZATION_ENDPOINT",
+ "AUTHORIZATION_ENCRYPTION_ALG_VALUES_SUPPORTED",
+ "AUTHORIZATION_ENCRYPTION_ENC_VALUES_SUPPORTED",
"AUTHORIZATION_RESPONSE_ISS_PARAMETER_SUPPORTED",
+ "AUTHORIZATION_SIGNING_ALG_VALUES_SUPPORTED",
"BACKCHANNEL_AUTHENTICATION_ENDPOINT",
"BACKCHANNEL_AUTHENTICATION_REQUEST_SIGNING_ALG_VALUES_SUPPORTED",
"BACKCHANNEL_TOKEN_DELIVERY_MODES_SUPPORTED",
@@ -91,6 +94,7 @@ public static readonly
"TOKEN_ENDPOINT",
"TOKEN_ENDPOINT_AUTH_METHODS_SUPPORTED",
"TOKEN_ENDPOINT_AUTH_SIGNING_ALG_VALUES_SUPPORTED",
+ "TLS_CLIENT_CERTIFICATE_BOUND_ACCESS_TOKENS",
"UI_LOCALES_SUPPORTED",
"USERINFO_ENDPOINT",
"USERINFO_ENCRYPTION_ALG_VALUES_SUPPORTED",
@@ -162,9 +166,18 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC
else if (reader.ValueTextEquals(Utf8Bytes.AuthorizationEndpoint))
config.AuthorizationEndpoint = JsonPrimitives.ReadString(ref reader, MetadataName.AuthorizationEndpoint, ClassName, true);
+ else if (reader.ValueTextEquals(Utf8Bytes.AuthorizationEncryptionAlgValuesSupported))
+ JsonPrimitives.ReadStrings(ref reader, config.AuthorizationEncryptionAlgValuesSupported, MetadataName.AuthorizationEncryptionAlgValuesSupported, ClassName, true);
+
+ else if (reader.ValueTextEquals(Utf8Bytes.AuthorizationEncryptionEncValuesSupported))
+ JsonPrimitives.ReadStrings(ref reader, config.AuthorizationEncryptionEncValuesSupported, MetadataName.AuthorizationEncryptionEncValuesSupported, ClassName, true);
+
else if (reader.ValueTextEquals(Utf8Bytes.AuthorizationResponseIssParameterSupported))
config.AuthorizationResponseIssParameterSupported = JsonPrimitives.ReadBoolean(ref reader, MetadataName.AuthorizationResponseIssParameterSupported, ClassName, true);
+ else if (reader.ValueTextEquals(Utf8Bytes.AuthorizationSigningAlgValuesSupported))
+ JsonPrimitives.ReadStrings(ref reader, config.AuthorizationSigningAlgValuesSupported, MetadataName.AuthorizationSigningAlgValuesSupported, ClassName, true);
+
else if (reader.ValueTextEquals(Utf8Bytes.BackchannelAuthenticationEndpoint))
config.BackchannelAuthenticationEndpoint = JsonPrimitives.ReadString(ref reader, MetadataName.BackchannelAuthenticationEndpoint, ClassName, true);
@@ -328,6 +341,9 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC
else if (reader.ValueTextEquals(Utf8Bytes.TokenEndpointAuthSigningAlgValuesSupported))
JsonPrimitives.ReadStrings(ref reader, config.TokenEndpointAuthSigningAlgValuesSupported, MetadataName.TokenEndpointAuthSigningAlgValuesSupported, ClassName, true);
+ else if (reader.ValueTextEquals(Utf8Bytes.TlsClientCertificateBoundAccessTokens))
+ config.TlsClientCertificateBoundAccessTokens = JsonPrimitives.ReadBoolean(ref reader, MetadataName.TlsClientCertificateBoundAccessTokens, ClassName, true);
+
else if (reader.ValueTextEquals(Utf8Bytes.UILocalesSupported))
JsonPrimitives.ReadStrings(ref reader, config.UILocalesSupported, MetadataName.UILocalesSupported, ClassName, true);
@@ -366,9 +382,18 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC
else if (propertyName.Equals(MetadataName.AuthorizationEndpoint, StringComparison.OrdinalIgnoreCase))
config.AuthorizationEndpoint = JsonPrimitives.ReadString(ref reader, propertyName, ClassName);
+ else if (propertyName.Equals(MetadataName.AuthorizationEncryptionAlgValuesSupported, StringComparison.OrdinalIgnoreCase))
+ JsonPrimitives.ReadStrings(ref reader, config.AuthorizationEncryptionAlgValuesSupported, propertyName, ClassName);
+
+ else if (propertyName.Equals(MetadataName.AuthorizationEncryptionEncValuesSupported, StringComparison.OrdinalIgnoreCase))
+ JsonPrimitives.ReadStrings(ref reader, config.AuthorizationEncryptionEncValuesSupported, propertyName, ClassName);
+
else if (propertyName.Equals(MetadataName.AuthorizationResponseIssParameterSupported, StringComparison.OrdinalIgnoreCase))
config.AuthorizationResponseIssParameterSupported = JsonPrimitives.ReadBoolean(ref reader, propertyName, ClassName);
+ else if (propertyName.Equals(MetadataName.AuthorizationSigningAlgValuesSupported, StringComparison.OrdinalIgnoreCase))
+ JsonPrimitives.ReadStrings(ref reader, config.AuthorizationSigningAlgValuesSupported, propertyName, ClassName);
+
else if (propertyName.Equals(MetadataName.BackchannelAuthenticationEndpoint, StringComparison.OrdinalIgnoreCase))
config.BackchannelAuthenticationEndpoint = JsonPrimitives.ReadString(ref reader, propertyName, ClassName);
@@ -533,6 +558,9 @@ public static OpenIdConnectConfiguration Read(ref Utf8JsonReader reader, OpenIdC
else if (propertyName.Equals(MetadataName.TokenEndpointAuthSigningAlgValuesSupported, StringComparison.OrdinalIgnoreCase))
JsonPrimitives.ReadStrings(ref reader, config.TokenEndpointAuthSigningAlgValuesSupported, propertyName, ClassName);
+ else if (propertyName.Equals(MetadataName.TlsClientCertificateBoundAccessTokens, StringComparison.OrdinalIgnoreCase))
+ config.TlsClientCertificateBoundAccessTokens = JsonPrimitives.ReadBoolean(ref reader, propertyName, ClassName);
+
else if (propertyName.Equals(MetadataName.UILocalesSupported, StringComparison.OrdinalIgnoreCase))
JsonPrimitives.ReadStrings(ref reader, config.UILocalesSupported, propertyName, ClassName);
@@ -592,9 +620,18 @@ public static void Write(ref Utf8JsonWriter writer, OpenIdConnectConfiguration c
if (!string.IsNullOrEmpty(config.AuthorizationEndpoint))
writer.WriteString(Utf8Bytes.AuthorizationEndpoint, config.AuthorizationEndpoint);
+ if (config.AuthorizationEncryptionAlgValuesSupported.Count > 0)
+ JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.AuthorizationEncryptionAlgValuesSupported, config.AuthorizationEncryptionAlgValuesSupported);
+
+ if (config.AuthorizationEncryptionEncValuesSupported.Count > 0)
+ JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.AuthorizationEncryptionEncValuesSupported, config.AuthorizationEncryptionEncValuesSupported);
+
if (config.AuthorizationResponseIssParameterSupported)
writer.WriteBoolean(Utf8Bytes.AuthorizationResponseIssParameterSupported, config.AuthorizationResponseIssParameterSupported);
+ if (config.AuthorizationSigningAlgValuesSupported.Count > 0)
+ JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.AuthorizationSigningAlgValuesSupported, config.AuthorizationSigningAlgValuesSupported);
+
if (!string.IsNullOrEmpty(config.BackchannelAuthenticationEndpoint))
writer.WriteString(Utf8Bytes.BackchannelAuthenticationEndpoint, config.BackchannelAuthenticationEndpoint);
@@ -745,6 +782,9 @@ public static void Write(ref Utf8JsonWriter writer, OpenIdConnectConfiguration c
if (config.TokenEndpointAuthSigningAlgValuesSupported.Count > 0)
JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.TokenEndpointAuthSigningAlgValuesSupported, config.TokenEndpointAuthSigningAlgValuesSupported);
+ if (config.TlsClientCertificateBoundAccessTokens)
+ writer.WriteBoolean(Utf8Bytes.TlsClientCertificateBoundAccessTokens, config.TlsClientCertificateBoundAccessTokens);
+
if (config.UILocalesSupported.Count > 0)
JsonPrimitives.WriteStrings(ref writer, Utf8Bytes.UILocalesSupported, config.UILocalesSupported);
diff --git a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/OpenIdProviderMetadataNames.cs b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/OpenIdProviderMetadataNames.cs
index 62f15637c6..b5c802d3dd 100644
--- a/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/OpenIdProviderMetadataNames.cs
+++ b/src/Microsoft.IdentityModel.Protocols.OpenIdConnect/OpenIdProviderMetadataNames.cs
@@ -14,7 +14,10 @@ public static class OpenIdProviderMetadataNames
#pragma warning disable 1591
public const string AcrValuesSupported = "acr_values_supported";
public const string AuthorizationEndpoint = "authorization_endpoint";
+ public const string AuthorizationEncryptionAlgValuesSupported = "authorization_encryption_alg_values_supported";
+ public const string AuthorizationEncryptionEncValuesSupported = "authorization_encryption_enc_values_supported";
public const string AuthorizationResponseIssParameterSupported = "authorization_response_iss_parameter_supported";
+ public const string AuthorizationSigningAlgValuesSupported = "authorization_signing_alg_values_supported";
public const string BackchannelAuthenticationEndpoint = "backchannel_authentication_endpoint";
public const string BackchannelAuthenticationRequestSigningAlgValuesSupported = "backchannel_authentication_request_signing_alg_values_supported";
public const string BackchannelTokenDeliveryModesSupported = "backchannel_token_delivery_modes_supported";
@@ -68,6 +71,7 @@ public static class OpenIdProviderMetadataNames
public const string TokenEndpointAuthMethodsSupported = "token_endpoint_auth_methods_supported";
public const string TokenEndpointAuthSigningAlgValuesSupported = "token_endpoint_auth_signing_alg_values_supported";
public const string UILocalesSupported = "ui_locales_supported";
+ public const string TlsClientCertificateBoundAccessTokens = "tls_client_certificate_bound_access_tokens";
public const string UserInfoEndpoint = "userinfo_endpoint";
public const string UserInfoEncryptionAlgValuesSupported = "userinfo_encryption_alg_values_supported";
public const string UserInfoEncryptionEncValuesSupported = "userinfo_encryption_enc_values_supported";
@@ -84,7 +88,10 @@ internal static class OpenIdProviderMetadataUtf8Bytes
{
public static ReadOnlySpan AcrValuesSupported => "acr_values_supported"u8;
public static ReadOnlySpan AuthorizationEndpoint => "authorization_endpoint"u8;
+ public static ReadOnlySpan AuthorizationEncryptionAlgValuesSupported => "authorization_encryption_alg_values_supported"u8;
+ public static ReadOnlySpan AuthorizationEncryptionEncValuesSupported => "authorization_encryption_enc_values_supported"u8;
public static ReadOnlySpan AuthorizationResponseIssParameterSupported => "authorization_response_iss_parameter_supported"u8;
+ public static ReadOnlySpan AuthorizationSigningAlgValuesSupported => "authorization_signing_alg_values_supported"u8;
public static ReadOnlySpan BackchannelAuthenticationEndpoint => "backchannel_authentication_endpoint"u8;
public static ReadOnlySpan BackchannelAuthenticationRequestSigningAlgValuesSupported => "backchannel_authentication_request_signing_alg_values_supported"u8;
public static ReadOnlySpan BackchannelTokenDeliveryModesSupported => "backchannel_token_delivery_modes_supported"u8;
@@ -137,6 +144,7 @@ internal static class OpenIdProviderMetadataUtf8Bytes
public static ReadOnlySpan TokenEndpoint => "token_endpoint"u8;
public static ReadOnlySpan TokenEndpointAuthMethodsSupported => "token_endpoint_auth_methods_supported"u8;
public static ReadOnlySpan TokenEndpointAuthSigningAlgValuesSupported => "token_endpoint_auth_signing_alg_values_supported"u8;
+ public static ReadOnlySpan TlsClientCertificateBoundAccessTokens => "tls_client_certificate_bound_access_tokens"u8;
public static ReadOnlySpan UILocalesSupported => "ui_locales_supported"u8;
public static ReadOnlySpan UserInfoEndpoint => "userinfo_endpoint"u8;
public static ReadOnlySpan UserInfoEncryptionAlgValuesSupported => "userinfo_encryption_alg_values_supported"u8;
diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs
index 1f60d43365..75a62b1539 100644
--- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs
+++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConfigData.cs
@@ -68,7 +68,10 @@ public static OpenIdConnectConfiguration FullyPopulatedWithKeys
public static string JsonAllValues =
@"{ ""acr_values_supported"": [""acr_value1"", ""acr_value2"", ""acr_value3""],
""authorization_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/authorize"",
+ ""authorization_encryption_alg_values_supported"": [""A192KW"", ""A256KW""],
+ ""authorization_encryption_enc_values_supported"": [""A128CBC-HS256"", ""A256CBC-HS512""],
""authorization_response_iss_parameter_supported"": false,
+ ""authorization_signing_alg_values_supported"": [""ES384"", ""ES512""],
""backchannel_authentication_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/bc-authorize"",
""backchannel_authentication_request_signing_alg_values_supported"": [""ES384"", ""ES512""],
""backchannel_token_delivery_modes_supported"": [""poll"", ""ping""],
@@ -119,6 +122,7 @@ public static OpenIdConnectConfiguration FullyPopulatedWithKeys
""token_endpoint"": ""https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/token"",
""token_endpoint_auth_methods_supported"": [""client_secret_post"", ""private_key_jwt""],
""token_endpoint_auth_signing_alg_values_supported"": [""ES192"", ""ES256""],
+ ""tls_client_certificate_bound_access_tokens"": true,
""ui_locales_supported"": [""hak-CN"", ""en-us""],
""userinfo_endpoint"": ""https://login.microsoftonline.com/add29489-7269-41f4-8841-b63c95564420/openid/userinfo"",
""userinfo_encryption_alg_values_supported"": [""ECDH-ES+A128KW"", ""ECDH-ES+A192KW""],
@@ -610,7 +614,10 @@ private static OpenIdConnectConfiguration SetDefaultConfiguration(OpenIdConnectC
{
AddToCollection(config.AcrValuesSupported, "acr_value1", "acr_value2", "acr_value3");
config.AuthorizationEndpoint = "https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/authorize";
+ AddToCollection(config.AuthorizationEncryptionAlgValuesSupported, "A192KW", "A256KW");
+ AddToCollection(config.AuthorizationEncryptionEncValuesSupported, "A128CBC-HS256", "A256CBC-HS512");
config.AuthorizationResponseIssParameterSupported = false;
+ AddToCollection(config.AuthorizationSigningAlgValuesSupported, "ES384", "ES512");
config.BackchannelAuthenticationEndpoint = "https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/bc-authorize";
AddToCollection(config.BackchannelAuthenticationRequestSigningAlgValuesSupported, "ES384", "ES512");
AddToCollection(config.BackchannelTokenDeliveryModesSupported, "poll", "ping");
@@ -660,6 +667,7 @@ private static OpenIdConnectConfiguration SetDefaultConfiguration(OpenIdConnectC
config.TokenEndpoint = "https://login.windows.net/d062b2b0-9aca-4ff7-b32a-ba47231a4002/oauth2/token";
AddToCollection(config.TokenEndpointAuthMethodsSupported, "client_secret_post", "private_key_jwt");
AddToCollection(config.TokenEndpointAuthSigningAlgValuesSupported, "ES192", "ES256");
+ config.TlsClientCertificateBoundAccessTokens = true;
AddToCollection(config.UILocalesSupported, "hak-CN", "en-us");
config.UserInfoEndpoint = "https://login.microsoftonline.com/add29489-7269-41f4-8841-b63c95564420/openid/userinfo";
AddToCollection(config.UserInfoEndpointEncryptionAlgValuesSupported, "ECDH-ES+A128KW", "ECDH-ES+A192KW");
diff --git a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs
index 9ee0bb7cdb..c31a60b085 100644
--- a/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs
+++ b/test/Microsoft.IdentityModel.Protocols.OpenIdConnect.Tests/OpenIdConnectConfigurationTests.cs
@@ -75,6 +75,9 @@ public void Defaults()
{
OpenIdConnectConfiguration configuration = new OpenIdConnectConfiguration();
Assert.NotNull(configuration.AcrValuesSupported);
+ Assert.NotNull(configuration.AuthorizationEncryptionAlgValuesSupported);
+ Assert.NotNull(configuration.AuthorizationEncryptionEncValuesSupported);
+ Assert.NotNull(configuration.AuthorizationSigningAlgValuesSupported);
Assert.False(configuration.AuthorizationResponseIssParameterSupported);
Assert.NotNull(configuration.BackchannelAuthenticationRequestSigningAlgValuesSupported);
Assert.NotNull(configuration.BackchannelTokenDeliveryModesSupported);
@@ -110,6 +113,7 @@ public void Defaults()
Assert.NotNull(configuration.SubjectTypesSupported);
Assert.NotNull(configuration.TokenEndpointAuthMethodsSupported);
Assert.NotNull(configuration.TokenEndpointAuthSigningAlgValuesSupported);
+ Assert.False(configuration.TlsClientCertificateBoundAccessTokens);
Assert.NotNull(configuration.UILocalesSupported);
Assert.NotNull(configuration.UserInfoEndpointEncryptionAlgValuesSupported);
Assert.NotNull(configuration.UserInfoEndpointEncryptionEncValuesSupported);
@@ -141,8 +145,8 @@ public void GetSets()
OpenIdConnectConfiguration configuration = new OpenIdConnectConfiguration();
Type type = typeof(OpenIdConnectConfiguration);
PropertyInfo[] properties = type.GetProperties();
- if (properties.Length != 63)
- Assert.True(false, "Number of properties has changed from 63 to: " + properties.Length + ", adjust tests");
+ if (properties.Length != 67)
+ Assert.True(false, "Number of properties has changed from 67 to: " + properties.Length + ", adjust tests");
TestUtilities.CallAllPublicInstanceAndStaticPropertyGets(configuration, "OpenIdConnectConfiguration_GetSets");
@@ -152,7 +156,10 @@ public void GetSets()
PropertyNamesAndSetGetValue = new List>>
{
new KeyValuePair>("AuthorizationEndpoint", new List