diff --git a/src/Microsoft.Identity.Abstractions/PublicAPI/net462/PublicAPI.Unshipped.txt b/src/Microsoft.Identity.Abstractions/PublicAPI/net462/PublicAPI.Unshipped.txt index 7dc5c58..bf40861 100644 --- a/src/Microsoft.Identity.Abstractions/PublicAPI/net462/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Abstractions/PublicAPI/net462/PublicAPI.Unshipped.txt @@ -1 +1,3 @@ #nullable enable +Microsoft.Identity.Abstractions.AcquireTokenOptions.FmiPath.get -> string? +Microsoft.Identity.Abstractions.AcquireTokenOptions.FmiPath.set -> void \ No newline at end of file diff --git a/src/Microsoft.Identity.Abstractions/PublicAPI/net8.0/PublicAPI.Unshipped.txt b/src/Microsoft.Identity.Abstractions/PublicAPI/net8.0/PublicAPI.Unshipped.txt index 7dc5c58..bf40861 100644 --- a/src/Microsoft.Identity.Abstractions/PublicAPI/net8.0/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Abstractions/PublicAPI/net8.0/PublicAPI.Unshipped.txt @@ -1 +1,3 @@ #nullable enable +Microsoft.Identity.Abstractions.AcquireTokenOptions.FmiPath.get -> string? +Microsoft.Identity.Abstractions.AcquireTokenOptions.FmiPath.set -> void \ No newline at end of file diff --git a/src/Microsoft.Identity.Abstractions/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt b/src/Microsoft.Identity.Abstractions/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt index 7dc5c58..bf40861 100644 --- a/src/Microsoft.Identity.Abstractions/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Abstractions/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt @@ -1 +1,3 @@ #nullable enable +Microsoft.Identity.Abstractions.AcquireTokenOptions.FmiPath.get -> string? +Microsoft.Identity.Abstractions.AcquireTokenOptions.FmiPath.set -> void \ No newline at end of file diff --git a/src/Microsoft.Identity.Abstractions/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt b/src/Microsoft.Identity.Abstractions/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt index 7dc5c58..bf40861 100644 --- a/src/Microsoft.Identity.Abstractions/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt +++ b/src/Microsoft.Identity.Abstractions/PublicAPI/netstandard2.1/PublicAPI.Unshipped.txt @@ -1 +1,3 @@ #nullable enable +Microsoft.Identity.Abstractions.AcquireTokenOptions.FmiPath.get -> string? +Microsoft.Identity.Abstractions.AcquireTokenOptions.FmiPath.set -> void \ No newline at end of file diff --git a/src/Microsoft.Identity.Abstractions/TokenAcquisition/AcquireTokenOptions.cs b/src/Microsoft.Identity.Abstractions/TokenAcquisition/AcquireTokenOptions.cs index 1c7a896..1dfe63d 100644 --- a/src/Microsoft.Identity.Abstractions/TokenAcquisition/AcquireTokenOptions.cs +++ b/src/Microsoft.Identity.Abstractions/TokenAcquisition/AcquireTokenOptions.cs @@ -33,6 +33,7 @@ public AcquireTokenOptions(AcquireTokenOptions other) ExtraHeadersParameters = other.ExtraHeadersParameters; ExtraParameters = other.ExtraParameters; ForceRefresh = other.ForceRefresh; + FmiPath = other.FmiPath; Claims = other.Claims; PopPublicKey = other.PopPublicKey; PopClaim = other.PopClaim; @@ -81,6 +82,11 @@ public AcquireTokenOptions(AcquireTokenOptions other) /// public string? Claims { get; set; } + /// + /// Federated Managed Identity (FMI) sub-path. + /// + public string? FmiPath { get; set; } + /// /// Specifies if the token request will ignore the access token in the token cache /// and will attempt to acquire a new access token. diff --git a/test/Microsoft.Identity.Abstractions.Tests/AquireTokenOptionsTests.cs b/test/Microsoft.Identity.Abstractions.Tests/AquireTokenOptionsTests.cs index acdc547..7786dd7 100644 --- a/test/Microsoft.Identity.Abstractions.Tests/AquireTokenOptionsTests.cs +++ b/test/Microsoft.Identity.Abstractions.Tests/AquireTokenOptionsTests.cs @@ -67,5 +67,31 @@ public void ManagedIdentityUserAssigned() Assert.NotNull(acquireTokenOptions.ManagedIdentity); Assert.Equal(managedIdentityOptions.UserAssignedClientId, acquireTokenOptions.ManagedIdentity.UserAssignedClientId); } + + [Fact] + public void FmiPathTest() + { + // App token from a Federated Managed Identity (FMI). + // ------------------------------------------------- + /* + // + { + "AquireTokenOptions": { + "FmiPath": "/example.org/service/my-service" + } + } + // + */ + + // + AcquireTokenOptions acquireTokenOptions = new AcquireTokenOptions + { + FmiPath = "/example.org/service/my-service" + }; + // + + Assert.NotNull(acquireTokenOptions.FmiPath); + Assert.Equal("/example.org/service/my-service", acquireTokenOptions.FmiPath); + } } } diff --git a/test/Microsoft.Identity.Abstractions.Tests/CredentialDescriptionTest.cs b/test/Microsoft.Identity.Abstractions.Tests/CredentialDescriptionTest.cs index 64bf786..0f1e71a 100644 --- a/test/Microsoft.Identity.Abstractions.Tests/CredentialDescriptionTest.cs +++ b/test/Microsoft.Identity.Abstractions.Tests/CredentialDescriptionTest.cs @@ -203,7 +203,7 @@ public void Secret() [Fact] public void SignedAssertionFromMSI() { - // Signed assertion from Managed identity federation + // Signed assertion from Federation Identity Credential (Managed Identity) // ------------------------------------------------- // https://learn.microsoft.com/azure/active-directory/develop/workload-identity-federation /* diff --git a/test/Microsoft.Identity.Abstractions.Tests/DownstreamApiTests.cs b/test/Microsoft.Identity.Abstractions.Tests/DownstreamApiTests.cs index d4fb812..1671f1c 100644 --- a/test/Microsoft.Identity.Abstractions.Tests/DownstreamApiTests.cs +++ b/test/Microsoft.Identity.Abstractions.Tests/DownstreamApiTests.cs @@ -33,6 +33,7 @@ public void CloneClonesAllProperties() ExtraHeadersParameters = new Dictionary { { "slice", "test" } }, ExtraQueryParameters = new Dictionary { { "slice", "test" } }, ExtraParameters = new Dictionary { { "param1", "value1" }, { "param2", "value2" } }, + FmiPath = "fmiPath", ForceRefresh = true, LongRunningWebApiSessionKey = AcquireTokenOptions.LongRunningWebApiSessionKeyAuto, ManagedIdentity = new ManagedIdentityOptions(), @@ -83,6 +84,7 @@ public void CloneClonesAllProperties() Assert.Equal(downstreamApiOptions.AcquireTokenOptions.ExtraHeadersParameters, downstreamApiClone.AcquireTokenOptions.ExtraHeadersParameters); Assert.Equal(downstreamApiOptions.AcquireTokenOptions.ExtraQueryParameters, downstreamApiClone.AcquireTokenOptions.ExtraQueryParameters); Assert.Equal(downstreamApiOptions.AcquireTokenOptions.ExtraParameters, downstreamApiClone.AcquireTokenOptions.ExtraParameters); + Assert.Equal(downstreamApiOptions.AcquireTokenOptions.FmiPath, downstreamApiClone.AcquireTokenOptions.FmiPath); Assert.Equal(downstreamApiOptions.AcquireTokenOptions.ForceRefresh, downstreamApiClone.AcquireTokenOptions.ForceRefresh); Assert.Equal(downstreamApiOptions.AcquireTokenOptions.LongRunningWebApiSessionKey, downstreamApiClone.AcquireTokenOptions.LongRunningWebApiSessionKey); Assert.Equal(downstreamApiOptions.AcquireTokenOptions.ManagedIdentity.UserAssignedClientId, downstreamApiClone.AcquireTokenOptions.ManagedIdentity?.UserAssignedClientId); @@ -95,7 +97,7 @@ public void CloneClonesAllProperties() // If this fails, think of also adding a line to test the new property Assert.Equal(12, typeof(DownstreamApiOptions).GetProperties().Length); - Assert.Equal(14, typeof(AcquireTokenOptions).GetProperties().Length); + Assert.Equal(15, typeof(AcquireTokenOptions).GetProperties().Length); DownstreamApiOptionsReadOnlyHttpMethod options = new DownstreamApiOptionsReadOnlyHttpMethod(downstreamApiOptions, HttpMethod.Delete.ToString()); Assert.Equal(HttpMethod.Delete.ToString(), options.HttpMethod);