Skip to content

Conversation

@melissaahn
Copy link
Contributor

@melissaahn melissaahn commented Nov 4, 2025

Summary

This PR creates some new data objects and contains changes to BrokerMsalController and some validation logic in BrokerSsoController in order to accommodate the webapps API. Please see the main broker PR for a more detailed description:
Broker PR: https://github.com/AzureAD/ad-accounts-for-android/pull/3267

AB#3317102

@melissaahn melissaahn requested a review from Copilot November 4, 2025 12:16
@github-actions
Copy link

github-actions bot commented Nov 4, 2025

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

Click here to Learn more.

@melissaahn melissaahn requested a review from Copilot November 5, 2025 04:00
Copy link
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 16 out of 16 changed files in this pull request and generated 9 comments.

Comment on lines 1730 to 1737
final WebAppsTokenResponse response = new WebAppsTokenResponse(
interactiveResult.getAccountRecord() != null ? interactiveResult.getAccountRecord().getUsername() : null,
interactiveResult.getUniqueId(),
interactiveResult.getAccessTokenRecord() != null ? interactiveResult.getAccessTokenRecord().getExpiresOn() : null,
interactiveResult.getIdToken(),
interactiveResult.getAccessToken(),
null
);
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

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

Severity: High – Raw access token and ID token are being included in the response object that will be serialized and transmitted. Issue: Lines 1734-1735 include raw token values (interactiveResult.getIdToken() and interactiveResult.getAccessToken()) in the WebAppsTokenResponse. Impact: These sensitive tokens will be logged if serialization occurs in any logging/telemetry path, violating the security principle that raw tokens must never be logged (per guidelines §2.2). Recommendation: Verify that the serialization path for WebAppsTokenResponse and its transmission to the broker does not pass through any logging or telemetry emission points. If there's any risk of exposure, redact or exclude tokens from logged representations.

Copilot generated this review using guidance from repository custom instructions.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

While this is a good warning, don't we already do this in our regular token operation logic? Is this really a big concern?

