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);