Implement UserFIC: IByUserFederatedIdentityCredential interface and user_fic grant type#5802
Conversation
…dentityCredential interface, and UserFederatedIdentityCredentialRequest Co-authored-by: neha-bhargava <61847233+neha-bhargava@users.noreply.github.com>
… test Co-authored-by: neha-bhargava <61847233+neha-bhargava@users.noreply.github.com>
|
@copilot Can you add integration tests using username ficuser@msidlabtse4.onmicrosoft.com and confidential client app with app id 979a25aa-0daf-41a5-bcad-cebec5c7c254. Same app id can be used for creating assertion as well as getting the token. |
…crosoft.com Co-authored-by: neha-bhargava <61847233+neha-bhargava@users.noreply.github.com>
Added integration tests in
All tests use app ID |
...ty.Test.Integration.netcore/HeadlessTests/UserFederatedIdentityCredentialIntegrationTests.cs
Outdated
Show resolved
Hide resolved
…on in UserFIC integration tests Co-authored-by: neha-bhargava <61847233+neha-bhargava@users.noreply.github.com>
...t.Identity.Client/ApiConfig/AcquireTokenByUserFederatedIdentityCredentialParameterBuilder.cs
Outdated
Show resolved
Hide resolved
src/client/Microsoft.Identity.Client/AppConfig/FederatedCredentialProvider.cs
Outdated
Show resolved
Hide resolved
|
@copilot Update the user fix dev ex to remove the helper methods and class FederatedCredentialProvider.cs. The dev ex will require the developer to create an assertion and pass to AcquireTokenByUserFederatedIdentityCredential as a plain string. Update methods as well |
…ain string assertion Co-authored-by: neha-bhargava <61847233+neha-bhargava@users.noreply.github.com>
Done in commit 6093243. |
|
@copilot remove the class UserFederatedIdentityCredentialIntegrationTests.cs |
Co-authored-by: neha-bhargava <61847233+neha-bhargava@users.noreply.github.com>
Head branch was pushed to by a user without write access
Adds the User Federated Identity Credential (UserFIC) flow — a new
grant_type=user_fictoken acquisition path that allows a confidential client to obtain user tokens by presenting a federated identity credential assertion instead of a password.New public surface
IByUserFederatedIdentityCredential— interface onIConfidentialClientApplicationexposingAcquireTokenByUserFederatedIdentityCredential(scopes, username, assertion)whereassertionis a plain JWT stringAcquireTokenByUserFederatedIdentityCredentialParameterBuilder— fluent builder withWithForceRefresh,WithSendX5CWire protocol (new internal plumbing)
OAuth2GrantType.UserFic = "user_fic",OAuth2Parameter.UserFederatedIdentityCredential = "user_federated_identity_credential"UserFederatedIdentityCredentialRequest— modeled afterUsernamePasswordRequest; setsuser_federated_identity_credential+usernameon the token request body, merges OIDC scopes, sendsclient_info=1, caches response in user token cacheUsage
Developers acquire the assertion themselves (from a Managed Identity, Confidential Client, or any other source) and pass the access token string directly:
Testing
6 unit tests in
UserFederatedIdentityCredentialTests.cscovering: correct OAuth2 wire parameters (grant_type,username,user_federated_identity_credential), token cache storage,ForceRefreshbehavior, and null/empty-argument guards on the builder.Performance impact
None — new code path only; no changes to existing hot paths.
Documentation
Original prompt
Implement UserFIC: Add
FederatedCredentialProviderhelper factory and extended callback signature for assertion providersCloses #5766 (sub-issue)
Overview
Implement the User Federated Identity Credential (UserFIC) flow in MSAL .NET, including a new
IByUserFederatedIdentityCredentialinterface,FederatedCredentialProviderstatic factory, and all necessary plumbing to support token acquisition viagrant_type=user_fic.API to implement
1.
IByUserFederatedIdentityCredentialinterfaceAssertionRequestOptionsis the existing type inMicrosoft.Identity.Client— it is passed directly by users (not constructed by the library internally for this flow), to allow for extensibility and future requirements. Do not add new properties toAssertionRequestOptionsfor this feature.2.
FederatedCredentialProviderstatic factoryCreate a new file:
src/client/Microsoft.Identity.Client/AppConfig/FederatedCredentialProvider.csFromManagedIdentity(ManagedIdentityId, audience?): Eagerly builds aManagedIdentityApplicationfrom the providedManagedIdentityId(viaManagedIdentityApplicationBuilder.Create(...).Build()), then returns a delegate that callsAcquireTokenForManagedIdentity(audience).ExecuteAsync(ct)and returnsresult.AccessToken.FromConfidentialClient(IConfidentialClientApplication, audience?): Returns a delegate that callscca.AcquireTokenForClient(new[] { audience }).ExecuteAsync(ct)and returnsresult.AccessToken.ArgumentNullExceptionon null arguments.audiencedefaults to"api://AzureADTokenExchange/.default".Func<AssertionRequestOptions, Task<string>>must propagateoptions.CancellationTokento the innerExecuteAsynccall.3. Internal parameter class
File:
src/client/Microsoft.Identity.Client/ApiConfig/Parameters/AcquireTokenByUserFederatedIdentityCredentialParameters.cs4. Parameter builder
File:
src/client/Microsoft.Identity.Client/ApiConfig/AcquireTokenByUserFederatedIdentityCredentialParameterBuilder.csAbstractConfidentialClientAcquireTokenParameterBuilder<AcquireTokenByUserFederatedIdentityCredentialParameterBuilder>WithForceRefresh(bool),WithSendX5C(bool),WithClaims(string),WithCorrelationId(Guid),ExecuteAsync(CancellationToken)methodsstatic internal Create(IConfidentialClientApplicationExecutor executor, IEnumerable<string> scopes, string username, Func<AssertionRequestOptions, Task<string>> assertionProvider)factory method5.
UserFederatedIdentityCredentialRequest— internal request classFile:
src/client/Microsoft.Identity.Client/Internal/Requests/UserFederatedIdentityCredentialRequest.csModel this after the existing
UsernamePasswordRequest. Key differences:grant_type=user_fic(addUserFicconstant toOAuth2GrantType)passwordparameter withuser_federated_identity_credential(add constant toOAuth2Parameter)AssertionProvider(assertionRequestOptions)to get the assertion string, then set it asuser_federated_identity_credentialon the OAuth2 request bodyopenid,offline_access,profilein scopes (same as ROPC)client_info=1(same as ROPC)IAccount6. Wire up
ConfidentialClientApplicationConfidentialClientApplicationshould implementIByUserFederatedIdentityCredentialIConfidentialClientApplicationshould extend `IByUserF...This pull request was created from Copilot chat.
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.