mirror of
https://github.com/microsoft/vscode.git
synced 2025-12-28 06:31:58 +00:00
Enable the broker in macOS (#261148)
* Enable the broker in macOS Fixes https://github.com/microsoft/vscode/issues/260158 * for testing * better globbing * guh * guh * delete * log it all * let's just log everything * Only do on supported OS/Arches * Add a console.log * look at VSCODE_ARCH * add msal files * add entitlement maybe here * actually it's probably here * build: bundle msal libs for x64 and arm64 * revert that * try again * try adding $(AppIdentifierPrefix) * temp: add debuggee entitlements * bump msal and pass in redirect uri on macOS * revert entitlement files * forgot the .helper * Allow PII for the output channel only * use unsigned option --------- Co-authored-by: deepak1556 <hop2deep@gmail.com>
This commit is contained in:
parent
543ea0e80d
commit
da3cf78129
@ -29,7 +29,7 @@ async function main(buildDir) {
|
||||
'**/Credits.rtf',
|
||||
'**/policies/{*.mobileconfig,**/*.plist}',
|
||||
// TODO: Should we consider expanding this to other files in this area?
|
||||
'**/node_modules/@parcel/node-addon-api/nothing.target.mk'
|
||||
'**/node_modules/@parcel/node-addon-api/nothing.target.mk',
|
||||
];
|
||||
await (0, vscode_universal_bundler_1.makeUniversalApp)({
|
||||
x64AppPath,
|
||||
@ -38,7 +38,7 @@ async function main(buildDir) {
|
||||
outAppPath,
|
||||
force: true,
|
||||
mergeASARs: true,
|
||||
x64ArchFiles: '*/kerberos.node',
|
||||
x64ArchFiles: '{*/kerberos.node,**/extensions/microsoft-authentication/dist/libmsalruntime.dylib,**/extensions/microsoft-authentication/dist/msal-node-runtime.node}',
|
||||
filesToSkipComparison: (file) => {
|
||||
for (const expected of filesToSkip) {
|
||||
if ((0, minimatch_1.default)(file, expected)) {
|
||||
|
||||
@ -30,7 +30,7 @@ async function main(buildDir?: string) {
|
||||
'**/Credits.rtf',
|
||||
'**/policies/{*.mobileconfig,**/*.plist}',
|
||||
// TODO: Should we consider expanding this to other files in this area?
|
||||
'**/node_modules/@parcel/node-addon-api/nothing.target.mk'
|
||||
'**/node_modules/@parcel/node-addon-api/nothing.target.mk',
|
||||
];
|
||||
|
||||
await makeUniversalApp({
|
||||
@ -40,7 +40,7 @@ async function main(buildDir?: string) {
|
||||
outAppPath,
|
||||
force: true,
|
||||
mergeASARs: true,
|
||||
x64ArchFiles: '*/kerberos.node',
|
||||
x64ArchFiles: '{*/kerberos.node,**/extensions/microsoft-authentication/dist/libmsalruntime.dylib,**/extensions/microsoft-authentication/dist/msal-node-runtime.node}',
|
||||
filesToSkipComparison: (file: string) => {
|
||||
for (const expected of filesToSkip) {
|
||||
if (minimatch(file, expected)) {
|
||||
|
||||
@ -11,6 +11,7 @@ const assert_1 = __importDefault(require("assert"));
|
||||
const path_1 = __importDefault(require("path"));
|
||||
const promises_1 = require("fs/promises");
|
||||
const cross_spawn_promise_1 = require("@malept/cross-spawn-promise");
|
||||
const minimatch_1 = __importDefault(require("minimatch"));
|
||||
const MACHO_PREFIX = 'Mach-O ';
|
||||
const MACHO_64_MAGIC_LE = 0xfeedfacf;
|
||||
const MACHO_UNIVERSAL_MAGIC_LE = 0xbebafeca;
|
||||
@ -22,6 +23,15 @@ const MACHO_X86_64_CPU_TYPE = new Set([
|
||||
0x07000001,
|
||||
0x01000007,
|
||||
]);
|
||||
// Files to skip during architecture validation
|
||||
const FILES_TO_SKIP = [
|
||||
// MSAL runtime files are only present in ARM64 builds
|
||||
'**/extensions/microsoft-authentication/dist/libmsalruntime.dylib',
|
||||
'**/extensions/microsoft-authentication/dist/msal-node-runtime.node',
|
||||
];
|
||||
function isFileSkipped(file) {
|
||||
return FILES_TO_SKIP.some(pattern => (0, minimatch_1.default)(file, pattern));
|
||||
}
|
||||
async function read(file, buf, offset, length, position) {
|
||||
let filehandle;
|
||||
try {
|
||||
@ -109,11 +119,11 @@ const archToCheck = process.argv[2];
|
||||
(0, assert_1.default)(process.env['APP_PATH'], 'APP_PATH not set');
|
||||
(0, assert_1.default)(archToCheck === 'x64' || archToCheck === 'arm64' || archToCheck === 'universal', `Invalid architecture ${archToCheck} to check`);
|
||||
checkMachOFiles(process.env['APP_PATH'], archToCheck).then(invalidFiles => {
|
||||
if (invalidFiles.length > 0) {
|
||||
console.error('\x1b[31mThe following files are built for the wrong architecture:\x1b[0m');
|
||||
for (const file of invalidFiles) {
|
||||
console.error(`\x1b[31m${file}\x1b[0m`);
|
||||
}
|
||||
// Filter out files that should be skipped
|
||||
const actualInvalidFiles = invalidFiles.filter(file => !isFileSkipped(file));
|
||||
if (actualInvalidFiles.length > 0) {
|
||||
console.error('\x1b[31mThese files are built for the wrong architecture:\x1b[0m');
|
||||
actualInvalidFiles.forEach(file => console.error(`\x1b[31m${file}\x1b[0m`));
|
||||
process.exit(1);
|
||||
}
|
||||
else {
|
||||
|
||||
@ -7,6 +7,7 @@ import assert from 'assert';
|
||||
import path from 'path';
|
||||
import { open, stat, readdir, realpath } from 'fs/promises';
|
||||
import { spawn, ExitCodeError } from '@malept/cross-spawn-promise';
|
||||
import minimatch from 'minimatch';
|
||||
|
||||
const MACHO_PREFIX = 'Mach-O ';
|
||||
const MACHO_64_MAGIC_LE = 0xfeedfacf;
|
||||
@ -20,6 +21,17 @@ const MACHO_X86_64_CPU_TYPE = new Set([
|
||||
0x01000007,
|
||||
]);
|
||||
|
||||
// Files to skip during architecture validation
|
||||
const FILES_TO_SKIP = [
|
||||
// MSAL runtime files are only present in ARM64 builds
|
||||
'**/extensions/microsoft-authentication/dist/libmsalruntime.dylib',
|
||||
'**/extensions/microsoft-authentication/dist/msal-node-runtime.node',
|
||||
];
|
||||
|
||||
function isFileSkipped(file: string): boolean {
|
||||
return FILES_TO_SKIP.some(pattern => minimatch(file, pattern));
|
||||
}
|
||||
|
||||
async function read(file: string, buf: Buffer, offset: number, length: number, position: number) {
|
||||
let filehandle;
|
||||
try {
|
||||
@ -105,11 +117,11 @@ const archToCheck = process.argv[2];
|
||||
assert(process.env['APP_PATH'], 'APP_PATH not set');
|
||||
assert(archToCheck === 'x64' || archToCheck === 'arm64' || archToCheck === 'universal', `Invalid architecture ${archToCheck} to check`);
|
||||
checkMachOFiles(process.env['APP_PATH'], archToCheck).then(invalidFiles => {
|
||||
if (invalidFiles.length > 0) {
|
||||
console.error('\x1b[31mThe following files are built for the wrong architecture:\x1b[0m');
|
||||
for (const file of invalidFiles) {
|
||||
console.error(`\x1b[31m${file}\x1b[0m`);
|
||||
}
|
||||
// Filter out files that should be skipped
|
||||
const actualInvalidFiles = invalidFiles.filter(file => !isFileSkipped(file));
|
||||
if (actualInvalidFiles.length > 0) {
|
||||
console.error('\x1b[31mThese files are built for the wrong architecture:\x1b[0m');
|
||||
actualInvalidFiles.forEach(file => console.error(`\x1b[31m${file}\x1b[0m`));
|
||||
process.exit(1);
|
||||
} else {
|
||||
console.log('\x1b[32mAll files are valid\x1b[0m');
|
||||
|
||||
@ -8,6 +8,25 @@ import CopyWebpackPlugin from 'copy-webpack-plugin';
|
||||
import path from 'path';
|
||||
|
||||
const isWindows = process.platform === 'win32';
|
||||
const windowsArches = ['x64'];
|
||||
const isMacOS = process.platform === 'darwin';
|
||||
const macOSArches = ['arm64'];
|
||||
|
||||
const arch = process.arch;
|
||||
console.log(`Building Microsoft Authentication Extension for ${process.platform} (${arch})`);
|
||||
|
||||
const plugins = [...nodePlugins(import.meta.dirname)];
|
||||
if ((isWindows && windowsArches.includes(arch)) || (isMacOS && macOSArches.includes(arch))) {
|
||||
plugins.push(new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
// The native files we need to ship with the extension
|
||||
from: '**/dist/(lib|)msal*.(node|dll|dylib)',
|
||||
to: '[name][ext]'
|
||||
}
|
||||
]
|
||||
}));
|
||||
}
|
||||
|
||||
export default withDefaults({
|
||||
context: import.meta.dirname,
|
||||
@ -25,18 +44,5 @@ export default withDefaults({
|
||||
'keytar': path.resolve(import.meta.dirname, 'packageMocks', 'keytar', 'index.js')
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
...nodePlugins(import.meta.dirname),
|
||||
new CopyWebpackPlugin({
|
||||
patterns: [
|
||||
{
|
||||
// The native files we need to ship with the extension
|
||||
from: '**/dist/msal*.(node|dll)',
|
||||
to: '[name][ext]',
|
||||
// These will only be present on Windows for now
|
||||
noErrorOnMissing: !isWindows
|
||||
}
|
||||
]
|
||||
})
|
||||
]
|
||||
plugins
|
||||
});
|
||||
|
||||
@ -10,8 +10,8 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/ms-rest-azure-env": "^2.0.0",
|
||||
"@azure/msal-node": "^2.16.2",
|
||||
"@azure/msal-node-extensions": "^1.5.0",
|
||||
"@azure/msal-node": "^3.7.3",
|
||||
"@azure/msal-node-extensions": "^1.5.22",
|
||||
"@vscode/extension-telemetry": "^0.9.8",
|
||||
"keytar": "file:./packageMocks/keytar",
|
||||
"vscode-tas-client": "^0.1.84"
|
||||
@ -33,21 +33,21 @@
|
||||
"integrity": "sha512-dG76W7ElfLi+fbTjnZVGj+M9e0BIEJmRxU6fHaUQ12bZBe8EJKYb2GV50YWNaP2uJiVQ5+7nXEVj1VN1UQtaEw=="
|
||||
},
|
||||
"node_modules/@azure/msal-common": {
|
||||
"version": "14.16.0",
|
||||
"resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.16.0.tgz",
|
||||
"integrity": "sha512-1KOZj9IpcDSwpNiQNjt0jDYZpQvNZay7QAEi/5DLubay40iGYtLzya/jbjRPLyOTZhEKyL1MzPuw2HqBCjceYA==",
|
||||
"version": "15.12.0",
|
||||
"resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-15.12.0.tgz",
|
||||
"integrity": "sha512-4ucXbjVw8KJ5QBgnGJUeA07c8iznwlk5ioHIhI4ASXcXgcf2yRFhWzYOyWg/cI49LC9ekpFJeQtO3zjDTbl6TQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/msal-node": {
|
||||
"version": "2.16.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.16.2.tgz",
|
||||
"integrity": "sha512-An7l1hEr0w1HMMh1LU+rtDtqL7/jw74ORlc9Wnh06v7TU/xpG39/Zdr1ZJu3QpjUfKJ+E0/OXMW8DRSWTlh7qQ==",
|
||||
"version": "3.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-3.7.3.tgz",
|
||||
"integrity": "sha512-MoJxkKM/YpChfq4g2o36tElyzNUMG8mfD6u8NbuaPAsqfGpaw249khAcJYNoIOigUzRw45OjXCOrexE6ImdUxg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/msal-common": "14.16.0",
|
||||
"@azure/msal-common": "15.12.0",
|
||||
"jsonwebtoken": "^9.0.0",
|
||||
"uuid": "^8.3.0"
|
||||
},
|
||||
@ -56,14 +56,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/msal-node-extensions": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@azure/msal-node-extensions/-/msal-node-extensions-1.5.0.tgz",
|
||||
"integrity": "sha512-UfEyh2xmJHKH64zPS/SbN1bd9adV4ZWGp1j2OSwIuhVraqpUXyXZ1LpDpiUqg/peTgLLtx20qrHOzYT0kKzmxQ==",
|
||||
"version": "1.5.22",
|
||||
"resolved": "https://registry.npmjs.org/@azure/msal-node-extensions/-/msal-node-extensions-1.5.22.tgz",
|
||||
"integrity": "sha512-pdHcoyxmCszjXhc59jZ+7WKH0ZqebH0ZVvKlBwFD57TQzAOnXPS6q76/dsVO/Y7EXAlvkoCmcebNc6eP4cQulA==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@azure/msal-common": "14.16.0",
|
||||
"@azure/msal-node-runtime": "^0.17.1",
|
||||
"@azure/msal-common": "15.12.0",
|
||||
"@azure/msal-node-runtime": "^0.19.0",
|
||||
"keytar": "^7.8.0"
|
||||
},
|
||||
"engines": {
|
||||
@ -71,9 +71,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@azure/msal-node-runtime": {
|
||||
"version": "0.18.2",
|
||||
"resolved": "https://registry.npmjs.org/@azure/msal-node-runtime/-/msal-node-runtime-0.18.2.tgz",
|
||||
"integrity": "sha512-v45fyBQp80BrjZAeGJXl+qggHcbylQiFBihr0ijO2eniDCW9tz5TZBKYsqzH06VuiRaVG/Sa0Hcn4pjhJqFSTw==",
|
||||
"version": "0.19.4",
|
||||
"resolved": "https://registry.npmjs.org/@azure/msal-node-runtime/-/msal-node-runtime-0.19.4.tgz",
|
||||
"integrity": "sha512-v90QdV/VKG6gvHx2bQp82yRCJ8IGG7OOk6gDQgbKvoHtOs7mSEz2CIqWydUpwCryJkUwgNfgMPAMoGhe/a4fOw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
|
||||
@ -144,15 +144,12 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@azure/ms-rest-azure-env": "^2.0.0",
|
||||
"@azure/msal-node": "^2.16.2",
|
||||
"@azure/msal-node-extensions": "^1.5.0",
|
||||
"@azure/msal-node": "^3.7.3",
|
||||
"@azure/msal-node-extensions": "^1.5.22",
|
||||
"@vscode/extension-telemetry": "^0.9.8",
|
||||
"keytar": "file:./packageMocks/keytar",
|
||||
"vscode-tas-client": "^0.1.84"
|
||||
},
|
||||
"overrides": {
|
||||
"@azure/msal-node-runtime": "^0.18.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/microsoft/vscode.git"
|
||||
|
||||
19
extensions/microsoft-authentication/src/common/config.ts
Normal file
19
extensions/microsoft-authentication/src/common/config.ts
Normal file
@ -0,0 +1,19 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
export interface IConfig {
|
||||
// The macOS broker redirect URI which is dependent on the bundle identifier of the signed app.
|
||||
// Other platforms do not require a redirect URI to be set. For unsigned apps, the unsigned
|
||||
// format can be used.
|
||||
// Example formats:
|
||||
// msauth.com.msauth.unsignedapp://auth or msauth.<bundleId>://auth
|
||||
macOSBrokerRedirectUri: string;
|
||||
}
|
||||
|
||||
export const Config: IConfig = {
|
||||
// This is replaced in the build with the correct bundle id for that distro.
|
||||
macOSBrokerRedirectUri: 'msauth.com.msauth.unsignedapp://auth'
|
||||
};
|
||||
@ -19,13 +19,7 @@ export class MsalLoggerOptions {
|
||||
return this._toMsalLogLevel(env.logLevel);
|
||||
}
|
||||
|
||||
loggerCallback(level: MsalLogLevel, message: string, containsPii: boolean): void {
|
||||
if (containsPii) {
|
||||
// TODO: Should we still log the message if it contains PII? It's just going to
|
||||
// an output channel that doesn't leave the machine.
|
||||
this._output.debug('Skipped logging message because it may contain PII');
|
||||
return;
|
||||
}
|
||||
loggerCallback(level: MsalLogLevel, message: string, _containsPii: boolean): void {
|
||||
|
||||
// Log to output channel one level lower than the MSAL log level
|
||||
switch (level) {
|
||||
|
||||
@ -14,6 +14,7 @@ export interface ICachedPublicClientApplication {
|
||||
removeAccount(account: AccountInfo): Promise<void>;
|
||||
accounts: AccountInfo[];
|
||||
clientId: string;
|
||||
isBrokerAvailable: Readonly<boolean>;
|
||||
}
|
||||
|
||||
export interface ICachedPublicClientApplicationManager {
|
||||
|
||||
@ -3,6 +3,7 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { AuthError } from '@azure/msal-node';
|
||||
import TelemetryReporter, { TelemetryEventProperties } from '@vscode/extension-telemetry';
|
||||
import { IExperimentationTelemetry } from 'vscode-tas-client';
|
||||
|
||||
@ -75,20 +76,36 @@ export class MicrosoftAuthenticationTelemetryReporter implements IExperimentatio
|
||||
}
|
||||
|
||||
sendTelemetryErrorEvent(error: unknown): void {
|
||||
const errorMessage = error instanceof Error ? error.message : String(error);
|
||||
const errorStack = error instanceof Error ? error.stack : undefined;
|
||||
const errorName = error instanceof Error ? error.name : undefined;
|
||||
let errorMessage: string | undefined;
|
||||
let errorName: string | undefined;
|
||||
let errorCode: string | undefined;
|
||||
let errorCorrelationId: string | undefined;
|
||||
if (typeof error === 'string') {
|
||||
errorMessage = error;
|
||||
} else {
|
||||
const authError: AuthError = error as any;
|
||||
// don't set error message or stack because it contains PII
|
||||
errorCode = authError.errorCode;
|
||||
errorCorrelationId = authError.correlationId;
|
||||
errorName = authError.name;
|
||||
}
|
||||
|
||||
/* __GDPR__
|
||||
"msalError" : {
|
||||
"owner": "TylerLeonhardt",
|
||||
"comment": "Used to determine how often users run into issues with the login flow.",
|
||||
"errorMessage": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The error message from the exception." },
|
||||
"errorStack": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The stack trace from the exception." },
|
||||
"errorName": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The name of the error." }
|
||||
"errorMessage": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The error message." },
|
||||
"errorName": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The name of the error." },
|
||||
"errorCode": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The error code." },
|
||||
"errorCorrelationId": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The error correlation id." }
|
||||
}
|
||||
*/
|
||||
this._telemetryReporter.sendTelemetryErrorEvent('msalError', { errorMessage, errorStack, errorName });
|
||||
this._telemetryReporter.sendTelemetryErrorEvent('msalError', {
|
||||
errorMessage,
|
||||
errorName,
|
||||
errorCode,
|
||||
errorCorrelationId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -213,6 +213,7 @@ export class MsalAuthProvider implements AuthenticationProvider {
|
||||
extensionHost: isNodeEnvironment
|
||||
? this._context.extension.extensionKind === ExtensionKind.UI ? ExtensionHost.Local : ExtensionHost.Remote
|
||||
: ExtensionHost.WebWorker,
|
||||
isBrokerSupported: cachedPca.isBrokerAvailable
|
||||
});
|
||||
|
||||
const authority = new URL(scopeData.tenant, this._env.activeDirectoryEndpointUrl).toString();
|
||||
@ -342,6 +343,7 @@ export class MsalAuthProvider implements AuthenticationProvider {
|
||||
extensionHost: isNodeEnvironment
|
||||
? this._context.extension.extensionKind === ExtensionKind.UI ? ExtensionHost.Local : ExtensionHost.Remote
|
||||
: ExtensionHost.WebWorker,
|
||||
isBrokerSupported: cachedPca.isBrokerAvailable
|
||||
});
|
||||
|
||||
const authority = new URL(scopeData.tenant, this._env.activeDirectoryEndpointUrl).toString();
|
||||
|
||||
@ -24,7 +24,7 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica
|
||||
private readonly _secretStorageCachePlugin: SecretStorageCachePlugin;
|
||||
|
||||
// Broker properties
|
||||
private readonly _isBrokerAvailable: boolean;
|
||||
readonly isBrokerAvailable: boolean;
|
||||
|
||||
//#region Events
|
||||
|
||||
@ -51,14 +51,16 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica
|
||||
|
||||
const loggerOptions = new MsalLoggerOptions(_logger, telemetryReporter);
|
||||
const nativeBrokerPlugin = new NativeBrokerPlugin();
|
||||
this._isBrokerAvailable = nativeBrokerPlugin.isBrokerAvailable;
|
||||
this.isBrokerAvailable = nativeBrokerPlugin.isBrokerAvailable;
|
||||
this._pca = new PublicClientApplication({
|
||||
auth: { clientId: _clientId },
|
||||
system: {
|
||||
loggerOptions: {
|
||||
correlationId: _clientId,
|
||||
loggerCallback: (level, message, containsPii) => loggerOptions.loggerCallback(level, message, containsPii),
|
||||
logLevel: LogLevel.Trace
|
||||
logLevel: LogLevel.Trace,
|
||||
// Enable PII logging since it will only go to the output channel
|
||||
piiLoggingEnabled: true
|
||||
}
|
||||
},
|
||||
broker: { nativeBrokerPlugin },
|
||||
@ -110,7 +112,7 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica
|
||||
);
|
||||
if (fiveMinutesBefore < new Date()) {
|
||||
this._logger.debug(`[acquireTokenSilent] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}] [${request.account.username}] id token is expired or about to expire. Forcing refresh...`);
|
||||
const newRequest = this._isBrokerAvailable
|
||||
const newRequest = this.isBrokerAvailable
|
||||
// HACK: Broker doesn't support forceRefresh so we need to pass in claims which will force a refresh
|
||||
? { ...request, claims: request.claims ?? '{ "id_token": {}}' }
|
||||
: { ...request, forceRefresh: true };
|
||||
@ -128,7 +130,7 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica
|
||||
|
||||
// HACK: Only for the Broker we try one more time with different claims to force a refresh. Why? We've seen the Broker caching tokens by the claims requested, thus
|
||||
// there has been a situation where both tokens are expired.
|
||||
if (this._isBrokerAvailable) {
|
||||
if (this.isBrokerAvailable) {
|
||||
this._logger.error(`[acquireTokenSilent] [${this._clientId}] [${request.authority}] [${request.scopes.join(' ')}] [${request.account.username}] forcing refresh with different claims...`);
|
||||
const newRequest = { ...request, claims: request.claims ?? '{ "access_token": {}}' };
|
||||
result = await this._sequencer.queue(() => this._pca.acquireTokenSilent(newRequest));
|
||||
@ -166,20 +168,25 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica
|
||||
title: l10n.t('Signing in to Microsoft...')
|
||||
},
|
||||
(_process, token) => this._sequencer.queue(async () => {
|
||||
const result = await raceCancellationAndTimeoutError(
|
||||
this._pca.acquireTokenInteractive(request),
|
||||
token,
|
||||
1000 * 60 * 5
|
||||
);
|
||||
if (this._isBrokerAvailable) {
|
||||
await this._accountAccess.setAllowedAccess(result.account!, true);
|
||||
try {
|
||||
const result = await raceCancellationAndTimeoutError(
|
||||
this._pca.acquireTokenInteractive(request),
|
||||
token,
|
||||
1000 * 60 * 5
|
||||
);
|
||||
if (this.isBrokerAvailable) {
|
||||
await this._accountAccess.setAllowedAccess(result.account!, true);
|
||||
}
|
||||
// Force an update so that the account cache is updated.
|
||||
// TODO:@TylerLeonhardt The problem is, we use the sequencer for
|
||||
// change events but we _don't_ use it for the accounts cache.
|
||||
// We should probably use it for the accounts cache as well.
|
||||
await this._update();
|
||||
return result;
|
||||
} catch (error) {
|
||||
this._logger.error(`[acquireTokenInteractive] [${this._clientId}] [${request.authority}] [${request.scopes?.join(' ')}] error: ${error}`);
|
||||
throw error;
|
||||
}
|
||||
// Force an update so that the account cache is updated.
|
||||
// TODO:@TylerLeonhardt The problem is, we use the sequencer for
|
||||
// change events but we _don't_ use it for the accounts cache.
|
||||
// We should probably use it for the accounts cache as well.
|
||||
await this._update();
|
||||
return result;
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -203,7 +210,7 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica
|
||||
});
|
||||
if (result) {
|
||||
// this._setupRefresh(result);
|
||||
if (this._isBrokerAvailable && result.account) {
|
||||
if (this.isBrokerAvailable && result.account) {
|
||||
await this._accountAccess.setAllowedAccess(result.account, true);
|
||||
}
|
||||
}
|
||||
@ -211,14 +218,14 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica
|
||||
}
|
||||
|
||||
removeAccount(account: AccountInfo): Promise<void> {
|
||||
if (this._isBrokerAvailable) {
|
||||
if (this.isBrokerAvailable) {
|
||||
return this._accountAccess.setAllowedAccess(account, false);
|
||||
}
|
||||
return this._sequencer.queue(() => this._pca.getTokenCache().removeAccount(account));
|
||||
}
|
||||
|
||||
private _registerOnSecretStorageChanged() {
|
||||
if (this._isBrokerAvailable) {
|
||||
if (this.isBrokerAvailable) {
|
||||
return this._accountAccess.onDidAccountAccessChange(() => this._sequencer.queue(() => this._update()));
|
||||
}
|
||||
return this._secretStorageCachePlugin.onDidChange(() => this._sequencer.queue(() => this._update()));
|
||||
@ -258,7 +265,7 @@ export class CachedPublicClientApplication implements ICachedPublicClientApplica
|
||||
// Clear in-memory cache so we know we're getting account data from the SecretStorage
|
||||
this._pca.clearCache();
|
||||
let after = await this._pca.getAllAccounts();
|
||||
if (this._isBrokerAvailable) {
|
||||
if (this.isBrokerAvailable) {
|
||||
after = after.filter(a => this._accountAccess.isAllowedAccess(a));
|
||||
}
|
||||
this._accounts = after;
|
||||
|
||||
@ -9,8 +9,9 @@ import { ICachedPublicClientApplication } from '../common/publicClientCache';
|
||||
import { UriHandlerLoopbackClient } from '../common/loopbackClientAndOpener';
|
||||
import { UriEventHandler } from '../UriEventHandler';
|
||||
import { loopbackTemplate } from './loopbackTemplate';
|
||||
import { Config } from '../common/config';
|
||||
|
||||
const redirectUri = 'https://vscode.dev/redirect';
|
||||
const DEFAULT_REDIRECT_URI = 'https://vscode.dev/redirect';
|
||||
|
||||
export const enum ExtensionHost {
|
||||
WebWorker,
|
||||
@ -49,6 +50,10 @@ class DefaultLoopbackFlow implements IMsalFlow {
|
||||
|
||||
async trigger({ cachedPca, authority, scopes, claims, loginHint, windowHandle, logger }: IMsalFlowTriggerOptions): Promise<AuthenticationResult> {
|
||||
logger.info('Trying default msal flow...');
|
||||
let redirectUri: string | undefined;
|
||||
if (cachedPca.isBrokerAvailable && process.platform === 'darwin') {
|
||||
redirectUri = Config.macOSBrokerRedirectUri;
|
||||
}
|
||||
return await cachedPca.acquireTokenInteractive({
|
||||
openBrowser: async (url: string) => { await env.openExternal(Uri.parse(url)); },
|
||||
scopes,
|
||||
@ -58,7 +63,8 @@ class DefaultLoopbackFlow implements IMsalFlow {
|
||||
loginHint,
|
||||
prompt: loginHint ? undefined : 'select_account',
|
||||
windowHandle,
|
||||
claims
|
||||
claims,
|
||||
redirectUri
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -72,7 +78,11 @@ class UrlHandlerFlow implements IMsalFlow {
|
||||
|
||||
async trigger({ cachedPca, authority, scopes, claims, loginHint, windowHandle, logger, uriHandler }: IMsalFlowTriggerOptions): Promise<AuthenticationResult> {
|
||||
logger.info('Trying protocol handler flow...');
|
||||
const loopbackClient = new UriHandlerLoopbackClient(uriHandler, redirectUri, logger);
|
||||
const loopbackClient = new UriHandlerLoopbackClient(uriHandler, DEFAULT_REDIRECT_URI, logger);
|
||||
let redirectUri: string | undefined;
|
||||
if (cachedPca.isBrokerAvailable && process.platform === 'darwin') {
|
||||
redirectUri = Config.macOSBrokerRedirectUri;
|
||||
}
|
||||
return await cachedPca.acquireTokenInteractive({
|
||||
openBrowser: (url: string) => loopbackClient.openBrowser(url),
|
||||
scopes,
|
||||
@ -81,7 +91,8 @@ class UrlHandlerFlow implements IMsalFlow {
|
||||
loginHint,
|
||||
prompt: loginHint ? undefined : 'select_account',
|
||||
windowHandle,
|
||||
claims
|
||||
claims,
|
||||
redirectUri
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -93,10 +104,12 @@ const allFlows: IMsalFlow[] = [
|
||||
|
||||
export interface IMsalFlowQuery {
|
||||
extensionHost: ExtensionHost;
|
||||
isBrokerSupported: boolean;
|
||||
}
|
||||
|
||||
export function getMsalFlows(query: IMsalFlowQuery): IMsalFlow[] {
|
||||
return allFlows.filter(flow => {
|
||||
const flows = [];
|
||||
for (const flow of allFlows) {
|
||||
let useFlow: boolean = true;
|
||||
switch (query.extensionHost) {
|
||||
case ExtensionHost.Remote:
|
||||
@ -106,6 +119,13 @@ export function getMsalFlows(query: IMsalFlowQuery): IMsalFlow[] {
|
||||
useFlow &&= flow.options.supportsWebWorkerExtensionHost;
|
||||
break;
|
||||
}
|
||||
return useFlow;
|
||||
});
|
||||
if (useFlow) {
|
||||
flows.push(flow);
|
||||
if (query.isBrokerSupported) {
|
||||
// If broker is supported, only use the first valid flow
|
||||
return flows;
|
||||
}
|
||||
}
|
||||
}
|
||||
return flows;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user