Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,34 @@ public ManagedIdentityApplicationBuilder WithClientCapabilities(IEnumerable<stri
return this;
}

/// <summary>
/// Sets Extra Query Parameters for the query string in the HTTP authentication request.
/// </summary>
/// <param name="extraQueryParameters">This parameter will be appended as is to the query string in the HTTP authentication request to the authority
/// as a string of segments of the form <c>key=value</c> separated by an ampersand character.
/// The parameter can be null.</param>
/// <returns>The builder to chain the .With methods.</returns>
/// <remarks>This API is experimental and it may change in future versions of the library without a major version increment</remarks>
[EditorBrowsable(EditorBrowsableState.Never)]
public ManagedIdentityApplicationBuilder WithExtraQueryParameters(IDictionary<string, string> extraQueryParameters)
{
ValidateUseOfExperimentalFeature();

if (Config.ExtraQueryParameters == null)
{
Config.ExtraQueryParameters = extraQueryParameters;
}
else
{
foreach (var kvp in extraQueryParameters)
{
Config.ExtraQueryParameters[kvp.Key] = kvp.Value; // This will overwrite if key exists, or add if new
}
}

return this;
}

/// <summary>
/// Builds an instance of <see cref="IManagedIdentityApplication"/>
/// from the parameters set in the <see cref="ManagedIdentityApplicationBuilder"/>.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ public virtual async Task<ManagedIdentityResponse> AuthenticateAsync(
_requestContext.Logger);
}

request.AddExtraQueryParams(
_requestContext.ServiceBundle.Config.ExtraQueryParameters,
_requestContext.Logger);

_requestContext.Logger.Info("[Managed Identity] Sending request to managed identity endpoints.");

IRetryPolicy retryPolicy = _requestContext.ServiceBundle.Config.RetryPolicyFactory.GetRetryPolicy(request.RequestType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,24 @@ internal void AddClaimsAndCapabilities(
logger.Info("[Managed Identity] Passing SHA-256 of the 'revoked' token to Managed Identity endpoint.");
}
}

