Dissection of MS Teams (mac desktop app)

Quarantine or not I always have some side projects, this time it's the app I start every morning: MS Teams.

ignite

 From previous experiences as a SharePoint architect, I know that quality information is usually presented by MS internal people, who are working on the product teams. So to realize that Teams is much more than just the client app, please watch the following videos (originally channel9, but I prefer YouTube links):

 There are also solutions posters available, or you can start reading full blown documentation.

introduction

Update: in my original version I had here the title 'architecture' and some screenshots from the suggested videos to watch, but I've decided to remove those to avoid any copyright issues ...

 Few words on the app, before we dive into details ... MS Teams is implemented as an Electron app, MS already gained experience building Electron apps with their VSCode application, and for Teams they picked the same, BUT in a totally different manner! While VSCode is a standalone app, MS Teams client app is 'just' a wrapper around the web version, to hook it up with your desktop OS services and give you a more 'native' experience. As it's an Electron app, there is a ton of nodejs involved, most of them are visible, but there are some important pieces where MS only deployed binaries.

dissection

 My autopsy assumes MacOS as a platform, but the process should be similar on any other OS. As a result of the whole shebang, you should have an extracted version of Teams app, with most of the functionality in place. You should be able to start up Teams from the 'source code', but it has some requirements ... I assume you are somewhat familiar with 'Terminal' and Node.js!

first incision, extracting an asar

the rig
Our goal in this step is to extract the 'app.asar' as can be seen on the picture above.

On MacOS applications are installed under /Applications folder, under that folder we need to find the asar file of Teams:
# cd /Applications/Microsoft Teams.app/Contents/Resources
# ls *.asar
app.asar       electron.asar
We are interested in the app.asar, and to keep my plate clean, I created a folder for the experiment in my dev folder. Successful extraction of the asar file requires some extra files in place in advance. To extract, I use npx, so I could avoid global install of asar.
... navigate to the folder where you gonna work ...
# mkdir teamz
# cp /Applications/Microsoft\ Teams.app/Contents/Resources/app.asar .
# cp -r /Applications/Microsoft\ Teams.app/Contents/Resources/app.asar.unpacked .
# npx asar extract app.asar src
# cd src; ls src
assets/          env_config.json  external/        lib/             locales/         node_modules/    package.json
Bingo! Let's check package.json

the rig
package.json file in VSCode

"Copyright (C) 2016 Microsoft. All rights reserved.", would it mean that the first official code was committed in 2016? At least the first blog entry Welcome to the Microsoft Teams Community! at Microsoft Teams Blog also dates back to 2016. We are ready now with our first step, let's try to start up things ...

side trip, Electron

 As I don't wanna install Electron globally, and we need a given version of it, I will do a dirty shortcut ...

# cd ..
# mkdir elektron; cd elektron
# npm init
... name your project whatever you want, I named mine 'elektron'
# npm install electron@v3.1.13
I also downgraded my version of nodejs, but that is a different stroy ...

back on track, main.js

 According to package.json presumably lib/main.js, is our entry point to start the app. Well, from experience I can tell, without some adjustments to the code, it won't! main.js is the main entry-point of the code, contains bootstrap for the app. As I haven't done a global install of Electron there are things out of context. (Please note, that I'm not an Electron expert, so due to the fact I had to do shortcuts).

From (line #32)

let appName = electron_1.app.getName();
To
let appName = 'Teams'
 As I learned the hard way, electron.app.getAppPath() function is used overall in the code, so it's better to override the default value

From (line #40)
electron_1.app.setPath('userData', userDataPath);
To
electron_1.app.setPath('userData', userDataPath);
electron_1.app.setAppPath('<your path>/teamz/src');

We are now just few steps away to start the app, but first we have to move our existing Teams preferences folder to safety. On MacOS, application configurations setting for teams can be found under '~/Library/Application\ Support/Microsoft/Teams/'. If you are planning to use the 'Teams app' in the normal way as well, I suggest you make a backup of this folder (though Teams is storing most of you data in Azure).
# mv ~/Library/Application\ Support/Microsoft/Teams/ ~/Library/Application\ Support/Microsoft/Teams.backup
# mkdir ~/Library/Application\ Support/Microsoft/Teams/
And now the 'hard part'! There is an authentication flow going on, and it fails when we start the app with electron. But I managed to fix it, so at least you can login once and use the app. To achieve this we need to modify 'adal-impl-mac.js, below is my diff:
178c178
<         if (this.currentRequestStatus.errorCode === 204 /* AD_ERROR_SERVER_WRONG_USER */) {
---
>         if (this.currentRequestStatus && this.currentRequestStatus.errorCode === 204 /* AD_ERROR_SERVER_WRONG_USER */) {
188c188
<             + 'error:' + this.currentRequestStatus.errorCode
---
>             //+ 'error:' + (this.currentRequestStatus) ? this.currentRequestStatus.errorCode : 'unknown'
190c190
<         if (!this.hasTriedLogout && appConfig.getInstance().getSetting(constants.settings.handle300)
---
>         if (this.currentRequestStatus && !this.hasTriedLogout && appConfig.getInstance().getSetting(constants.settings.handle300

let's try

 Living on the edge? Let's try to start ...

node ../elektron/node_modules/electron/cli.js lib/main.js
Important! if there is an earlier Teams folder under ~/Library/Application\ Support/Microsoft/ the app will start, but turns idle at a certain point!

You should get the Teams login screen as you can see below.

the rig

One has to go through the 'login' flow, so next is your authentication at Azure

the rig

You authenticated yourself you should get Teams!!!

the rig

Summary

 I hope you managed to start up Teams, and find my tech summary useful. Now you shall be able to check out what is under the hood of Teams electron app, and make some minor changes to your copy if you fancy. Though as you will understand, it's a complex beast and most of it is running in Auzre and not on your machine. As my time was limited I did not spent any minute on checking how native bindings toward devices would work. But for sure you can send messages to chats from the 'source code' based app.
 I personally don't like the fact that MS is using Angular for the UI, but I understand their decision. (Update: in the video I added lately to the list at the top, there is mentioning that MS is migrating things to React. In that presentation it's also shown that the mobile clients are already using ReactNative). There are also some 'native' node libraries that are part of the Electron app and the source code of these modules are not available (e.g.: adal-mac, slimcore, etc.).
 While I was writing the tech summary an interesting article caught my eye in my LinkedIn feed: Microsoft revenue beats as remote work boosts Teams. If you watched the suggested videos, you are aware, that Teams is much more than just a video conferencing app and by using it you are using a lot of services from Azure / Office365.

Comments

Back to vaew.io