Skip to content

Wire ClientDataInfo through AcquireTokenResult, Fixes AB#3604499#3109

Merged
fadidurah merged 17 commits into
devfrom
fadi/wire-clientdata-to-acquiretokenresult
May 15, 2026
Merged

Wire ClientDataInfo through AcquireTokenResult, Fixes AB#3604499#3109
fadidurah merged 17 commits into
devfrom
fadi/wire-clientdata-to-acquiretokenresult

Conversation

@fadidurah
Copy link
Copy Markdown
Contributor

@fadidurah fadidurah commented May 12, 2026

Propagate the parsed x-ms-clientdata (token endpoint) and clientdata query parameter (authorize endpoint) data from the response handlers through TokenResult, MicrosoftStsAuthorizationResult, and ultimately onto AcquireTokenResult so callers can access server-side telemetry (error, sub-error, account type, cloud instance, data boundary).

AB#3604499

Copilot AI review requested due to automatic review settings May 12, 2026 02:04
@fadidurah fadidurah requested a review from a team as a code owner May 12, 2026 02:04
@github-actions
Copy link
Copy Markdown

❌ Work item link check failed. Description does not contain AB#{ID}.

Click here to Learn more.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Propagates ClientDataInfo (parsed from x-ms-clientdata response header and clientdata redirect query parameter) through the Common auth result pipeline so callers can access server-side telemetry context via AcquireTokenResult.

Changes:

  • Added ClientDataInfo plumbing to TokenResult, MicrosoftStsAuthorizationResult, and AcquireTokenResult.
  • Wired clientdata parsing results into MicrosoftStsAuthorizationResultFactory (/authorize redirect parsing) and AbstractMicrosoftStsTokenResponseHandler (/token header parsing).
  • Propagated ClientDataInfo from authorization/token results into AcquireTokenResult in controllers (preferring the token endpoint value when present).

Reviewed changes

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

Show a summary per file
File Description
common4j/src/main/com/microsoft/identity/common/java/result/AcquireTokenResult.java Adds nullable ClientDataInfo accessor/mutator to expose server-side telemetry to callers.
common4j/src/main/com/microsoft/identity/common/java/providers/oauth2/TokenResult.java Stores nullable ClientDataInfo parsed from x-ms-clientdata on token responses.
common4j/src/main/com/microsoft/identity/common/java/providers/microsoft/microsoftsts/MicrosoftStsAuthorizationResultFactory.java Captures clientdata redirect param into MicrosoftStsAuthorizationResult.
common4j/src/main/com/microsoft/identity/common/java/providers/microsoft/microsoftsts/MicrosoftStsAuthorizationResult.java Adds nullable ClientDataInfo storage on authorization results.
common4j/src/main/com/microsoft/identity/common/java/providers/microsoft/microsoftsts/AbstractMicrosoftStsTokenResponseHandler.java Sets ClientDataInfo onto TokenResult when header is present/parseable (behind flight).
common4j/src/main/com/microsoft/identity/common/java/controllers/BaseController.java Copies TokenResult.getClientDataInfo() into AcquireTokenResult for ROPC/silent flows.
common/src/main/java/com/microsoft/identity/common/internal/controllers/LocalMSALController.java Wires ClientDataInfo from authorize result, then prefers token endpoint value when available.
Comments suppressed due to low confidence (1)

common4j/src/main/com/microsoft/identity/common/java/providers/microsoft/microsoftsts/MicrosoftStsAuthorizationResultFactory.java:84

  • Test coverage: parseRedirectUriAndCreateAuthorizationResult() now attaches ClientDataInfo to the returned MicrosoftStsAuthorizationResult (result.setClientDataInfo(clientDataInfo)). The existing factory tests validate span attributes but don’t assert that the parsed data is actually accessible on the result object. Add an assertion (casting to MicrosoftStsAuthorizationResult) that getClientDataInfo() is populated with the expected fields when the clientdata query parameter is present (and null when absent/flight disabled).
        ClientDataInfo clientDataInfo = null;
        if (CommonFlightsManager.INSTANCE.getFlightsProvider().isFlightEnabled(CommonFlight.ENABLE_SERVER_CLIENT_DATA_TELEMETRY)) {
            clientDataInfo = ClientDataInfo.fromPipeDelimited(urlParameters.get(ClientDataInfo.CLIENTDATA_QUERY_PARAMETER));
            if (null != clientDataInfo) {
                clientDataInfo.emitToSpan();
            }
        }

