Skip to content

Add OID-based user identification to UserFIC (user_fic) flow#6050

Merged
Avery-Dunn merged 4 commits into
mainfrom
avdunn/fic-oid-support
Jun 4, 2026
Merged

Add OID-based user identification to UserFIC (user_fic) flow#6050
Avery-Dunn merged 4 commits into
mainfrom
avdunn/fic-oid-support

Conversation

@Avery-Dunn

Copy link
Copy Markdown
Contributor

Adds a Guid userObjectId overload to AcquireTokenByUserFederatedIdentityCredential, enabling callers to identify users by Object ID (OID) in the user_fic grant type. Previously, only UPN-based identification (username parameter) was supported.

This brings MSAL .NET into parity with MSAL Java, Python, Go, and ID Web, which already support both UPN and OID for UserFIC scenarios.

Why a Guid overload?

The user_fic grant type identifies the target user via one of two mutually exclusive body parameters:

Parameter Identifier type Example
username UPN (User Principal Name) alice@contoso.com
user_id OID (Object ID) 11111111-2222-3333-4444-555555555555

A single method with a string parameter cannot disambiguate whether a given string is a UPN or an OID: both are valid strings, and while they often look very different there's no reliable way to guarantee that a string of characters isn't actually a username.

Using Guid for the OID overload resolves this problem:

  1. Unambiguous dispatch — the compiler resolves string vs Guid overloads without ambiguity
  2. Type safety — prevents accidentally passing a UPN where an OID is expected (and vice versa), matching MSAL Java and ID Web's use of GUID types

Changes

Production code

File Change
IByUserFederatedIdentityCredential.cs Added Guid userObjectId overload with XML docs
AcquireTokenByUserFederatedIdentityCredentialParameters.cs Added Guid? UserObjectId property, improved LogParameters()
AcquireTokenByUserFederatedIdentityCredentialParameterBuilder.cs Added Guid constructor + Create factory (rejects Guid.Empty)
UserFederatedIdentityCredentialRequest.cs OID/UPN mutual exclusion in POST body (user_id vs username), CCS routing by OID
OAuthConstants.cs Added UserId = "user_id" constant
ConfidentialClientApplication.cs Implemented OID overload via explicit interface
PublicAPI.Unshipped.txt (×6 TFMs) New API entry

Request body behavior

When UserObjectId is set, the request sends user_id=<guid> and omits username. When Username is set, it sends username=<upn> and omits user_id. This mutual exclusion is enforced structurally — the two code paths use separate constructors, so both values cannot be populated simultaneously through the public API.

CCS routing follows the same pattern: OID requests use oid:<oid>@<tenantId>, UPN requests use the existing upn:<upn> header.

Tests (6 new, 13 total)

Test What it validates
AcquireTokenByUserFic_WithOid_SendsUserIdParameter_Async user_id in POST body, username absent
AcquireTokenByUserFic_WithUpn_SendsUsernameParameter_Async username in POST body, user_id absent
AcquireTokenByUserFic_EmptyGuid_ThrowsArgumentException Guid.Empty rejected at builder creation
AcquireTokenByUserFic_NullOidAssertion_ThrowsArgumentNullException Null assertion rejected for OID overload
AcquireTokenByUserFic_EmptyOidAssertion_ThrowsArgumentNullException Empty assertion rejected for OID overload
AcquireTokenByUserFic_TwoUpns_SilentReturnsCorrectToken_Async Multi-user cache isolation by UPN
AcquireTokenByUserFic_TwoOids_SilentReturnsCorrectToken_Async Multi-user cache isolation by OID (lookup via HomeAccountId.ObjectId)

@Avery-Dunn Avery-Dunn requested a review from a team as a code owner June 3, 2026 15:59
Copilot AI review requested due to automatic review settings June 3, 2026 15:59

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Object ID (OID) support to the User Federated Identity Credential (user_fic) flow by introducing a Guid userObjectId overload, enabling unambiguous user identification (UPN vs OID) and ensuring the token request body/CCS routing hint use user_id when OID is supplied.

Changes:

  • Added a Guid userObjectId overload to AcquireTokenByUserFederatedIdentityCredential and surfaced it via ConfidentialClientApplication.
  • Updated request construction to send user_id (OID) vs username (UPN) in a mutually exclusive way, including CCS routing behavior.
  • Added unit tests for request-body mutual exclusion, argument validation, and multi-user cache behavior.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/Microsoft.Identity.Test.Unit/RequestsTests/UserFederatedIdentityCredentialTests.cs Adds tests validating OID vs UPN request-body parameters and multi-user cache behavior.
src/client/Microsoft.Identity.Client/PublicApi/netstandard2.0/PublicAPI.Unshipped.txt Declares the new public API signature for the OID overload.
src/client/Microsoft.Identity.Client/PublicApi/net8.0/PublicAPI.Unshipped.txt Declares the new public API signature for the OID overload.
src/client/Microsoft.Identity.Client/PublicApi/net8.0-ios/PublicAPI.Unshipped.txt Declares the new public API signature for the OID overload.
src/client/Microsoft.Identity.Client/PublicApi/net8.0-android/PublicAPI.Unshipped.txt Declares the new public API signature for the OID overload.
src/client/Microsoft.Identity.Client/PublicApi/net472/PublicAPI.Unshipped.txt Declares the new public API signature for the OID overload.
src/client/Microsoft.Identity.Client/PublicApi/net462/PublicAPI.Unshipped.txt Declares the new public API signature for the OID overload.
src/client/Microsoft.Identity.Client/OAuth2/OAuthConstants.cs Adds OAuth2Parameter.UserId constant (user_id) for user_fic requests.
src/client/Microsoft.Identity.Client/Internal/Requests/UserFederatedIdentityCredentialRequest.cs Switches request body + CCS routing between user_id (OID) and username (UPN).
src/client/Microsoft.Identity.Client/IByUserFederatedIdentityCredential.cs Adds the new Guid userObjectId overload with XML documentation.
src/client/Microsoft.Identity.Client/ConfidentialClientApplication.cs Implements the new overload (explicit interface) and routes to the builder factory.
src/client/Microsoft.Identity.Client/ApiConfig/Parameters/AcquireTokenByUserFederatedIdentityCredentialParameters.cs Adds UserObjectId parameter storage and improves parameter logging.
src/client/Microsoft.Identity.Client/ApiConfig/AcquireTokenByUserFederatedIdentityCredentialParameterBuilder.cs Adds builder constructor/factory for OID, including Guid.Empty validation.

# Conflicts:
#	src/client/Microsoft.Identity.Client/PublicApi/net462/PublicAPI.Unshipped.txt
#	src/client/Microsoft.Identity.Client/PublicApi/net472/PublicAPI.Unshipped.txt
#	src/client/Microsoft.Identity.Client/PublicApi/net8.0-android/PublicAPI.Unshipped.txt
#	src/client/Microsoft.Identity.Client/PublicApi/net8.0-ios/PublicAPI.Unshipped.txt
#	src/client/Microsoft.Identity.Client/PublicApi/net8.0/PublicAPI.Unshipped.txt
#	src/client/Microsoft.Identity.Client/PublicApi/netstandard2.0/PublicAPI.Unshipped.txt

@gladjohn gladjohn left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!!!

@neha-bhargava neha-bhargava left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approve with comments

Copilot AI review requested due to automatic review settings June 4, 2026 18:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot encountered an error and was unable to review this pull request. You can try again by re-requesting a review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants