Skip to content

Fix: WPJ's BrokerDiscovery cache crash due to shared predefined encryption key with MSAL, Fixes AB#3577391#3081

Open
rpdome wants to merge 10 commits intodevfrom
rapong/encryption
Open

Fix: WPJ's BrokerDiscovery cache crash due to shared predefined encryption key with MSAL, Fixes AB#3577391#3081
rpdome wants to merge 10 commits intodevfrom
rapong/encryption

Conversation

@rpdome
Copy link
Copy Markdown
Member

@rpdome rpdome commented Apr 14, 2026

AB#3577391

Problem

In Company Portal, AndroidAuthSdkStorageEncryptionManager reads from the global AuthenticationSettings.INSTANCE.getSecretKeyData() singleton. When CP sets a predefined key, WPJ's DeviceRegistrationClientApplication (which uses that same class as MSAL) inherits it and encrypts the active broker cache with it (U001 prefix). If WPJ later runs without the predefined key being set, decryption throws IllegalStateException — uncaught by EncryptedNameValueStorage.get() (which only catches ClientException) — crashing the app.

Specific trigger in Company Portal: DisableBrokerUseCase (added to the :auth process in their PR 6333837, July 2022) checks if the device is workplace joined via IsWorkplaceJoinedUseCaseDeviceRegistrationClientApplication. Since this runs in the :auth process, the MSAL predefined key is never set, so encryption/decryption of the active broker cache fails.

For context: The "predefined" key is a legacy ADAL pattern from when Android Keystore wasn't considered reliable — apps supplied their own encryption key. Company Portal has continued using this approach since then. The predefined key exists to protect token caches; DeviceRegistrationClientApplication only uses encrypted storage for the active broker cache (non-token), so the legacy key isn't needed here. This PR switches it to always use the Android KeyStore instead.

Long term wise, we should push Intune/CP to not invoke any APIs on :auth process - but our code should be resilient to how the key is set regardless.

Fix

  1. useKeystoreOnly mode — New constructor param on AndroidAuthSdkStorageEncryptionManager. When true, ignores predefined key from AuthenticationSettings, always encrypts with Android KeyStore.

  2. IllegalStateExceptionClientException — Missing predefined key now throws ClientException(DECRYPTION_FAILED), which EncryptedNameValueStorage.get() catches → returns null → cache miss → BrokerDiscoveryClient falls back to IPC → read the cached value from one of the broker apps -> self-heals.

  3. DeviceRegistrationClientApplication and BrokerAppsApi wired to keystore-only — via new AndroidPlatformComponentsFactory.createFromContextWithKeystoreOnlyEncryption(). MSAL behavior unchanged.

Changed files

  • AndroidAuthSdkStorageEncryptionManager.javauseKeystoreOnly param, ClientException instead of IllegalStateException
  • AndroidPlatformComponentsFactory.java — new createFromContextWithKeystoreOnlyEncryption()
  • DeviceRegistrationClientApplication.kt (common + broker) — use keystore-only factory
  • AndroidAuthSdkStorageEncryptionManagerTest.java — tests for new behavior
  • BrokerDiscoveryClientTests.kt — E2E: predefined-key cache → keystore-only read → IPC fallback → cache re-populated

@rpdome rpdome requested a review from a team as a code owner April 14, 2026 19:23
Copilot AI review requested due to automatic review settings April 14, 2026 19:23
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

Note

Copilot was unable to run its full agentic suite in this review.

This PR addresses a crash in WPJ/BrokerDiscovery caused by Company Portal setting a global MSAL predefined encryption key that later becomes unavailable, leading to unhandled decryption failures.

Changes:

  • Add a “keystore-only” mode to the Android storage encryption manager and surface missing-key decryption as ClientException(DECRYPTION_FAILED) instead of IllegalStateException.
  • Add a new platform components factory method to build components with keystore-only encryption and wire Device Registration to use it.
  • Add/extend tests, including an end-to-end test that validates IPC fallback and cache self-healing on decryption failure.

Reviewed changes

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

Show a summary per file
File Description
common/src/main/java/com/microsoft/identity/common/crypto/AndroidAuthSdkStorageEncryptionManager.java Adds keystore-only mode and throws ClientException on predefined-key decryption mismatch.
common/src/main/java/com/microsoft/identity/common/components/AndroidPlatformComponentsFactory.java Adds factory method to create platform components using keystore-only encryption.
common/src/main/java/com/microsoft/identity/deviceregistration/api/DeviceRegistrationClientApplication.kt Switches Device Registration to keystore-only platform components.
common/src/test/java/com/microsoft/identity/common/crypto/AndroidAuthSdkStorageEncryptionManagerTest.java Updates/extends tests for new exception behavior and keystore-only mode.
common/src/test/java/com/microsoft/identity/common/internal/activebrokerdiscovery/BrokerDiscoveryClientTests.kt Adds E2E test for decryption failure → cache miss → IPC fallback → cache repopulation.
common/src/test/java/com/microsoft/identity/common/crypto/MockData.java Exposes predefined key byte arrays for cross-test usage.

@github-actions
Copy link
Copy Markdown

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

Click here to Learn more.

@rpdome rpdome requested a review from a team as a code owner April 14, 2026 22:05
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 7 out of 7 changed files in this pull request and generated 6 comments.

rpdome and others added 2 commits April 14, 2026 15:07
…oidAuthSdkStorageEncryptionManagerTest.java

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…AndroidPlatformComponentsFactory.java

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@rpdome rpdome changed the title Fix: WPJ's BrokerDiscovery crash due to shared encryption key with MSAL Fix: WPJ's BrokerDiscovery cache crash due to shared encryption key with MSAL Apr 14, 2026
@rpdome rpdome changed the title Fix: WPJ's BrokerDiscovery cache crash due to shared encryption key with MSAL Fix: WPJ's BrokerDiscovery cache crash due to shared predefined encryption key with MSAL Apr 14, 2026
@rpdome rpdome requested a review from Copilot April 14, 2026 22:22
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 7 out of 7 changed files in this pull request and generated 3 comments.

@github-actions
Copy link
Copy Markdown

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

@github-actions
Copy link
Copy Markdown

❌ Invalid work item number: AB#3577391

###. Work item number must be a valid integer.

Click here to learn more.

@github-actions github-actions bot changed the title Fix: WPJ's BrokerDiscovery cache crash due to shared predefined encryption key with MSAL Fix: WPJ's BrokerDiscovery cache crash due to shared predefined encryption key with MSAL, Fixes AB#3577391 Apr 15, 2026
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.

Left a comment

@rpdome
Copy link
Copy Markdown
Member Author

rpdome commented Apr 17, 2026

@copilot resolve the merge conflicts in this pull request

# Conflicts:
#	changelog.txt

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

Copilot AI commented Apr 17, 2026

@copilot resolve the merge conflicts in this pull request

Merged origin/dev into the branch in commit 2234b3c. The only conflict was in changelog.txt (both sides added a vNext entry) — both entries are preserved.

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