@fadidurah fadidurah force-pushed the fadi/wire-clientdata-to-acquiretokenresult branch 4 times, most recently from dc89211 to d3c256a Compare May 13, 2026 21:39
@fadidurah fadidurah requested a review from a team as a code owner May 13, 2026 21:51
@github-actions
Copy link
Copy Markdown

✅ Work item link check complete. Description contains link AB#3604499 to an Azure Boards work item.

@github-actions
Copy link
Copy Markdown

❌ Work item link check failed. Description contains AB#3604499 but the Bot could not link it to an Azure Boards work item.

Click here to learn more.

@github-actions github-actions Bot changed the title Wire ClientDataInfo through AcquireTokenResult Wire ClientDataInfo through AcquireTokenResult, Fixes AB#3604499 May 13, 2026
@fadidurah fadidurah force-pushed the fadi/wire-clientdata-to-acquiretokenresult branch 4 times, most recently from 1677007 to fdae003 Compare May 13, 2026 23:41
Propagate ClientDataInfo (parsed from the x-ms-clientdata token response
header and the clientdata authorize redirect query parameter) through
AcquireTokenResult on success paths and through BaseException on failure
paths. Includes broker IPC serialization via BrokerResult so the payload
reaches the MSAL caller process for both success and error responses.
Adds a raw field to ClientDataInfo preserving the original pipe-delimited
string for partner teams that want the unparsed payload.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@fadidurah fadidurah force-pushed the fadi/wire-clientdata-to-acquiretokenresult branch from fdae003 to 694037f Compare May 13, 2026 23:46
);
}

result.setClientDataInfo(clientDataInfo);
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.

result.setClientDataInfo(clientDataInfo);

Is it okay, if this is not under flight?

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.

Good catch — while clientDataInfo is always null when the flight is disabled (making the unconditional call semantically a no-op), it was misleading. Fixed in f849f51 by wrapping the setClientDataInfo call in a null != clientDataInfo guard, so it's only invoked when the flight is enabled and parsing actually succeeded.

fadidurah and others added 2 commits May 14, 2026 18:36
…cationResult

LocalAuthenticationResult is the single canonical owner of ClientDataInfo (it's the only result type that survives the broker IPC boundary). Remove the redundant mClientDataInfo field/setter from AcquireTokenResult; getClientDataInfo() now delegates to the underlying LocalAuthenticationResult. Update controllers (LocalMSALController, BaseController) and MsalBrokerResultAdapter to write CDI directly to LocalAuthenticationResult, sourcing it from TokenResult (preferred) with fallback to MicrosoftStsAuthorizationResult.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolve in order: LocalAuthenticationResult -> TokenResult -> MicrosoftStsAuthorizationResult. This ensures callers can retrieve CDI even on failure paths where LocalAuthenticationResult was never constructed (e.g., token-error or authorize-error responses).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 7 comments.

);
}

result.setClientDataInfo(clientDataInfo);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@copilot in this case, ClientDataInfo should not be attached

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.

Fixed in accc218. ClientDataInfo is now only attached to the result when AuthorizationStatus.SUCCESS — i.e., after state validation passes. For state-mismatch (potential CSRF redirects), it is discarded. Also added two unit tests covering both cases: testClientDataParam_stateMismatch_clientDataInfoNotAttached and testClientDataParam_validState_clientDataInfoAttached.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@copilot nope, we shouldn't limit it based on authorizationstatus being SUCCESS. if it is a failure we especially want the clientDataInfo, but only if it's coming from a trusted source

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.

Fixed in f3c3f0b. The guard now excludes only state-mismatch errors specifically (CSRF protection), allowing ClientDataInfo to be attached for all other results including server-error redirects (FAIL with errors like access_denied, login_required, etc.). Added a testClientDataParam_serverError_clientDataInfoAttached test to verify this.

Copy link
Copy Markdown
Contributor

Copilot AI commented May 14, 2026

