I moved to a factory model because there was just so much that needed to be async.
I think the amount of async code will be reduced in the future as we remove some migration logic, but this makes sure we don't accidentally create instances without awaiting their initialization.
The point here is that the user already allowed access to the account for one client id, so that should just apply to any client id that is being used since:
* If we don't actually _have_ an auth token, the user will be asked to log in - so they will see a prompt as expected
* If we _do_ have an auth token, then we rely on extension auth access to gate access to the account
Fixes https://github.com/microsoft/vscode/issues/241526
* Force an update after acquiring a token interactively
This will make sure the account cache is up-to-date before the acquireTokenInteractive ends.
A greater fix is maybe turning the accounts cache to be a promise... bit this is the candidate fix for now.
Fixes#235327
* also delete event
We needed this workaround because MSAL was always trying to require a native module we never use.
I sent a PR to MSAL to rework their behavior and that has now been released and we pulled that in in https://github.com/microsoft/vscode/pull/234450
With the updated msal-node-extensions library, we no longer need to do this webpack logic.
MSAL node made `clearCache` synchronous 🎉 so we can safely depend on it for clearing the cache.
> Context: The default behavior of MSAL's internal cache is that it is a union with what's in the persistant cache (secret storage) but what _we_ want is that secret storage is the source of truth, so every time we receive an update to secret storage, we clear the in-memory cache to get the data from the persistant cache.
Also bumps msal-node-extensions while we're at it.
Bascally, we reach into the old location in secret storage and if we find sessions (with a refresh token) we seed that in the MSAL world.
We do this one time... unless they switch back to the old world and then switch to the new world.
This has two different behaviors depending on if the Broker is used:
* If the broker is not used, this does what you might expect. It makes it seem totally transparent to the user that something has changed. All sessions get migrated over and the user is still logged in to what they were previously.
* If the broker is used... you don't get automatically logged in _unless_ you have already logged in to that account at the OS level. So this helps skip the "VS Code access layer" outlined in `accountAccess.ts`. Not as good as the previous bullet, but this is the best we can do in the broker world.
In time, we can remove this migration along with the old way of doing things.
In a couple of builds [like this one](https://dev.azure.com/monacotools/Monaco/_build/results?buildId=305323&view=results) we have seen bad comparisons of `extension.js` in the Microsoft Auth extension:
> 2024-11-15T19:16:07.080Z electron-universal SHA for file Contents/Resources/app/extensions/microsoft-authentication/dist/extension.js does not match across builds a4db653e84d42a8cb4681a2274dffd34e0d7729cf14c0c4228b668778aa81c18!=6ff1bd8b8b51db2bff1d5f000625f0efe490a92eb282d0559aa904325d6cad68
Which is odd, considering there is no native dependencies used on macOS. The suspicion is that this is because of `keytar` which we have in the package.json using an odd `file:./path...`syntax to prevent it from installing normally since we don't use it.
The solution: additionally alias keytar in the webpack config so that the resolution is predictable.
This adopts the `NativeBrokerPlugin` provided by `@azure/msal-node-extensions` to provide the ability to use auth state from the OS, and show native auth dialogs instead of going to the browser.
This has several pieces:
* The adoption of the broker in the microsoft-authentication extension:
* Adding `NativeBrokerPlugin` to our PCAs
* Using the proposed handle API to pass the native window handle down to MSAL calls (btw, this API will change in a follow up PR)
* Adopting an AccountAccess layer to handle:
* giving the user control of which accounts VS Code uses
* an eventing layer so that auth state can be updated across multiple windows
* Getting the extension to build properly and only build what it really needs. This required several package.json/webpack hacks:
* Use a fake keytar since we don't use the feature in `@azure/msal-node-extensions` that uses keytar
* Use a fake dpapi layer since we don't use the feature in `@azure/msal-node-extensions` that uses it
* Ensure the msal runtime `.node` and `.dll` files are included in the bundle
* Get the VS Code build to allow a native node module in an extension: by having a list of native extensions that will be built in the "ci" part of the build - in other words when VS Code is building on the target platform
There are a couple of followups:
* Refactor the `handle` API to handle (heh) Auxiliary Windows https://github.com/microsoft/vscode/issues/233106
* Separate the call to `acquireTokenSilent` and `acquireTokenInteractive` and all the usage of this native node module into a separate process or maybe in Core... we'll see. Something to experiment with after we have something working. NEEDS FOLLOW UP ISSUE
Fixes https://github.com/microsoft/vscode/issues/229431
Now we will refresh tokens over time so extensions can cache auth sessions in memory and just need to listen to the event to decide when to refresh their caches.