diff --git a/src/vs/platform/auth/common/auth.css b/src/vs/platform/auth/common/auth.css
new file mode 100644
index 0000000000000..e87a6372763f5
--- /dev/null
+++ b/src/vs/platform/auth/common/auth.css
@@ -0,0 +1,100 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+html {
+ height: 100%;
+}
+
+body {
+ box-sizing: border-box;
+ min-height: 100%;
+ margin: 0;
+ padding: 15px 30px;
+ display: flex;
+ flex-direction: column;
+ color: white;
+ font-family: "Segoe UI","Helvetica Neue","Helvetica",Arial,sans-serif;
+ background-color: #373277;
+}
+
+.branding {
+ background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+PGRlZnM+PHN0eWxlPi5pY29uLWNhbnZhcy10cmFuc3BhcmVudHtmaWxsOiNmNmY2ZjY7b3BhY2l0eTowO30uaWNvbi13aGl0ZXtmaWxsOiNmZmY7fTwvc3R5bGU+PC9kZWZzPjx0aXRsZT5CcmFuZFZpc3VhbFN0dWRpb0NvZGUyMDE3UlRXXzI0eF93aGl0ZV8yNHg8L3RpdGxlPjxwYXRoIGNsYXNzPSJpY29uLWNhbnZhcy10cmFuc3BhcmVudCIgZD0iTTI0LDBWMjRIMFYwWiIvPjxwYXRoIGNsYXNzPSJpY29uLXdoaXRlIiBkPSJNMjQsMi41VjIxLjVMMTgsMjQsMCwxOC41di0uNTYxbDE4LDEuNTQ1VjBaTTEsMTMuMTExLDQuMzg1LDEwLDEsNi44ODlsMS40MTgtLjgyN0w1Ljg1Myw4LjY1LDEyLDNsMywxLjQ1NlYxNS41NDRMMTIsMTcsNS44NTMsMTEuMzUsMi40MTksMTMuOTM5Wk03LjY0NCwxMCwxMiwxMy4yODNWNi43MTdaIi8+PC9zdmc+");
+ background-size: 24px;
+ background-repeat: no-repeat;
+ background-position: left 50%;
+ padding-left: 36px;
+ font-size: 20px;
+ letter-spacing: -0.04rem;
+ font-weight: 400;
+ color: white;
+ text-decoration: none;
+}
+
+.message-container {
+ flex-grow: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin: 0 30px;
+}
+
+.message {
+ font-weight: 300;
+ font-size: 1.3rem;
+}
+
+body.error .message {
+ display: none;
+}
+
+body.error .error-message {
+ display: block;
+}
+
+.error-message {
+ display: none;
+ font-weight: 300;
+ font-size: 1.3rem;
+}
+
+.error-text {
+ color: red;
+ font-size: 1rem;
+}
+
+@font-face {
+ font-family: 'Segoe UI';
+ src: url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/light/latest.eot"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/light/latest.eot?#iefix") format("embedded-opentype");
+ src: local("Segoe UI Light"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/light/latest.woff2") format("woff2"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/light/latest.woff") format("woff"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/light/latest.ttf") format("truetype"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/light/latest.svg#web") format("svg");
+ font-weight: 200
+}
+
+@font-face {
+ font-family: 'Segoe UI';
+ src: url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semilight/latest.eot"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semilight/latest.eot?#iefix") format("embedded-opentype");
+ src: local("Segoe UI Semilight"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semilight/latest.woff2") format("woff2"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semilight/latest.woff") format("woff"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semilight/latest.ttf") format("truetype"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semilight/latest.svg#web") format("svg");
+ font-weight: 300
+}
+
+@font-face {
+ font-family: 'Segoe UI';
+ src: url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/normal/latest.eot"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/normal/latest.eot?#iefix") format("embedded-opentype");
+ src: local("Segoe UI"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/normal/latest.woff2") format("woff"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/normal/latest.woff") format("woff"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/normal/latest.ttf") format("truetype"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/normal/latest.svg#web") format("svg");
+ font-weight: 400
+}
+
+@font-face {
+ font-family: 'Segoe UI';
+ src: url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semibold/latest.eot"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semibold/latest.eot?#iefix") format("embedded-opentype");
+ src: local("Segoe UI Semibold"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semibold/latest.woff2") format("woff"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semibold/latest.woff") format("woff"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semibold/latest.ttf") format("truetype"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/semibold/latest.svg#web") format("svg");
+ font-weight: 600
+}
+
+@font-face {
+ font-family: 'Segoe UI';
+ src: url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/bold/latest.eot"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/bold/latest.eot?#iefix") format("embedded-opentype");
+ src: local("Segoe UI Bold"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/bold/latest.woff2") format("woff"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/bold/latest.woff") format("woff"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/bold/latest.ttf") format("truetype"),url("https://c.s-microsoft.com/static/fonts/segoe-ui/west-european/bold/latest.svg#web") format("svg");
+ font-weight: 700
+}
diff --git a/src/vs/platform/auth/common/auth.html b/src/vs/platform/auth/common/auth.html
new file mode 100644
index 0000000000000..8fe3e50e7b7cc
--- /dev/null
+++ b/src/vs/platform/auth/common/auth.html
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+ Azure Account - Sign In
+
+
+
+
+
+ Visual Studio Code
+
+
+
+ You are signed in now and can close this page.
+
+
+ An error occurred while signing in:
+
+
+
+
+
+
diff --git a/src/vs/platform/auth/common/auth.ts b/src/vs/platform/auth/common/auth.ts
index 039949e9035e0..81af0bbf0a4a7 100644
--- a/src/vs/platform/auth/common/auth.ts
+++ b/src/vs/platform/auth/common/auth.ts
@@ -26,6 +26,6 @@ export interface IAuthTokenService {
getToken(): Promise;
refreshToken(): Promise;
- login(callbackUri?: URI): Promise;
+ login(): Promise;
logout(): Promise;
}
diff --git a/src/vs/platform/auth/common/authTokenIpc.ts b/src/vs/platform/auth/common/authTokenIpc.ts
index 99a2111750c42..eff088c111473 100644
--- a/src/vs/platform/auth/common/authTokenIpc.ts
+++ b/src/vs/platform/auth/common/authTokenIpc.ts
@@ -22,11 +22,8 @@ export class AuthTokenChannel implements IServerChannel {
switch (command) {
case '_getInitialStatus': return Promise.resolve(this.service.status);
case 'getToken': return this.service.getToken();
- case 'exchangeCodeForToken':
- this.service._onDidGetCallback.fire(args);
- return Promise.resolve();
case 'refreshToken': return this.service.refreshToken();
- case 'login': return this.service.login(args);
+ case 'login': return this.service.login();
case 'logout': return this.service.logout();
}
throw new Error('Invalid call');
diff --git a/src/vs/platform/auth/electron-browser/authServer.ts b/src/vs/platform/auth/electron-browser/authServer.ts
new file mode 100644
index 0000000000000..b2f227114fd97
--- /dev/null
+++ b/src/vs/platform/auth/electron-browser/authServer.ts
@@ -0,0 +1,162 @@
+/*---------------------------------------------------------------------------------------------
+ * Copyright (c) Microsoft Corporation. All rights reserved.
+ * Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+
+import * as http from 'http';
+import * as url from 'url';
+import * as fs from 'fs';
+import * as net from 'net';
+import { getPathFromAmdModule } from 'vs/base/common/amd';
+
+interface Deferred {
+ resolve: (result: T | Promise) => void;
+ reject: (reason: any) => void;
+}
+
+export function createTerminateServer(server: http.Server) {
+ const sockets: Record = {};
+ let socketCount = 0;
+ server.on('connection', socket => {
+ const id = socketCount++;
+ sockets[id] = socket;
+ socket.on('close', () => {
+ delete sockets[id];
+ });
+ });
+ return async () => {
+ const result = new Promise(resolve => server.close(resolve));
+ for (const id in sockets) {
+ sockets[id].destroy();
+ }
+ return result;
+ };
+}
+
+export async function startServer(server: http.Server): Promise {
+ let portTimer: NodeJS.Timer;
+
+ function cancelPortTimer() {
+ clearTimeout(portTimer);
+ }
+
+ const port = new Promise((resolve, reject) => {
+ portTimer = setTimeout(() => {
+ reject(new Error('Timeout waiting for port'));
+ }, 5000);
+
+ server.on('listening', () => {
+ const address = server.address();
+ if (typeof address === 'string') {
+ resolve(address);
+ } else {
+ resolve(address.port.toString());
+ }
+ });
+
+ server.on('error', err => {
+ reject(err);
+ });
+
+ server.on('close', () => {
+ reject(new Error('Closed'));
+ });
+
+ server.listen(0);
+ });
+
+ port.then(cancelPortTimer, cancelPortTimer);
+ return port;
+}
+
+function sendFile(res: http.ServerResponse, filepath: string, contentType: string) {
+ fs.readFile(filepath, (err, body) => {
+ if (err) {
+ console.error(err);
+ } else {
+ res.writeHead(200, {
+ 'Content-Length': body.length,
+ 'Content-Type': contentType
+ });
+ res.end(body);
+ }
+ });
+}
+
+async function callback(nonce: string, reqUrl: url.Url): Promise {
+ const query = reqUrl.query;
+ if (!query || typeof query === 'string') {
+ throw new Error('No query received.');
+ }
+
+ let error = query.error_description || query.error;
+
+ if (!error) {
+ const state = (query.state as string) || '';
+ const receivedNonce = (state.split(',')[1] || '').replace(/ /g, '+');
+ if (receivedNonce !== nonce) {
+ error = 'Nonce does not match.';
+ }
+ }
+
+ const code = query.code as string;
+ if (!error && code) {
+ return code;
+ }
+
+ throw new Error((error as string) || 'No code received.');
+}
+
+export function createServer(nonce: string) {
+ type RedirectResult = { req: http.IncomingMessage; res: http.ServerResponse; } | { err: any; res: http.ServerResponse; };
+ let deferredRedirect: Deferred;
+ const redirectPromise = new Promise((resolve, reject) => deferredRedirect = { resolve, reject });
+
+ type CodeResult = { code: string; res: http.ServerResponse; } | { err: any; res: http.ServerResponse; };
+ let deferredCode: Deferred;
+ const codePromise = new Promise((resolve, reject) => deferredCode = { resolve, reject });
+
+ const codeTimer = setTimeout(() => {
+ deferredCode.reject(new Error('Timeout waiting for code'));
+ }, 5 * 60 * 1000);
+
+ function cancelCodeTimer() {
+ clearTimeout(codeTimer);
+ }
+
+ const server = http.createServer(function (req, res) {
+ const reqUrl = url.parse(req.url!, /* parseQueryString */ true);
+ switch (reqUrl.pathname) {
+ case '/signin':
+ const receivedNonce = ((reqUrl.query.nonce as string) || '').replace(/ /g, '+');
+ if (receivedNonce === nonce) {
+ deferredRedirect.resolve({ req, res });
+ } else {
+ const err = new Error('Nonce does not match.');
+ deferredRedirect.resolve({ err, res });
+ }
+ break;
+ case '/':
+ sendFile(res, getPathFromAmdModule(require, '../common/auth.html'), 'text/html; charset=utf-8');
+ break;
+ case '/auth.css':
+ sendFile(res, getPathFromAmdModule(require, '../common/auth.css'), 'text/css; charset=utf-8');
+ break;
+ case '/callback':
+ deferredCode.resolve(callback(nonce, reqUrl)
+ .then(code => ({ code, res }), err => ({ err, res })));
+ break;
+ default:
+ res.writeHead(404);
+ res.end();
+ break;
+ }
+ });
+
+ codePromise.then(cancelCodeTimer, cancelCodeTimer);
+ return {
+ server,
+ redirectPromise,
+ codePromise
+ };
+}
diff --git a/src/vs/platform/auth/electron-browser/authTokenService.ts b/src/vs/platform/auth/electron-browser/authTokenService.ts
index 14586bab7b00c..301a6ae505c7a 100644
--- a/src/vs/platform/auth/electron-browser/authTokenService.ts
+++ b/src/vs/platform/auth/electron-browser/authTokenService.ts
@@ -8,10 +8,11 @@ import * as https from 'https';
import { Event, Emitter } from 'vs/base/common/event';
import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth';
import { ICredentialsService } from 'vs/platform/credentials/common/credentials';
-import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
+import { Disposable } from 'vs/base/common/lifecycle';
import { URI } from 'vs/base/common/uri';
import { generateUuid } from 'vs/base/common/uuid';
import { shell } from 'electron';
+import { createServer, startServer } from 'vs/platform/auth/electron-browser/authServer';
const SERVICE_NAME = 'VS Code';
const ACCOUNT = 'MyAccount';
@@ -23,14 +24,6 @@ const activeDirectoryResourceId = 'https://management.core.windows.net/';
const clientId = 'aebc6443-996d-45c2-90f0-388ff96faa56';
const tenantId = 'common';
-function parseQuery(uri: URI) {
- return uri.query.split('&').reduce((prev: any, current) => {
- const queryString = current.split('=');
- prev[queryString[0]] = queryString[1];
- return prev;
- }, {});
-}
-
function toQuery(obj: any): string {
return Object.keys(obj).map(key => `${key}=${obj[key]}`).join('&');
}
@@ -72,34 +65,63 @@ export class AuthTokenService extends Disposable implements IAuthTokenService {
});
}
- public async login(callbackUri: URI): Promise {
+ public async login(): Promise {
this.setStatus(AuthTokenStatus.SigningIn);
+
const nonce = generateUuid();
- const port = (callbackUri.authority.match(/:([0-9]*)$/) || [])[1] || (callbackUri.scheme === 'https' || callbackUri.scheme === 'http' ? 443 : 80);
- const state = `${callbackUri.scheme},${port},${encodeURIComponent(nonce)},${encodeURIComponent(callbackUri.query)}`;
- const signInUrl = `${activeDirectoryEndpointUrl}${tenantId}/oauth2/authorize`;
+ const { server, redirectPromise, codePromise } = createServer(nonce);
+
+ try {
+ const port = await startServer(server);
+ shell.openExternal(`http://localhost:${port}/signin?nonce=${encodeURIComponent(nonce)}`);
+
+ const redirectReq = await redirectPromise;
+ if ('err' in redirectReq) {
+ const { err, res } = redirectReq;
+ res.writeHead(302, { Location: `/?error=${encodeURIComponent(err && err.message || 'Unkown error')}` });
+ res.end();
+ throw err;
+ }
- const codeVerifier = toBase64UrlEncoding(crypto.randomBytes(32).toString('base64'));
- const codeChallenge = toBase64UrlEncoding(crypto.createHash('sha256').update(codeVerifier).digest('base64'));
+ const host = redirectReq.req.headers.host || '';
+ const updatedPortStr = (/^[^:]+:(\d+)$/.exec(Array.isArray(host) ? host[0] : host) || [])[1];
+ const updatedPort = updatedPortStr ? parseInt(updatedPortStr, 10) : port;
- let uri = URI.parse(signInUrl);
- uri = uri.with({
- query: `response_type=code&client_id=${encodeURIComponent(clientId)}&redirect_uri=${redirectUrlAAD}&state=${encodeURIComponent(state)}&resource=${activeDirectoryResourceId}&prompt=select_account&code_challenge_method=S256&code_challenge=${codeChallenge}`
- });
+ const state = `${updatedPort},${encodeURIComponent(nonce)}`;
+ const signInUrl = `${activeDirectoryEndpointUrl}${tenantId}/oauth2/authorize`;
- await shell.openExternal(uri.toString(true));
+ const codeVerifier = toBase64UrlEncoding(crypto.randomBytes(32).toString('base64'));
+ const codeChallenge = toBase64UrlEncoding(crypto.createHash('sha256').update(codeVerifier).digest('base64'));
- const timeoutPromise = new Promise((resolve: (value: IToken) => void, reject) => {
- const wait = setTimeout(() => {
- this.setStatus(AuthTokenStatus.SignedOut);
- clearTimeout(wait);
- reject('Login timed out.');
- }, 1000 * 60 * 5);
- });
+ let uri = URI.parse(signInUrl);
+ uri = uri.with({
+ query: `response_type=code&client_id=${encodeURIComponent(clientId)}&redirect_uri=${redirectUrlAAD}&state=${encodeURIComponent(state)}&resource=${activeDirectoryResourceId}&prompt=select_account&code_challenge_method=S256&code_challenge=${codeChallenge}`
+ });
+
+ await redirectReq.res.writeHead(302, { Location: uri.toString(true) });
+ redirectReq.res.end();
+
+ const codeRes = await codePromise;
+ const res = codeRes.res;
+
+ try {
+ if ('err' in codeRes) {
+ throw codeRes.err;
+ }
+ const token = await this.exchangeCodeForToken(codeRes.code, codeVerifier);
+ this.setToken(token);
+ res.writeHead(302, { Location: '/' });
+ res.end();
+ } catch (err) {
+ res.writeHead(302, { Location: `/?error=${encodeURIComponent(err && err.message || 'Unkown error')}` });
+ res.end();
+ }
+ } finally {
+ setTimeout(() => {
+ server.close();
+ }, 5000);
+ }
- return Promise.race([this.exchangeCodeForToken(clientId, tenantId, codeVerifier, state), timeoutPromise]).then(token => {
- this.setToken(token);
- });
}
public getToken(): Promise {
@@ -120,71 +142,55 @@ export class AuthTokenService extends Disposable implements IAuthTokenService {
this.setStatus(AuthTokenStatus.SignedIn);
}
- private async exchangeCodeForToken(clientId: string, tenantId: string, codeVerifier: string, state: string): Promise {
- let uriEventListener: IDisposable;
+ private exchangeCodeForToken(code: string, codeVerifier: string): Promise {
return new Promise((resolve: (value: IToken) => void, reject) => {
- uriEventListener = this.onDidGetCallback(async (uri: URI) => {
- try {
- const query = parseQuery(uri);
- const code = query.code;
+ try {
+ const postData = toQuery({
+ grant_type: 'authorization_code',
+ code: code,
+ client_id: clientId,
+ code_verifier: codeVerifier,
+ redirect_uri: redirectUrlAAD
+ });
- if (query.state !== state) {
- return;
+ const post = https.request({
+ host: 'login.microsoftonline.com',
+ path: `/${tenantId}/oauth2/token`,
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ 'Content-Length': postData.length
}
-
- const postData = toQuery({
- grant_type: 'authorization_code',
- code: code,
- client_id: clientId,
- code_verifier: codeVerifier,
- redirect_uri: redirectUrlAAD
+ }, result => {
+ const buffer: Buffer[] = [];
+ result.on('data', (chunk: Buffer) => {
+ buffer.push(chunk);
});
-
- const post = https.request({
- host: 'login.microsoftonline.com',
- path: `/${tenantId}/oauth2/token`,
- method: 'POST',
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded',
- 'Content-Length': postData.length
+ result.on('end', () => {
+ if (result.statusCode === 200) {
+ const json = JSON.parse(Buffer.concat(buffer).toString());
+ resolve({
+ expiresIn: json.access_token,
+ expiresOn: json.expires_on,
+ accessToken: json.access_token,
+ refreshToken: json.refresh_token
+ });
+ } else {
+ reject(new Error('Bad!'));
}
- }, result => {
- const buffer: Buffer[] = [];
- result.on('data', (chunk: Buffer) => {
- buffer.push(chunk);
- });
- result.on('end', () => {
- if (result.statusCode === 200) {
- const json = JSON.parse(Buffer.concat(buffer).toString());
- resolve({
- expiresIn: json.access_token,
- expiresOn: json.expires_on,
- accessToken: json.access_token,
- refreshToken: json.refresh_token
- });
- } else {
- reject(new Error('Bad!'));
- }
- });
});
+ });
- post.write(postData);
+ post.write(postData);
- post.end();
- post.on('error', err => {
- reject(err);
- });
+ post.end();
+ post.on('error', err => {
+ reject(err);
+ });
- } catch (e) {
- reject(e);
- }
- });
- }).then(result => {
- uriEventListener.dispose();
- return result;
- }).catch(err => {
- uriEventListener.dispose();
- throw err;
+ } catch (e) {
+ reject(e);
+ }
});
}
diff --git a/src/vs/workbench/services/authToken/electron-browser/authTokenService.ts b/src/vs/workbench/services/authToken/electron-browser/authTokenService.ts
index 099395471aa06..ad7abd588267c 100644
--- a/src/vs/workbench/services/authToken/electron-browser/authTokenService.ts
+++ b/src/vs/workbench/services/authToken/electron-browser/authTokenService.ts
@@ -9,7 +9,6 @@ import { Emitter, Event } from 'vs/base/common/event';
import { IChannel } from 'vs/base/parts/ipc/common/ipc';
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { IAuthTokenService, AuthTokenStatus } from 'vs/platform/auth/common/auth';
-import { IURLService } from 'vs/platform/url/common/url';
import { URI } from 'vs/base/common/uri';
export class AuthTokenService extends Disposable implements IAuthTokenService {
@@ -27,23 +26,11 @@ export class AuthTokenService extends Disposable implements IAuthTokenService {
constructor(
@ISharedProcessService sharedProcessService: ISharedProcessService,
- @IURLService private readonly urlService: IURLService
) {
super();
this.channel = sharedProcessService.getChannel('authToken');
this._register(this.channel.listen('onDidChangeStatus')(status => this.updateStatus(status)));
this.channel.call('_getInitialStatus').then(status => this.updateStatus(status));
-
- this.urlService.registerHandler(this);
- }
-
- handleURL(uri: URI) {
- if (uri.authority === 'vscode.login') {
- this.channel.call('exchangeCodeForToken', uri);
- return Promise.resolve(true);
- } else {
- return Promise.resolve(false);
- }
}
getToken(): Promise {
@@ -51,8 +38,7 @@ export class AuthTokenService extends Disposable implements IAuthTokenService {
}
login(): Promise {
- const callbackUri = this.urlService.create({ authority: 'vscode.login ' });
- return this.channel.call('login', callbackUri);
+ return this.channel.call('login');
}
refreshToken(): Promise {