Just as a heads up, I was blocked by some firewall rules while working on your feedback. Expand below for details.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • www.puppycrawl.com
    • Triggering command: /opt/hostedtoolcache/CodeQL/2.25.1/x64/codeql/tools/linux64/java/bin/java /opt/hostedtoolcache/CodeQL/2.25.1/x64/codeql/tools/linux64/java/bin/java -jar /opt/hostedtoolcache/CodeQL/2.25.1/x64/codeql/xml/tools/xml-extractor.jar --fileList=/tmp/codeql-scratch-b2678d0398b00160/dbs/java/working/files-to-index15681778810567777269.list --sourceArchiveDir=/tmp/codeql-scratch-b2678d0398b00160/dbs/java/src --outputDir=/tmp/codeql-scratch-b2678d0398b00160/dbs/java/trap/java -j DROP (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

fadidurah and others added 2 commits May 14, 2026 19:49
When configure-on-demand is enabled, Gradle only configures the projects
that are actually in the dependency graph of the requested tasks. Previously
building AADAuthenticator triggered configure of broker4j, brokerHost,
java-linux-test-app, LinuxBroker, brokerautomationapp etc. — none of
which are needed for AADAuthenticator:assembleDistRelease. Logs showed
~16 min spent in unnecessary configure phases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@fadidurah
Copy link
Copy Markdown
Contributor Author

@copilot there's a merge conflict in dev, please fix it

…resolve conflicts keeping both ClientDataInfo IPC and onboarding blob changes

Co-authored-by: fadidurah <88730756+fadidurah@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented May 15, 2026

@copilot there's a merge conflict in dev, please fix it

Resolved in 331dc0c. Four files had conflicts:

  • BrokerResult.java: kept both CLIENT_DATA_INFO and ONBOARDING_BLOB constants
  • MsalBrokerResultAdapter.java: adopted dev's authenticationResultFromBrokerResult(brokerResult) refactoring to avoid double deserialization
  • MsalBrokerResultAdapterTests.kt: kept both the ClientDataInfo round-trip tests and the new onboarding blob tests
  • AcquireTokenResultTest.java (add/add): merged both the ClientDataInfo resolution chain tests and the onboarding blob accessor tests into one class

@fadidurah
Copy link
Copy Markdown
Contributor Author

@copilot what's the current status? seems you got stuck

Copy link
Copy Markdown
Contributor

Copilot AI commented May 15, 2026

@copilot what's the current status? seems you got stuck

The branch is up to date — the merge conflict with dev was resolved in 331dc0c. The branch is clean with no pending conflicts or uncommitted changes.

@fadidurah
Copy link
Copy Markdown
Contributor Author

@copilot make sure all of the additions in this PR are gated behind the flight ENABLE_SERVER_CLIENT_DATA_TELEMETRY

Copy link
Copy Markdown
Contributor

Copilot AI commented May 15, 2026

@copilot make sure all of the additions in this PR are gated behind the flight ENABLE_SERVER_CLIENT_DATA_TELEMETRY

Done in d0f38bf. All ClientDataInfo propagation points are now gated behind ENABLE_SERVER_CLIENT_DATA_TELEMETRY:

  • ExceptionAdapter — auth-exception path and token-error path
  • BaseController — interactive and silent token result paths
  • LocalMSALController — interactive token and device-code-flow paths
  • MsalBrokerResultAdapter — success serialization, exception serialization, success deserialization, and exception deserialization

The parsing entry points (MicrosoftStsAuthorizationResultFactory and AbstractMicrosoftStsTokenResponseHandler) were already gated in earlier commits. The flight defaults to true, so existing tests continue to pass without any setup changes.

Comment thread gradle.properties Outdated
Copy link
Copy Markdown
Contributor

@mohitc1 mohitc1 left a comment

Choose a reason for hiding this comment

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

:shipit:

@fadidurah fadidurah merged commit 26de108 into dev May 15, 2026
28 checks passed
fadidurah added a commit that referenced this pull request May 16, 2026
…, Fixes AB#3604499 (#3118)

Cherry-picks #3109 (squash commit `26de108`) onto
`working/release/24.2.1` for the 24.2.1 hotfix.

Propagates the parsed `x-ms-clientdata` (token endpoint) and
`clientdata` query parameter (authorize endpoint) data from the response
handlers through `TokenResult`, `MicrosoftStsAuthorizationResult`, and
ultimately onto `AcquireTokenResult` so callers can access server-side
telemetry (error, sub-error, account type, cloud instance, data
boundary). All propagation is gated behind the
`ENABLE_SERVER_CLIENT_DATA_TELEMETRY` flight.

### Conflict resolution notes
The hotfix branch does not contain the onboarding-blob feature (PR #3088
/ #3111) that landed on `dev` alongside #3109. To keep this hotfix
scoped to ClientDataInfo only, the following PR-side additions were
dropped during cherry-pick:
- `BrokerResult.ONBOARDING_BLOB` constant (kept only `CLIENT_DATA_INFO`)
- `MsalBrokerResultAdapterTests.testOnboardingBlob_*` tests
- `AcquireTokenResultTest.onboardingBlob_*` tests
- Other `vNext` changelog entries unrelated to #3109

All `ClientDataInfo` plumbing from #3109 is preserved unchanged.


[AB#3604499](https://identitydivision.visualstudio.com/fac9d424-53d2-45c0-91b5-ef6ba7a6bf26/_workitems/edit/3604499)

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
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