I have been using settings sync in Visual Studio Code since it was first released in the Insiders build and it has been working well for me, I currently sync settings from Insiders and Stable releases on four different Windows machines and one MacBook Pro. Then, all of a sudden the Insiders instance on one of the Windows computers stopped syncing;
Weirdly enough, the Stable build on the same machine kept happily working and syncing settings, suggesting the problem was specific to this Insiders installation and not some machine wide problem. It’s worth pointing out again installation, it was not even a problem with the general Insiders build since the same build was still working fine on all other machines.
At first I tried to start VSCode without extensions (code-insiders --disable-extensions
), then I tried to fully remove VSCode (and manually deleted all relevant folders under my local profile), restarted Windows… the usual deal, all with no luck. I then decided to open an issue on GitHub (more on that later) while I continued my investigation; the first comment from RMacfarlane suggested something might have changed with the network configuration on the machine, but again, that should have affected the Stable release as well. I checked anyway and made sure code-insiders was allowed through Windows Firewall (it was). So I decided to take a look at the failing code; Settings Sync (or rather, miccrosoft-authentication
in this case) is a built-in extension that can be found under C:\Users\<user>\AppData\Local\Programs\Microsoft VS Code Insiders\resources\app\extensions\microsoft-authentication\dist\extension.js
or /Applications/Visual Studio Code - Insiders.app/Contents/Resources/app/extensions/microsoft-authentication/dist/extension.js
on macOS. The file needs to be beautified but once done it was easy to find the failing method:
private async refreshToken(refreshToken: string, scope: string, sessionId: string): Promise < IToken > { try { Logger.info('Refreshing token...'); const postData = querystring.stringify({ refresh_token: refreshToken, client_id: clientId, grant_type: 'refresh_token', scope: scope }); const result = await fetch(`https://login.microsoftonline.com/${tenant}/oauth2/v2.0/token`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'Content-Length': postData.length.toString() }, body: postData }); if(result.ok) { const json = await result.json(); const token = this.getTokenFromResponse(json, scope, sessionId); this.setToken(token, scope); Logger.info('Token refresh success'); return token; } else { Logger.error(`Refreshing token failed: ${result.statusText}`); throw new Error('Refreshing token failed.'); } } catch (e) { Logger.error('Refreshing token failed'); throw new Error(REFRESH_NETWORK_FAILURE); } }
Clearly it is a network communication failure of some kind, so the next logical step was to analyze the network traffic: Fiddler in this case was enough:
INSIDERS REQUEST POST https://login.microsoftonline.com/organizations/oauth2/v2.0/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded Content-Length: 1688 Accept: */* User-Agent: node-fetch/1.0 (+https://github.com/bitinn/node-fetch) Accept-Encoding: gzip,deflate Connection: close Host: login.microsoftonline.com refresh_token=0.AAAAMe_N-B6jS[...] RESPONSE HTTP/1.1 400 Bad Request Cache-Control: no-store, no-cache Pragma: no-cache Content-Length: 566 Content-Type: application/json; charset=utf-8 Expires: -1 Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff P3P: CP="DSP CUR OTPi IND OTRi ONL FIN" x-ms-request-id: 6a98c866-d152-4b8c-9323-c267643a4d00 x-ms-ests-server: 2.1.11063.7 - WUS2 ProdSlices report-to: {"group":"network-errors","max_age":86400,"endpoints":[{"url":"https://ffde.nelreports.net/api/report?cat=estscorp+wst"}]} nel: {"report_to":"network-errors","max_age":86400,"success_fraction":0.001,"failure_fraction":1.0} Set-Cookie: fpc=AhzP-6kQ6rNOhtjP3prNTV6b5UYsAQAAACC19NYOAAAA; expires=Sat, 17-Oct-2020 01:38:41 GMT; path=/; secure; HttpOnly; SameSite=None Set-Cookie: x-ms-gateway-slice=corp; path=/; secure; samesite=none; httponly Set-Cookie: stsservicecookie=estscorp; path=/; secure; samesite=none; httponly Date: Thu, 17 Sep 2020 01:38:40 GMT Connection: close {"error":"invalid_grant","error_description":"AADSTS700003: Device object was not found in the tenant 'f8cdef31-a31e-4b4a-93e4-5f571e91255a' directory.\r\nTrace ID: 6a98c866-d152-4b8c-9323-c267643a4d00\r\nCorrelation ID: 7783e740-4e79-4c3c-82c5-32224fdfd7bf\r\nTimestamp: 2020-09-17 01:38:41Z","error_codes":[700003],"timestamp":"2020-09-17 01:38:41Z","trace_id":"6a98c866-d152-4b8c-9323-c267643a4d00","correlation_id":"7783e740-4e79-4c3c-82c5-32224fdfd7bf","error_uri":"https://login.microsoftonline.com/error?code=700003","suberror":"device_authentication_failed"} STABLE REQUEST POST https://login.microsoftonline.com/organizations/oauth2/v2.0/token HTTP/1.1 Content-Type: application/x-www-form-urlencoded Content-Length: 1760 Accept: */* User-Agent: node-fetch/1.0 (+https://github.com/bitinn/node-fetch) Accept-Encoding: gzip,deflate Connection: close Host: login.microsoftonline.com refresh_token=0.AAAAMe_N-B6jSkuT5 [...] RESPONSE HTTP/1.1 200 OK Cache-Control: no-store, no-cache Pragma: no-cache Content-Length: 4659 Content-Type: application/json; charset=utf-8 Expires: -1 Strict-Transport-Security: max-age=31536000; includeSubDomains X-Content-Type-Options: nosniff P3P: CP="DSP CUR OTPi IND OTRi ONL FIN" client-request-id: 587d8a8b-a4e3-4ad1-b038-fb82fca5cbb3 x-ms-request-id: 6ee921d4-44eb-4bbd-a7d2-b92a2a333500 x-ms-ests-server: 2.1.11063.7 - EUS ProdSlices x-ms-clitelem: 1,0,0,3052114141.4735, Set-Cookie: fpc=Atn7i5LhCDlCqLjF_Sco5A_X5sDqAQAAAAa29NYOAAAA; expires=Sat, 17-Oct-2020 01:42:31 GMT; path=/; secure; HttpOnly; SameSite=None Set-Cookie: x-ms-gateway-slice=estsfd; path=/; secure; httponly Set-Cookie: stsservicecookie=estsfd; path=/; secure; httponly Date: Thu, 17 Sep 2020 01:42:31 GMT Connection: close [...]
So the authentication attempt was failing with a code 400 (Bad Request) and the error description is AADSTS700003: Device object was not found in the tenant 'f8cdef31-a31e-4b4a-93e4-5f571e91255a' directory
. Google and StackOverflow were not very helpful in this case, I only found some general information out of the error code.
Decided to not give up I tried to logout of all authentication providers in VSCode Insiders (currently Microsoft and GitHub are supported), that didn’t solve the problem but made me notice that when I tried to enable Settings Sync back, I was not prompted to authenticate as I would have expected; that means credentials where cached somewhere, and I already knew it was not in a temporary folder used by vscode because I had already cleared them all… On Windows, a place to check for cached credentials is Windows Credential Manager
: I noticed two entries related to VSCode Insiders, one for each authentication provider:
I deleted those two entries, re-enabled Settings Sync and sure enough I was able to authenticate and sync my settings again đź‘Ť.
Heres the GitHub issue I opened: https://github.com/microsoft/vscode/issues/106321; RMacfarlane has synce pushed an update to prevent this to happen again, you can see the details in this pull request.
You cannot shake hands with aclenched fist. Golda Meir