diff --git a/src/vs/code/browser/workbench/workbench-dev.html b/src/vs/code/browser/workbench/workbench-dev.html
index 0142bb7f53d..992fead7e94 100644
--- a/src/vs/code/browser/workbench/workbench-dev.html
+++ b/src/vs/code/browser/workbench/workbench-dev.html
@@ -14,12 +14,12 @@
+
+
+
-
-
-
diff --git a/src/vs/code/browser/workbench/workbench.html b/src/vs/code/browser/workbench/workbench.html
index d56e3fdd36a..b4f0ef89ce1 100644
--- a/src/vs/code/browser/workbench/workbench.html
+++ b/src/vs/code/browser/workbench/workbench.html
@@ -14,6 +14,9 @@
+
+
+
diff --git a/src/vs/code/browser/workbench/workbench.ts b/src/vs/code/browser/workbench/workbench.ts
index 9b814729d31..39bba698acb 100644
--- a/src/vs/code/browser/workbench/workbench.ts
+++ b/src/vs/code/browser/workbench/workbench.ts
@@ -17,6 +17,24 @@ import { isStandalone } from 'vs/base/browser/browser';
import { localize } from 'vs/nls';
import { Schemas } from 'vs/base/common/network';
+function doCreateUri(path: string, queryValues: Map): URI {
+ let query: string | undefined = undefined;
+
+ if (queryValues) {
+ let index = 0;
+ queryValues.forEach((value, key) => {
+ if (!query) {
+ query = '';
+ }
+
+ const prefix = (index++ === 0) ? '' : '&';
+ query += `${prefix}${key}=${encodeURIComponent(value)}`;
+ });
+ }
+
+ return URI.parse(window.location.href).with({ path, query });
+}
+
interface ICredential {
service: string;
account: string;
@@ -68,7 +86,7 @@ class LocalStorageCredentialsProvider implements ICredentialsProvider {
}
async setPassword(service: string, account: string, password: string): Promise {
- this.deletePassword(service, account);
+ this.doDeletePassword(service, account);
this.credentials.push({ service, account, password });
@@ -76,6 +94,22 @@ class LocalStorageCredentialsProvider implements ICredentialsProvider {
}
async deletePassword(service: string, account: string): Promise {
+ const result = await this.doDeletePassword(service, account);
+
+ if (result) {
+ const queryValues: Map = new Map();
+ queryValues.set('logout', String(true));
+ queryValues.set('service', service);
+
+ await request({
+ url: doCreateUri('/auth/logout', queryValues).toString(true)
+ }, CancellationToken.None);
+ }
+
+ return result;
+ }
+
+ async doDeletePassword(service: string, account: string): Promise {
let found = false;
this._credentials = this.credentials.filter(credential => {
@@ -154,7 +188,7 @@ class PollingURLCallbackProvider extends Disposable implements IURLCallbackProvi
// Start to poll on the callback being fired
this.periodicFetchCallback(requestId, Date.now());
- return this.doCreateUri('/callback', queryValues);
+ return doCreateUri('/callback', queryValues);
}
private async periodicFetchCallback(requestId: string, startTime: number): Promise {
@@ -164,7 +198,7 @@ class PollingURLCallbackProvider extends Disposable implements IURLCallbackProvi
queryValues.set(PollingURLCallbackProvider.QUERY_KEYS.REQUEST_ID, requestId);
const result = await request({
- url: this.doCreateUri('/fetch-callback', queryValues).toString(true)
+ url: doCreateUri('/fetch-callback', queryValues).toString(true)
}, CancellationToken.None);
// Check for callback results
@@ -185,23 +219,6 @@ class PollingURLCallbackProvider extends Disposable implements IURLCallbackProvi
}
}
- private doCreateUri(path: string, queryValues: Map): URI {
- let query: string | undefined = undefined;
-
- if (queryValues) {
- let index = 0;
- queryValues.forEach((value, key) => {
- if (!query) {
- query = '';
- }
-
- const prefix = (index++ === 0) ? '' : '&';
- query += `${prefix}${key}=${encodeURIComponent(value)}`;
- });
- }
-
- return URI.parse(window.location.href).with({ path, query });
- }
}
class WorkspaceProvider implements IWorkspaceProvider {
diff --git a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts
index 34184c32e0c..6b079117b33 100644
--- a/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts
+++ b/src/vs/workbench/browser/parts/activitybar/activitybarActions.ts
@@ -200,7 +200,10 @@ export class AccountsActionViewItem extends ActivityActionViewItem {
return this.authenticationService.signOutOfAccount(sessionInfo.providerId, accountName);
});
- const actions = hasEmbedderAccountSession ? [manageExtensionsAction] : [manageExtensionsAction, signOutAction];
+ const actions = [manageExtensionsAction];
+ if (!hasEmbedderAccountSession || authenticationSession?.canSignOut) {
+ actions.push(signOutAction);
+ }
const menu = new SubmenuAction('activitybar.submenu', `${accountName} (${providerDisplayName})`, actions);
menus.push(menu);
diff --git a/src/vs/workbench/services/authentication/browser/authenticationService.ts b/src/vs/workbench/services/authentication/browser/authenticationService.ts
index db85f09a426..59f88d7cebf 100644
--- a/src/vs/workbench/services/authentication/browser/authenticationService.ts
+++ b/src/vs/workbench/services/authentication/browser/authenticationService.ts
@@ -26,7 +26,7 @@ import { IExtensionService } from 'vs/workbench/services/extensions/common/exten
export function getAuthenticationProviderActivationEvent(id: string): string { return `onAuthenticationRequest:${id}`; }
-export type AuthenticationSessionInfo = { readonly id: string, readonly accessToken: string, readonly providerId: string };
+export type AuthenticationSessionInfo = { readonly id: string, readonly accessToken: string, readonly providerId: string, readonly canSignOut?: boolean };
export async function getCurrentAuthenticationSessionInfo(environmentService: IWorkbenchEnvironmentService, productService: IProductService): Promise {
if (environmentService.options?.credentialsProvider) {
const authenticationSessionValue = await environmentService.options.credentialsProvider.getPassword(`${productService.urlProtocol}.login`, 'account');