Comment on lines 1699 to 1704
private String handleInteractivePhase(@NonNull final String request,
@NonNull final Bundle phaseOneResultBundle,
@NonNull final String negotiatedBrokerProtocolVersion,
@NonNull final String minBrokerProtocolVersion,
@NonNull final WebAppsAdditionalRequiredParameters additionalRequiredParams,
@Nullable final Map<String, String> additionalArgs) throws BaseException {
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

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

Complex two-phase authentication flow lacks test coverage. Issue: The handleInteractivePhase() method implements critical two-phase flow logic including deserialization, token acquisition, error handling, and response serialization, but no tests exist for this method. Impact: This complex control flow with multiple error paths (lines 1707-1709, 1718-1720, 1726-1728, 1743-1754) and serialization operations is untested, leaving high-risk authentication logic unverified. Recommendation: Add unit tests covering: (1) successful interactive token acquisition and response serialization, (2) missing interactive request payload, (3) null deserialized request, (4) token acquisition failure with ClientException, (5) token acquisition failure with ServiceException, (6) serialization errors in phase 2 request.

Copilot generated this review using guidance from repository custom instructions.
Comment on lines 1778 to 1782
private String performSecondPhaseWebAppRequest(@NonNull final String request,
@NonNull final String negotiatedBrokerProtocolVersion,
@NonNull final String minBrokerProtocolVersion,
@NonNull final WebAppsAdditionalRequiredParameters additionalRequiredParams,
@NonNull final Map<String, String> extraArgs) throws BaseException {
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

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

Second phase web app request flow lacks test coverage. Issue: The performSecondPhaseWebAppRequest() method implements the critical second phase of the two-phase authentication flow but has no test coverage. Impact: This method handles bundle construction, result extraction, and version verification (lines 1809, 1810) without verification, leaving critical authentication flow logic untested. Recommendation: Add unit tests covering: (1) successful second phase request and response, (2) null result bundle handling, (3) broker version verification failure, (4) bundle construction errors.

Copilot generated this review using guidance from repository custom instructions.
Comment on lines 1841 to 1843
private BrokerInteractiveTokenCommandParameters buildInteractiveTokenParametersForWebApps(@NonNull final WebAppsInteractiveRequest webAppsRequest,
@NonNull final WebAppsAdditionalRequiredParameters requiredParams,
@NonNull final String minBrokerProtocolVersion) throws BaseException {
Copy link

Copilot AI Nov 5, 2025

Choose a reason for hiding this comment

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

Parameter building logic with complex validation lacks test coverage. Issue: The buildInteractiveTokenParametersForWebApps() method contains extensive validation logic (lines 1845-1864), scope parsing (lines 1866-1877), authority parsing (lines 1879-1886), and parameter construction (lines 1901-1918) but has no test coverage. Impact: The complex validation and transformation logic with multiple error paths is untested, increasing risk of parameter construction bugs. Recommendation: Add unit tests covering: (1) null/missing required parameter fields, (2) null/empty authority, clientId, redirect, (3) empty vs valid scope parsing, (4) null vs non-null nonce handling, (5) instanceAware true/false, (6) authority parsing failures, (7) successful parameter construction with all fields.

Copilot generated this review using guidance from repository custom instructions.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will be writing unit tests for this path (it will take some time) and it may not come in this PR due to the size.

@melissaahn melissaahn marked this pull request as ready for review November 5, 2025 09:25
@melissaahn melissaahn requested review from a team as code owners November 5, 2025 09:25
@melissaahn
Copy link
Contributor Author

melissaahn commented Nov 6, 2025

Regarding the failing assemble consumers being caused by the validate broker step, it's failing due to a breaking change:

  D:\a\_work\1\s\AADAuthenticator\src\msal\java\com\microsoft\identity\client\MicrosoftAuthServiceOperation.java:251: error: unreported exception ClientException; must be caught or declared to be thrown
              parameters.validate();
                                 ^
  D:\a\_work\1\s\AADAuthenticator\src\msal\java\com\microsoft\identity\client\MicrosoftAuthServiceOperation.java:294: error: unreported exception ClientException; must be caught or declared to be thrown
              parameters.validate();
                                 ^
  D:\a\_work\1\s\AADAuthenticator\src\msal\java\com\microsoft\identity\client\MicrosoftAuthServiceOperation.java:458: error: unreported exception ClientException; must be caught or declared to be thrown
              parameters.validate();

The fix is to declare ClientException to be thrown, and that is made in the broker PR: https://github.com/AzureAD/ad-accounts-for-android/pull/3267/files#diff-e67c2e127c25d14625ad43c557f2aeb3357591fb8c965b6df8f641c880a2dc86

So this is why I will add the "skips consumer check" (once I get this PR reviewed)

prefix = "[",
postfix = "]")
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

new line

const val FIELD_EXTRA_PARAMETERS = "extraParameters"
const val DEFAULT_AUTHORITY = "https://login.microsoftonline.com/common"
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

some files missing EOF new line

const val FIELD_HOME_ACCOUNT_ID = "accountId"
const val FIELD_CLIENT_ID = "clientId"
const val FIELD_AUTHORITY = "authority"
const val FIELD_SCOPES = "scope"
Copy link
Contributor

Choose a reason for hiding this comment

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

scope or scopes?

if (shouldForceInteractive(getTokenRequest, additionalRequiredParams.getCanShowUi())) {
mergedExtraArgs.putAll(
performInteractiveAndSerialize(envelope, additionalRequiredParams, minBrokerProtocolVersion)
);
Copy link
Contributor

Choose a reason for hiding this comment

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

Not clear here. Why do you need to send it to broker?
Don't you have full result already?

|| redirectUri.equals("https://login.microsoftonline.com/common/oauth2/nativeclient"));
}

protected Context getContext() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Where is this one used?

}

/**
* Builds and validates the authority from the WebApp sender URL.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this method only for this webApp functionality? we can rename it to include that i think. Maybe rename parameter to mention web app

* @return The result string from the broker after the second phase completes.
* @throws BaseException If the interactive request payload is missing or token acquisition fails.
*/
private String handleInteractivePhase(@NonNull final String request,
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's mention webapp in method name

Copy link
Contributor

Choose a reason for hiding this comment

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

"interactivePhase" can be vague i think

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.

4 participants