Add User Federated Identity Credential (user_fic) grant type support#1026
Add User Federated Identity Credential (user_fic) grant type support#1026Avery-Dunn wants to merge 3 commits intoavdunn/fmi-supportfrom
user_fic) grant type support#1026Conversation
| } | ||
|
|
||
| // ======================================================================== | ||
| // §6: user_fic grant type |
There was a problem hiding this comment.
Strange that this starts from 6
There was a problem hiding this comment.
The agent wrote this and some other comments with references to sections in some docs and some behavior in .NET it was using as examples.
In the latest commit I've cleaned up all the comments to remove that sort of stuff.
neha-bhargava
left a comment
There was a problem hiding this comment.
Overall looks good. I would like to see some end to end tests as well where an assertion is built and passed to user fic. The test setup is up and working and used in MISE PR.
user_fic) grant type support
c94ca99 to
07bdbb7
Compare
| // This handles cases where the IdP returns a slightly different username format | ||
| // (e.g., preferred_username vs UPN) but the token is still for the same user. | ||
| if (accounts.size() == 1) { | ||
| return accounts.iterator().next(); |
There was a problem hiding this comment.
This fallback can silently return the wrong user's token. If user B's account is in the cache and a first-time request comes in for user A (no username/OID match), accounts.size() == 1 is true and user B's token gets returned for user A — no error, no warning logged. The userFic_TwoUpns_SilentReturnsCorrectToken test won't catch this because it has 2 accounts in cache. What's the intended behavior here — if there's no exact match, shouldn't the safer default be to return null and go to IdP? A fresh token acquisition would naturally fix any format mismatch and cache correctly on the way back.
This PR adds support for the
user_fic(User Federated Identity Credential) grant type to MSAL Java, enabling Leg 3 of the agent identity protocol. This allows an agent application to exchange a federated identity credential (obtained from Leg 2's instance token) for a user-scoped access token, enabling the agent to act on behalf of a specific user.What's included
New public APIs:
IConfidentialClientApplication.acquireToken(UserFederatedIdentityCredentialParameters)— acquires a user-scoped token using theuser_ficgrant typeUserFederatedIdentityCredentialParameters— parameter object with builder pattern, supporting:.builder(scopes, username, assertion)— identify user by UPN.builder(scopes, userObjectId, assertion)— identify user by Object ID (UUID).forceRefresh(boolean)— bypass cache and hit IdP.tenant(String)— override tenant.claims(ClaimsRequest)— claims challenge support.extraHttpHeaders(Map)/.extraQueryParameters(Map)— extensibilityToken request behavior:
grant_type=user_ficin the POST bodyuser_federated_identity_credential=<T2>(the instance token from Leg 2)user_id=<OID>orusername=<UPN>(mutually exclusive, enforced by API design)openid,profile,offline_access(user-flow behavior, not app-flow)client_info=1to receive account information in the responseCache behavior:
forceRefresh=true)findCachedAccount()which matches by OID (homeAccountId prefix) or UPN (case-insensitive), with a single-account fallback for format mismatchesInternal changes:
AcquireTokenByUserFederatedIdentityCredentialSupplier— orchestrates cache-then-network logic, includingfindCachedAccount()for silent lookupUserFederatedIdentityCredentialRequest— constructs the OAuth2 grant with correct parametersGrantConstants.USER_FIC— new grant type constantConfidentialClientApplication.acquireToken(UserFederatedIdentityCredentialParameters)— routes to the new supplierPublicApi.ACQUIRE_TOKEN_BY_USER_FEDERATED_IDENTITY_CREDENTIAL— telemetry enumTests:
UserFederatedIdentityCredentialTest.java— 19 unit tests covering:FicIT.java— 4 integration tests matching MSAL .NET's agentic FIC coverage (user_fic with UPN, user_fic with OID, cache isolation between app and user tokens, multi-user cache correctness)AgenticIT.java— expanded with 2 additional FIC integration tests (agent acquiring user token for Graph, app+user token cache isolation)Alignment with MSAL .NET
This implementation matches the
user_ficbehavior on MSAL .NET'smainbranch. Key equivalences:AcquireTokenByUserFederatedIdentityCredential(scopes, username, assertion)acquireToken(UserFederatedIdentityCredentialParameters.builder(scopes, username, assertion).build())WithForceRefresh(true).forceRefresh(true)findCachedAccount()grant_type=user_fic+ scope augmentation +client_info=1Differences from .NET (intentional)
username(UPN)usernameanduserObjectId(UUID)AcquireTokenSilentseparately