/// <summary>
/// Adds extra query parameters to the Managed Identity request.
/// </summary>
/// <param name="extraQueryParameters">Dictionary containing additional query parameters to append to the request.
/// The parameter can be null.</param>
/// <param name="logger">Logger instance for recording the operation.</param>
internal void AddExtraQueryParams(IDictionary<string, string> extraQueryParameters, ILoggerAdapter logger)
{
if (extraQueryParameters != null)
{
foreach (var kvp in extraQueryParameters)
{
QueryParameters[kvp.Key] = kvp.Value;
}

logger.Info($"[Managed Identity] Adding {extraQueryParameters.Count} extra query parameters to Managed Identity request.");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const Microsoft.Identity.Client.MsalError.InvalidCertificate = "invalid_certificate" -> string
Microsoft.Identity.Client.ManagedIdentityApplication.GetManagedIdentitySourceAsync() -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource>
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
Microsoft.Identity.Client.ManagedIdentityApplicationBuilder.WithExtraQueryParameters(System.Collections.Generic.IDictionary<string, string> extraQueryParameters) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const Microsoft.Identity.Client.MsalError.InvalidCertificate = "invalid_certificate" -> string
Microsoft.Identity.Client.ManagedIdentityApplication.GetManagedIdentitySourceAsync() -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource>
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
Microsoft.Identity.Client.ManagedIdentityApplicationBuilder.WithExtraQueryParameters(System.Collections.Generic.IDictionary<string, string> extraQueryParameters) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const Microsoft.Identity.Client.MsalError.InvalidCertificate = "invalid_certificate" -> string
Microsoft.Identity.Client.ManagedIdentityApplication.GetManagedIdentitySourceAsync() -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource>
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
Microsoft.Identity.Client.ManagedIdentityApplicationBuilder.WithExtraQueryParameters(System.Collections.Generic.IDictionary<string, string> extraQueryParameters) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const Microsoft.Identity.Client.MsalError.InvalidCertificate = "invalid_certificate" -> string
Microsoft.Identity.Client.ManagedIdentityApplication.GetManagedIdentitySourceAsync() -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource>
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
Microsoft.Identity.Client.ManagedIdentityApplicationBuilder.WithExtraQueryParameters(System.Collections.Generic.IDictionary<string, string> extraQueryParameters) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const Microsoft.Identity.Client.MsalError.InvalidCertificate = "invalid_certificate" -> string
Microsoft.Identity.Client.ManagedIdentityApplication.GetManagedIdentitySourceAsync() -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource>
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
Microsoft.Identity.Client.ManagedIdentityApplicationBuilder.WithExtraQueryParameters(System.Collections.Generic.IDictionary<string, string> extraQueryParameters) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
const Microsoft.Identity.Client.MsalError.InvalidCertificate = "invalid_certificate" -> string
Microsoft.Identity.Client.ManagedIdentityApplication.GetManagedIdentitySourceAsync() -> System.Threading.Tasks.Task<Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource>
Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource.ImdsV2 = 8 -> Microsoft.Identity.Client.ManagedIdentity.ManagedIdentitySource
Microsoft.Identity.Client.ManagedIdentityApplicationBuilder.WithExtraQueryParameters(System.Collections.Generic.IDictionary<string, string> extraQueryParameters) -> Microsoft.Identity.Client.ManagedIdentityApplicationBuilder
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,8 @@ public static MockHttpMessageHandler AddManagedIdentityMockHandler(
HttpStatusCode statusCode = HttpStatusCode.OK,
string retryAfterHeader = null, // A number of seconds (e.g., "120"), or an HTTP-date in RFC1123 format (e.g., "Fri, 19 Apr 2025 15:00:00 GMT")
bool capabilityEnabled = false,
bool claimsEnabled = false
bool claimsEnabled = false,
IDictionary<string, string> extraQueryParameters = null
)
{
HttpResponseMessage responseMessage = new HttpResponseMessage(statusCode)
Expand All @@ -393,6 +394,15 @@ public static MockHttpMessageHandler AddManagedIdentityMockHandler(
capabilityEnabled,
claimsEnabled);

// Add extra query parameters if provided
if (extraQueryParameters != null)
{
foreach (var kvp in extraQueryParameters)
{
httpMessageHandler.ExpectedQueryParams[kvp.Key] = kvp.Value;
}
}

if (managedIdentitySourceType == ManagedIdentitySource.MachineLearning)
{
// For Machine Learning (App Service 2017), the client id param is "clientid"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net;
Expand Down Expand Up @@ -1508,5 +1509,70 @@ private AbstractManagedIdentity CreateManagedIdentitySource(ManagedIdentitySourc

return managedIdentity;
}

[TestMethod]
public async Task ManagedIdentityWithExtraQueryParametersTestAsync()
{
using (new EnvVariableContext())
using (var httpManager = new MockHttpManager())
{
SetEnvironmentVariables(ManagedIdentitySource.AppService, AppServiceEndpoint);

var extraQueryParameters = new Dictionary<string, string>
{
{ "param1", "value1" },
{ "param2", "value2" },
{ "custom_param", "custom_value" }
};

var miBuilder = ManagedIdentityApplicationBuilder.Create(ManagedIdentityId.SystemAssigned)
.WithExperimentalFeatures(true)
.WithExtraQueryParameters(extraQueryParameters)
.WithHttpManager(httpManager);

var mi = miBuilder.Build();

httpManager.AddManagedIdentityMockHandler(
AppServiceEndpoint,
Resource,
MockHelpers.GetMsiSuccessfulResponse(),
ManagedIdentitySource.AppService,
extraQueryParameters: extraQueryParameters);

var result = await mi.AcquireTokenForManagedIdentity(Resource).ExecuteAsync().ConfigureAwait(false);
}
}

[TestMethod]
public void WithExtraQueryParameters_MultipleCallsMergeValues()
{
var firstParams = new Dictionary<string, string>
{
{ "param1", "value1" },
{ "param2", "value2" }
};

var secondParams = new Dictionary<string, string>
{
{ "param3", "value3" },
{ "param4", "value4" },
{ "param1", "newvalue1" } // This should overwrite the first param1
};

var miBuilder = ManagedIdentityApplicationBuilder
.Create(ManagedIdentityId.SystemAssigned)
.WithExperimentalFeatures(true)
.WithExtraQueryParameters(firstParams)
.WithExtraQueryParameters(secondParams);

// Verify that parameters are merged
Assert.AreEqual(4, miBuilder.Config.ExtraQueryParameters.Count);

// Verify merged values
Assert.AreEqual("newvalue1", miBuilder.Config.ExtraQueryParameters["param1"]);
Assert.AreEqual("value2", miBuilder.Config.ExtraQueryParameters["param2"]);
Assert.AreEqual("value3", miBuilder.Config.ExtraQueryParameters["param3"]);
Assert.AreEqual("value4", miBuilder.Config.ExtraQueryParameters["param4"]);
}
}
}