Skip to content

Commit

Permalink
complete merge
Browse files Browse the repository at this point in the history
  • Loading branch information
Mallika Chennupaty committed Feb 10, 2025
2 parents 7d37e5c + 9bd5211 commit d8efbe7
Show file tree
Hide file tree
Showing 127 changed files with 913 additions and 295 deletions.
4 changes: 2 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
</PropertyGroup>

<PropertyGroup Label="Common dependency versions">
<MicrosoftIdentityModelVersion Condition="'$(MicrosoftIdentityModelVersion)' == ''">8.3.1</MicrosoftIdentityModelVersion>
<MicrosoftIdentityModelVersion Condition="'$(MicrosoftIdentityModelVersion)' == ''">8.4.0</MicrosoftIdentityModelVersion>
<MicrosoftIdentityClientVersion Condition="'$(MicrosoftIdentityClientVersion)' == ''">4.67.2</MicrosoftIdentityClientVersion>
<FxCopAnalyzersVersion>3.3.0</FxCopAnalyzersVersion>
<SystemTextEncodingsWebVersion>4.7.2</SystemTextEncodingsWebVersion>
Expand All @@ -96,7 +96,7 @@
<MicrosoftGraphVersion>4.36.0</MicrosoftGraphVersion>
<MicrosoftGraphBetaVersion>4.57.0-preview</MicrosoftGraphBetaVersion>
<MicrosoftExtensionsHttpVersion>3.1.3</MicrosoftExtensionsHttpVersion>
<MicrosoftIdentityAbstractionsVersion>8.1.0</MicrosoftIdentityAbstractionsVersion>
<MicrosoftIdentityAbstractionsVersion>8.1.1</MicrosoftIdentityAbstractionsVersion>
<!--CVE-2024-43485-->
<SystemTextJsonVersion>8.0.5</SystemTextJsonVersion>
<!--CVE-2023-29331-->
Expand Down
7 changes: 7 additions & 0 deletions Microsoft.Identity.Web.sln
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Identity.Web.UI",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Identity.Web.AotCompatibility.TestApp", "tests\Microsoft.Identity.Web.AotCompatibility.TestApp\Microsoft.Identity.Web.AotCompatibility.TestApp.csproj", "{BCE63265-6D36-423A-9C3D-BF8E448C7EA0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomSignedAssertionProviderTests", "tests\E2E Tests\CustomSignedAssertionProviderTests\CustomSignedAssertionProviderTests.csproj", "{A390650C-BCE1-4CB3-8C97-9EF9CFF5B7C5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -370,6 +372,10 @@ Global
{BCE63265-6D36-423A-9C3D-BF8E448C7EA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BCE63265-6D36-423A-9C3D-BF8E448C7EA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BCE63265-6D36-423A-9C3D-BF8E448C7EA0}.Release|Any CPU.Build.0 = Release|Any CPU
{A390650C-BCE1-4CB3-8C97-9EF9CFF5B7C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A390650C-BCE1-4CB3-8C97-9EF9CFF5B7C5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A390650C-BCE1-4CB3-8C97-9EF9CFF5B7C5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A390650C-BCE1-4CB3-8C97-9EF9CFF5B7C5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -442,6 +448,7 @@ Global
{4A63EA63-5679-4498-BB4C-30E09F268E00} = {E37CDBC1-18F6-4C06-A3EE-532C9106721F}
{C6CB0D5B-917A-4127-9984-7592C757BBDE} = {1DDE1AAC-5AE6-4725-94B6-A26C58D3423F}
{BCE63265-6D36-423A-9C3D-BF8E448C7EA0} = {B4E72F1C-603F-437C-AAA1-153A604CD34A}
{A390650C-BCE1-4CB3-8C97-9EF9CFF5B7C5} = {45B20A78-91F8-4DD2-B9AD-F12D3A93536C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {104367F1-CE75-4F40-B32F-F14853973187}
Expand Down
2 changes: 1 addition & 1 deletion benchmark/Benchmarks.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
Expand Down
5 changes: 3 additions & 2 deletions benchmark/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
<PropertyGroup>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
<TargetFrameworks>net8.0</TargetFrameworks>
<SignAssembly>True</SignAssembly>
<IsPackable>false</IsPackable>
<EnablePackageValidation>false</EnablePackageValidation>
<AssemblyOriginatorKeyFile>../build/MSAL.snk</AssemblyOriginatorKeyFile>
<SignAssembly>True</SignAssembly>
<DelaySign>True</DelaySign>
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)..\build\msal.snk</AssemblyOriginatorKeyFile>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
11 changes: 11 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
3.7.0
========
- Updated to Microsoft.Identity.Abstractions [8.1.0](https://github.com/AzureAD/microsoft-identity-abstractions-for-dotnet/releases/tag/8.1.0)
- Updated to Microsoft.IdentityModel.* [8.4.0](https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/releases/tag/8.4.0)

### New Feature
- IdentityWeb now provides extensibility to `DefaultCredentialsLoader` so that partner teams, or an SDK on top of IdWeb, can bring their own credential providers. See [#3220](https://github.com/AzureAD/microsoft-identity-web/issues/3220) for details.

## Bug fixes
- The merged options are now being passed to MSAL for the CCA ROPC scenario. See [#3207](https://github.com/AzureAD/microsoft-identity-web/issues/3207) for details.

3.6.2
========
- Updated to Microsoft.Identity.Abstractions [8.0.0](https://github.com/AzureAD/microsoft-identity-abstractions-for-dotnet/releases/tag/8.0.0)
Expand Down
15 changes: 10 additions & 5 deletions src/Microsoft.Identity.Web.Certificate/CertificateErrorMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,17 @@ internal static class CertificateErrorMessage
{
// Configuration IDW10100 = "IDW10100:"
public const string ClientSecretAndCertificateNull =
"IDW10104: Both client secret and client certificate cannot be null or whitespace, " +
"and only ONE must be included in the configuration of the web app when calling a web API. " +
"For instance, in the appsettings.json file. ";
public const string BothClientSecretAndCertificateProvided = "IDW10105: Both client secret and client certificate, " +
"cannot be included in the configuration of the web app when calling a web API. ";
"IDW10104: Both client secret and client certificate cannot be null or whitespace, " +
"and only ONE must be included in the configuration of the web app when calling a web API. " +
"For instance, in the appsettings.json file. ";
public const string BothClientSecretAndCertificateProvided =
"IDW10105: Both client secret and client certificate, cannot be included in the configuration of the web app when calling a web API. ";
public const string ClientCertificatesHaveExpiredOrCannotBeLoaded = "IDW10109: All client certificates passed to the configuration have expired or can't be loaded. ";
public const string CustomProviderNameAlreadyExists =
"IDW10111 The custom signed assertion provider '{0}' already exists, only the the first instance of ICustomSignedAssertionProvider with this name will be used.";
public const string CustomProviderNameNullOrEmpty = "IDW10112 The name of the custom signed assertion provider is null or empty.";
public const string CustomProviderNotFound = "IDW10113: The custom signed assertion provider with name '{0}' was not found. Was it registered in the service collection?";
public const string CustomProviderSourceLoaderNullOrEmpty = "IDW10114 The dictionary of SourceLoaders for custom signed assertion providers is null or empty.";

// Encoding IDW10600 = "IDW10600:"
public const string InvalidBase64UrlString = "IDW10601: Invalid Base64URL string. ";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ public DefaultCertificateLoader() : this(null)
{
}

/// <summary>
/// Constructor with custom signed assertion providers.
/// </summary>
/// <param name="customSignedAssertionProviders">List of providers of custom signed assertions</param>
/// <param name="logger">ILogger.</param>
public DefaultCertificateLoader(IEnumerable<ICustomSignedAssertionProvider> customSignedAssertionProviders, ILogger<DefaultCertificateLoader>? logger) : base(customSignedAssertionProviders, logger)
{
}

/// <summary>
/// This default is overridable at the level of the credential description (for the certificate from KeyVault).
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Identity.Abstractions;

namespace Microsoft.Identity.Web
{
public partial class DefaultCredentialsLoader
{
/// <summary>
/// Constructor for DefaultCredentialsLoader when using custom signed assertion provider source loaders.
/// </summary>
/// <param name="customSignedAssertionProviders">Set of custom signed assertion providers.</param>
/// <param name="logger">ILogger.</param>
public DefaultCredentialsLoader(IEnumerable<ICustomSignedAssertionProvider> customSignedAssertionProviders, ILogger<DefaultCredentialsLoader>? logger) : this(logger)
{
_ = Throws.IfNull(customSignedAssertionProviders);
var sourceLoaderDict = new Dictionary<string, ICustomSignedAssertionProvider>();

foreach (ICustomSignedAssertionProvider provider in customSignedAssertionProviders)
{
string providerName = provider.Name ?? provider.GetType().FullName!;
if (sourceLoaderDict.ContainsKey(providerName))
{
_logger.LogWarning(CertificateErrorMessage.CustomProviderNameAlreadyExists, providerName);
}
else
{
sourceLoaderDict.Add(providerName, provider);
}
}
CustomSignedAssertionCredentialSourceLoaders = sourceLoaderDict;
}

/// <summary>
/// Dictionary of custom signed assertion credential source loaders, by name (either ICustomSignedAssertionProvider.Name or the fully qualified type name).
/// The application can add more to process additional credential sources.
/// </summary>
protected IDictionary<string, ICustomSignedAssertionProvider>? CustomSignedAssertionCredentialSourceLoaders { get; }

private async Task ProcessCustomSignedAssertionAsync(CredentialDescription credentialDescription, CredentialSourceLoaderParameters? parameters)
{
if (CustomSignedAssertionCredentialSourceLoaders == null || CustomSignedAssertionCredentialSourceLoaders.Count == 0)
{
// No source loader(s)
_logger.LogError(CertificateErrorMessage.CustomProviderSourceLoaderNullOrEmpty);
}
else if (string.IsNullOrEmpty(credentialDescription.CustomSignedAssertionProviderName))
{
// No provider name
_logger.LogError(CertificateErrorMessage.CustomProviderNameNullOrEmpty);
}
else if (!CustomSignedAssertionCredentialSourceLoaders!.TryGetValue(credentialDescription.CustomSignedAssertionProviderName!, out ICustomSignedAssertionProvider? sourceLoader))
{
// No source loader for provider name
_logger.LogError(CertificateErrorMessage.CustomProviderNotFound, credentialDescription.CustomSignedAssertionProviderName);
}
else
{
// Load the credentials, if there is an error, it is coming from the user's custom extension and should be logged and propagated.
try
{
await sourceLoader.LoadIfNeededAsync(credentialDescription, parameters);
}
catch (Exception ex)
{
Logger.CustomSignedAssertionProviderLoadingFailure(_logger, credentialDescription, ex);
throw;
}
return;
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ namespace Microsoft.Identity.Web
// Log messages for DefaultCredentialsLoader
public partial class DefaultCredentialsLoader
{
internal const string nameMissing = "NameMissing";
internal static string CustomSignedAssertionProviderLoadingFailureMessage(string providerName, string sourceType, string skip)
{
return $"Failed to find custom signed assertion provider {providerName} from source {sourceType}. Will it be skipped in the future ? {skip}.";
}

/// <summary>
/// Logging infrastructure
/// </summary>
Expand All @@ -18,13 +24,25 @@ private static class Logger
private static readonly Action<ILogger, string, string, bool, Exception?> s_credentialLoadingFailure =
LoggerMessage.Define<string, string, bool>(
LogLevel.Information,
new EventId(
7,
nameof(CredentialLoadingFailure)),
"Failed to load credential {id} from source {sourceType}. Will it be skipped in the future ? {skip}.");
new EventId(7, nameof(CredentialLoadingFailure)),
"Failed to load credential {id} from source {sourceType}. Will it be skipped in the future ? {skip}."
);

public static void CredentialLoadingFailure(ILogger logger, CredentialDescription cd, Exception? ex)
=> s_credentialLoadingFailure(logger, cd.Id, cd.SourceType.ToString(), cd.Skip, ex);

private static readonly Action<ILogger, string, string, bool, Exception?> s_customSignedAssertionProviderLoadingFailure =
LoggerMessage.Define<string, string, bool>(
LogLevel.Information,
new EventId(8, nameof(CustomSignedAssertionProviderLoadingFailure)),
CustomSignedAssertionProviderLoadingFailureMessage("{name}", "{sourceType}", "{skip}")
);

public static void CustomSignedAssertionProviderLoadingFailure(
ILogger logger,
CredentialDescription cd,
Exception ex
) => s_customSignedAssertionProviderLoadingFailure(logger, cd.CustomSignedAssertionProviderName ?? nameMissing, cd.SourceType.ToString(), cd.Skip, ex);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ public async Task LoadCredentialsIfNeededAsync(CredentialDescription credentialD
{
if (credentialDescription.CachedValue == null)
{
if (CredentialSourceLoaders.TryGetValue(credentialDescription.SourceType, out ICredentialSourceLoader? loader))
if (credentialDescription.SourceType == CredentialSource.CustomSignedAssertion)
{
await ProcessCustomSignedAssertionAsync(credentialDescription, parameters);
}
else if (CredentialSourceLoaders.TryGetValue(credentialDescription.SourceType, out ICredentialSourceLoader? loader))
{
try
{
Expand Down
Loading

0 comments on commit d8efbe7

Please sign in to comment.