1
0
mirror of https://github.com/bitwarden/browser.git synced 2024-11-28 12:45:45 +01:00

Merge pull request #615 from Hinton/hotfix/multiple-extensions

Native Messaging - Support multiple extensions concurrently
This commit is contained in:
Chad Scharf 2020-12-22 10:54:58 -05:00 committed by GitHub
commit 76c040aff9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 286 additions and 226 deletions

View File

@ -26,6 +26,18 @@ npm install
npm run electron npm run electron
``` ```
**Debug Native Messaging**
Native Messaging (communication with the browser extension) works by having the browser start a lightweight proxy application baked into our desktop binary. To setup an environment which allows
for easy debugging you will need to build the application for distribution, i.e. `npm run dist:<platform>`, start the dist version and enable desktop integration. This will write some manifests
to disk, Consult the [native manifests](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Native_manifests#Manifest_location) documentation for more details of the manigest
format, and the exact locations for the different platforms. *Note* that disabling the desktop integration will delete the manifests, and the files will need to be updated again.
The generated manifests are pre-configured with the production ID for the browser extensions. In order to use them with the development builds, the browser extension ID of the development build
needs to be added to the `allowed_extensions` section of the manifest. These IDs are generated by the browser, and can be found in the extension settings within the browser.
It will then be possible to run the desktop application as usual using `npm run electron` and communicate with the browser.
# Contribute # Contribute
Code contributions are welcome! Please commit any pull requests against the `master` branch. Learn more about how to contribute by reading the [`CONTRIBUTING.md`](CONTRIBUTING.md) file. Code contributions are welcome! Please commit any pull requests against the `master` branch. Learn more about how to contribute by reading the [`CONTRIBUTING.md`](CONTRIBUTING.md) file.

2
jslib

@ -1 +1 @@
Subproject commit acdbc229533a4f5f57b83b882ce48037a8a17299 Subproject commit 12321e53b9199e1b4dd4653948b924f1a2b31efc

336
package-lock.json generated
View File

@ -11,9 +11,9 @@
"dev": true "dev": true
}, },
"@angular-devkit/core": { "@angular-devkit/core": {
"version": "9.1.12", "version": "9.1.13",
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-9.1.12.tgz", "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-9.1.13.tgz",
"integrity": "sha512-D/GnBeSlmdgGn7EhuE32HuPuRAjvUuxi7Q6WywBI8PSsXKAGnrypghBwMATNnOA24//CgbW2533Y9VWHaeXdeA==", "integrity": "sha512-bwehVRsva9OWfh/yuEh9VU+0Gr1T7DHJLe8tpZk/VsIkGOD0IszEPZOIEK23bg32yiff9bh6qJEPMA7ZBYEQHg==",
"dev": true, "dev": true,
"requires": { "requires": {
"ajv": "6.12.3", "ajv": "6.12.3",
@ -69,9 +69,9 @@
"dev": true "dev": true
}, },
"tslib": { "tslib": {
"version": "1.13.0", "version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true "dev": true
} }
} }
@ -100,9 +100,9 @@
"integrity": "sha512-suefk0OFkaJpUUKnV+phbL4T8fmVGHvzkereY5eqybQlumOez8NPL1PJcygAylh/E6OIAYm8SWookYwM6ZY9dg==" "integrity": "sha512-suefk0OFkaJpUUKnV+phbL4T8fmVGHvzkereY5eqybQlumOez8NPL1PJcygAylh/E6OIAYm8SWookYwM6ZY9dg=="
}, },
"@angular/compiler-cli": { "@angular/compiler-cli": {
"version": "9.1.12", "version": "9.1.13",
"resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-9.1.12.tgz", "resolved": "https://registry.npmjs.org/@angular/compiler-cli/-/compiler-cli-9.1.13.tgz",
"integrity": "sha512-bbqJ+fbY+aQejSYuHUjE1qYJCXkZBM5Hru9eN7m/j376u83MQ5jWdC290uYx+ipsXcPTa/YRZ44jpL+5cCzIrg==", "integrity": "sha512-40jbfMr1FinOqUyG3k4Moiytjs/Z8zKBgP3S5Qfn80EBJItRdFXwNtvaOi/onaag4+Mv+vigShwsgCewLbt/kA==",
"dev": true, "dev": true,
"requires": { "requires": {
"canonical-path": "1.0.0", "canonical-path": "1.0.0",
@ -116,7 +116,7 @@
"semver": "^6.3.0", "semver": "^6.3.0",
"source-map": "^0.6.1", "source-map": "^0.6.1",
"sourcemap-codec": "^1.4.8", "sourcemap-codec": "^1.4.8",
"yargs": "15.3.0" "yargs": "^16.1.1"
}, },
"dependencies": { "dependencies": {
"ansi-regex": { "ansi-regex": {
@ -126,30 +126,23 @@
"dev": true "dev": true
}, },
"ansi-styles": { "ansi-styles": {
"version": "4.2.1", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/color-name": "^1.1.1",
"color-convert": "^2.0.1" "color-convert": "^2.0.1"
} }
}, },
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
"cliui": { "cliui": {
"version": "6.0.0", "version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"string-width": "^4.2.0", "string-width": "^4.2.0",
"strip-ansi": "^6.0.0", "strip-ansi": "^6.0.0",
"wrap-ansi": "^6.2.0" "wrap-ansi": "^7.0.0"
} }
}, },
"color-convert": { "color-convert": {
@ -173,16 +166,6 @@
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"dev": true "dev": true
}, },
"find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"requires": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
}
},
"fs-extra": { "fs-extra": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz",
@ -206,51 +189,6 @@
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"dev": true "dev": true
}, },
"locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"requires": {
"p-locate": "^4.1.0"
}
},
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"requires": {
"p-limit": "^2.2.0"
}
},
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
},
"path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true
},
"require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
"dev": true
},
"semver": { "semver": {
"version": "6.3.0", "version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
@ -278,9 +216,9 @@
} }
}, },
"wrap-ansi": { "wrap-ansi": {
"version": "6.2.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dev": true, "dev": true,
"requires": { "requires": {
"ansi-styles": "^4.0.0", "ansi-styles": "^4.0.0",
@ -288,34 +226,32 @@
"strip-ansi": "^6.0.0" "strip-ansi": "^6.0.0"
} }
}, },
"y18n": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.5.tgz",
"integrity": "sha512-hsRUr4FFrvhhRH12wOdfs38Gy7k2FFzB9qgN9v3aLykRq0dRcdcpz5C9FxdS2NuhOrI/628b/KSTJ3rwHysYSg==",
"dev": true
},
"yargs": { "yargs": {
"version": "15.3.0", "version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.0.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-g/QCnmjgOl1YJjGsnUg2SatC7NUYEiLXJqxNOQU9qSpjzGtGXda9b+OKccr1kLTy8BN9yqEyqfq5lxlwdc13TA==", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true, "dev": true,
"requires": { "requires": {
"cliui": "^6.0.0", "cliui": "^7.0.2",
"decamelize": "^1.2.0", "escalade": "^3.1.1",
"find-up": "^4.1.0", "get-caller-file": "^2.0.5",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1", "require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^4.2.0", "string-width": "^4.2.0",
"which-module": "^2.0.0", "y18n": "^5.0.5",
"y18n": "^4.0.0", "yargs-parser": "^20.2.2"
"yargs-parser": "^18.1.0"
} }
}, },
"yargs-parser": { "yargs-parser": {
"version": "18.1.3", "version": "20.2.4",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
"dev": true, "dev": true
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
} }
} }
}, },
@ -544,12 +480,12 @@
} }
}, },
"@ngtools/webpack": { "@ngtools/webpack": {
"version": "9.1.12", "version": "9.1.13",
"resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-9.1.12.tgz", "resolved": "https://registry.npmjs.org/@ngtools/webpack/-/webpack-9.1.13.tgz",
"integrity": "sha512-lypMXIq5oxBMsoDu/VOa1yUmmXthhxkCJa8LG0ZohfnbwhmZvz3SAW7omBGuVrb5cVIfLCkaRCSnQ1MNc6ULXw==", "integrity": "sha512-mTygcNgr58Mpv+WVrkXe3QXZJO5RKUEDcMoj0bscBp9G62MiMsRKnkDjb5GSXXnSGZb5GOlzdVwayib1O5y3uQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"@angular-devkit/core": "9.1.12", "@angular-devkit/core": "9.1.13",
"enhanced-resolve": "4.1.1", "enhanced-resolve": "4.1.1",
"rxjs": "6.5.4", "rxjs": "6.5.4",
"webpack-sources": "1.4.3" "webpack-sources": "1.4.3"
@ -586,9 +522,9 @@
} }
}, },
"tslib": { "tslib": {
"version": "1.13.0", "version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==", "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true "dev": true
}, },
"webpack-sources": { "webpack-sources": {
@ -661,9 +597,9 @@
"dev": true "dev": true
}, },
"@types/node": { "@types/node": {
"version": "10.17.35", "version": "10.17.49",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.35.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.49.tgz",
"integrity": "sha512-gXx7jAWpMddu0f7a+L+txMplp3FnHl53OhQIF9puXKq3hDGY/GjH+MF04oWnV/adPSCrbtHumDCFwzq2VhltWA==", "integrity": "sha512-PGaJNs5IZz5XgzwJvL/1zRfZB7iaJ5BydZ8/Picm+lUNYoNO9iVTQkVy5eUh0dZDrx3rBOIs3GCbCRmMuYyqwg==",
"dev": true "dev": true
}, },
"@types/node-forge": { "@types/node-forge": {
@ -1761,6 +1697,14 @@
"integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=",
"dev": true "dev": true
}, },
"bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"bl": { "bl": {
"version": "1.2.2", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz",
@ -2400,9 +2344,9 @@
"dev": true "dev": true
}, },
"chokidar": { "chokidar": {
"version": "3.4.2", "version": "3.4.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz",
"integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", "integrity": "sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"anymatch": "~3.1.1", "anymatch": "~3.1.1",
@ -2412,7 +2356,7 @@
"is-binary-path": "~2.1.0", "is-binary-path": "~2.1.0",
"is-glob": "~4.0.1", "is-glob": "~4.0.1",
"normalize-path": "~3.0.0", "normalize-path": "~3.0.0",
"readdirp": "~3.4.0" "readdirp": "~3.5.0"
}, },
"dependencies": { "dependencies": {
"anymatch": { "anymatch": {
@ -2449,13 +2393,6 @@
"to-regex-range": "^5.0.1" "to-regex-range": "^5.0.1"
} }
}, },
"fsevents": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
"dev": true,
"optional": true
},
"glob-parent": { "glob-parent": {
"version": "5.1.1", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
@ -2486,15 +2423,6 @@
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true "dev": true
}, },
"readdirp": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz",
"integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
}
},
"to-regex-range": { "to-regex-range": {
"version": "5.0.1", "version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
@ -3774,6 +3702,14 @@
"@types/node": "^10.12.18", "@types/node": "^10.12.18",
"electron-download": "^4.1.0", "electron-download": "^4.1.0",
"extract-zip": "^1.0.3" "extract-zip": "^1.0.3"
},
"dependencies": {
"@types/node": {
"version": "10.17.49",
"resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.49.tgz",
"integrity": "sha512-PGaJNs5IZz5XgzwJvL/1zRfZB7iaJ5BydZ8/Picm+lUNYoNO9iVTQkVy5eUh0dZDrx3rBOIs3GCbCRmMuYyqwg==",
"dev": true
}
} }
}, },
"electron-builder": { "electron-builder": {
@ -4861,6 +4797,12 @@
"es6-symbol": "^3.1.1" "es6-symbol": "^3.1.1"
} }
}, },
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true
},
"escape-goat": { "escape-goat": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz",
@ -5246,6 +5188,11 @@
} }
} }
}, },
"file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
},
"filelist": { "filelist": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz",
@ -5650,6 +5597,15 @@
"integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
"dev": true "dev": true
}, },
"forcefocus": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/forcefocus/-/forcefocus-1.1.0.tgz",
"integrity": "sha512-bnY7rul5kBLyNoCn0FHNiFAF+GGUZx6TvxWhurUS4PlmOzF+FMixGIigHH5UcyM3w1gp2TxAtP6MOUSXA15Sgw==",
"requires": {
"bindings": "^1.3.0",
"prebuild-install": "^5.0.0"
}
},
"forever-agent": { "forever-agent": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
@ -5745,6 +5701,13 @@
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true "dev": true
}, },
"fsevents": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz",
"integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==",
"dev": true,
"optional": true
},
"fstream": { "fstream": {
"version": "1.0.12", "version": "1.0.12",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
@ -9343,34 +9306,6 @@
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.6.tgz",
"integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw==" "integrity": "sha512-sol30LUpz1jQFBjOKwbjxijiE3b6pjd74YwfD0fJOKPjF+fONKb2Yg8rYgS6+bK6VDl+/wfr4IYpC7jDzLUIfw=="
}, },
"node-gyp": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
"integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
"dev": true,
"requires": {
"fstream": "^1.0.0",
"glob": "^7.0.3",
"graceful-fs": "^4.1.2",
"mkdirp": "^0.5.0",
"nopt": "2 || 3",
"npmlog": "0 || 1 || 2 || 3 || 4",
"osenv": "0",
"request": "^2.87.0",
"rimraf": "2",
"semver": "~5.3.0",
"tar": "^2.0.0",
"which": "1"
},
"dependencies": {
"semver": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
"dev": true
}
}
},
"node-ipc": { "node-ipc": {
"version": "9.1.1", "version": "9.1.1",
"resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.1.1.tgz", "resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.1.1.tgz",
@ -9512,6 +9447,35 @@
"integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==",
"dev": true "dev": true
}, },
"node-gyp": {
"version": "3.8.0",
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz",
"integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==",
"dev": true,
"requires": {
"fstream": "^1.0.0",
"glob": "^7.0.3",
"graceful-fs": "^4.1.2",
"mkdirp": "^0.5.0",
"nopt": "2 || 3",
"npmlog": "0 || 1 || 2 || 3 || 4",
"osenv": "0",
"request": "^2.87.0",
"rimraf": "2",
"semver": "~5.3.0",
"tar": "^2.0.0",
"which": "1"
}
},
"nopt": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
"integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
"dev": true,
"requires": {
"abbrev": "1"
}
},
"oauth-sign": { "oauth-sign": {
"version": "0.9.0", "version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
@ -9546,12 +9510,29 @@
"uuid": "^3.3.2" "uuid": "^3.3.2"
} }
}, },
"semver": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz",
"integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=",
"dev": true
},
"supports-color": { "supports-color": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
"dev": true "dev": true
}, },
"tar": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
"integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
"dev": true,
"requires": {
"block-stream": "*",
"fstream": "^1.0.12",
"inherits": "2"
}
},
"tough-cookie": { "tough-cookie": {
"version": "2.4.3", "version": "2.4.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
@ -9569,15 +9550,6 @@
"resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz", "resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
"integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=" "integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI="
}, },
"nopt": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
"integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=",
"dev": true,
"requires": {
"abbrev": "1"
}
},
"nord": { "nord": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "https://registry.npmjs.org/nord/-/nord-0.2.1.tgz", "resolved": "https://registry.npmjs.org/nord/-/nord-0.2.1.tgz",
@ -10763,6 +10735,15 @@
"util-deprecate": "~1.0.1" "util-deprecate": "~1.0.1"
} }
}, },
"readdirp": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz",
"integrity": "sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ==",
"dev": true,
"requires": {
"picomatch": "^2.2.1"
}
},
"recast": { "recast": {
"version": "0.11.23", "version": "0.11.23",
"resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz", "resolved": "https://registry.npmjs.org/recast/-/recast-0.11.23.tgz",
@ -11186,9 +11167,9 @@
}, },
"dependencies": { "dependencies": {
"tslib": { "tslib": {
"version": "1.13.0", "version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==" "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
} }
} }
}, },
@ -12021,17 +12002,6 @@
"integrity": "sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==", "integrity": "sha512-IlqtmLVaZA2qab8epUXbVWRn3aB1imbDMJtjB3nu4X0NqPkcY/JH9ZtCBWKHWPxs8Svi9tyo8w2dBoi07qZbBA==",
"dev": true "dev": true
}, },
"tar": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz",
"integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==",
"dev": true,
"requires": {
"block-stream": "*",
"fstream": "^1.0.12",
"inherits": "2"
}
},
"tar-fs": { "tar-fs": {
"version": "1.16.3", "version": "1.16.3",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-1.16.3.tgz",

View File

@ -311,6 +311,7 @@
"electron-log": "2.2.17", "electron-log": "2.2.17",
"electron-store": "1.3.0", "electron-store": "1.3.0",
"electron-updater": "4.3.5", "electron-updater": "4.3.5",
"forcefocus": "^1.1.0",
"keytar": "4.13.0", "keytar": "4.13.0",
"lunr": "2.3.3", "lunr": "2.3.3",
"node-forge": "0.7.6", "node-forge": "0.7.6",

View File

@ -98,6 +98,16 @@
</div> </div>
<small class="help-block">{{'enableBrowserIntegrationDesc' | i18n}}</small> <small class="help-block">{{'enableBrowserIntegrationDesc' | i18n}}</small>
</div> </div>
<div class="form-group">
<div class="checkbox">
<label for="enableBrowserIntegrationFingerprint">
<input id="enableBrowserIntegrationFingerprint" type="checkbox" name="EnableBrowserIntegrationFingerprint"
[(ngModel)]="enableBrowserIntegrationFingerprint" (change)="saveBrowserIntegrationFingerprint()" [disabled]="!enableBrowserIntegration">
{{'enableBrowserIntegrationFingerprint' | i18n}}
</label>
</div>
<small class="help-block">{{'enableBrowserIntegrationFingerprintDesc' | i18n}}</small>
</div>
<div class="form-group"> <div class="form-group">
<div class="checkbox"> <div class="checkbox">
<label for="enableTray"> <label for="enableTray">

View File

@ -34,6 +34,7 @@ export class SettingsComponent implements OnInit {
pin: boolean = null; pin: boolean = null;
disableFavicons: boolean = false; disableFavicons: boolean = false;
enableBrowserIntegration: boolean = false; enableBrowserIntegration: boolean = false;
enableBrowserIntegrationFingerprint: boolean = false;
enableMinToTray: boolean = false; enableMinToTray: boolean = false;
enableCloseToTray: boolean = false; enableCloseToTray: boolean = false;
enableTray: boolean = false; enableTray: boolean = false;
@ -150,6 +151,7 @@ export class SettingsComponent implements OnInit {
this.disableFavicons = await this.storageService.get<boolean>(ConstantsService.disableFaviconKey); this.disableFavicons = await this.storageService.get<boolean>(ConstantsService.disableFaviconKey);
this.enableBrowserIntegration = await this.storageService.get<boolean>( this.enableBrowserIntegration = await this.storageService.get<boolean>(
ElectronConstants.enableBrowserIntegration); ElectronConstants.enableBrowserIntegration);
this.enableBrowserIntegrationFingerprint = await this.storageService.get<boolean>(ElectronConstants.enableBrowserIntegrationFingerprint);
this.enableMinToTray = await this.storageService.get<boolean>(ElectronConstants.enableMinimizeToTrayKey); this.enableMinToTray = await this.storageService.get<boolean>(ElectronConstants.enableMinimizeToTrayKey);
this.enableCloseToTray = await this.storageService.get<boolean>(ElectronConstants.enableCloseToTrayKey); this.enableCloseToTray = await this.storageService.get<boolean>(ElectronConstants.enableCloseToTrayKey);
this.enableTray = await this.storageService.get<boolean>(ElectronConstants.enableTrayKey); this.enableTray = await this.storageService.get<boolean>(ElectronConstants.enableTrayKey);
@ -348,9 +350,27 @@ export class SettingsComponent implements OnInit {
} }
async saveBrowserIntegration() { async saveBrowserIntegration() {
if (process.platform ==='darwin' && !this.platformUtilsService.isMacAppStore()) {
await this.platformUtilsService.showDialog(
this.i18nService.t('browserIntegrationMasOnlyDesc'),
this.i18nService.t('browserIntegrationMasOnlyTitle'),
this.i18nService.t('ok'), null, 'warning');
this.enableBrowserIntegration = false;
return;
}
await this.storageService.save(ElectronConstants.enableBrowserIntegration, this.enableBrowserIntegration); await this.storageService.save(ElectronConstants.enableBrowserIntegration, this.enableBrowserIntegration);
this.messagingService.send( this.messagingService.send(this.enableBrowserIntegration ? 'enableBrowserIntegration' : 'disableBrowserIntegration');
this.enableBrowserIntegration ? 'enableBrowserIntegration' : 'disableBrowserIntegration');
if (!this.enableBrowserIntegration) {
this.enableBrowserIntegrationFingerprint = false;
this.saveBrowserIntegrationFingerprint();
}
}
async saveBrowserIntegrationFingerprint() {
await this.storageService.save(ElectronConstants.enableBrowserIntegrationFingerprint, this.enableBrowserIntegrationFingerprint);
} }
private callAnalytics(name: string, enabled: boolean) { private callAnalytics(name: string, enabled: boolean) {

View File

@ -135,7 +135,7 @@ const eventService = new EventService(storageService, apiService, userService, c
const systemService = new SystemService(storageService, vaultTimeoutService, messagingService, platformUtilsService, const systemService = new SystemService(storageService, vaultTimeoutService, messagingService, platformUtilsService,
null); null);
const nativeMessagingService = new NativeMessagingService(cryptoFunctionService, cryptoService, platformUtilsService, const nativeMessagingService = new NativeMessagingService(cryptoFunctionService, cryptoService, platformUtilsService,
logService, i18nService, userService, messagingService); logService, i18nService, userService, messagingService, vaultTimeoutService, storageService);
const analytics = new Analytics(window, () => isDev(), platformUtilsService, storageService, appIdService); const analytics = new Analytics(window, () => isDev(), platformUtilsService, storageService, appIdService);
containerService.attachToGlobal(window); containerService.attachToGlobal(window);

View File

@ -1453,15 +1453,33 @@
"enableBrowserIntegrationDesc": { "enableBrowserIntegrationDesc": {
"message": "Browser integration is used for biometrics in browser." "message": "Browser integration is used for biometrics in browser."
}, },
"browserIntegrationMasOnlyTitle": {
"message": "Browser integration not supported"
},
"browserIntegrationMasOnlyDesc": {
"message": "Unfortunately browser integration is only supported in the Mac App Store version for now."
},
"enableBrowserIntegrationFingerprint": {
"message": "Require verification for browser integration"
},
"enableBrowserIntegrationFingerprintDesc": {
"message": "Enable an additional layer of security by requiring fingerprint phrase validation when establishing a link between your desktop and browser. When enabled, this requires user intervention and verification each time a connection is established."
},
"approve": { "approve": {
"message": "Approve" "message": "Approve"
}, },
"verifyBrowserTitle": { "verifyBrowserTitle": {
"message": "Verify browser connection" "message": "Verify browser connection"
}, },
"verifyBrowserDescription": { "verifyBrowserDesc": {
"message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension." "message": "Please ensure the shown fingerprint is identical to the fingerprint showed in the browser extension."
}, },
"biometricsNotEnabledTitle": {
"message": "Biometrics not enabled"
},
"biometricsNotEnabledDesc": {
"message": "Browser biometrics requires desktop biometrics to be enabled in the settings first."
},
"personalOwnershipSubmitError": { "personalOwnershipSubmitError": {
"message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections." "message": "Due to an Enterprise Policy, you are restricted from saving items to your personal vault. Change the Ownership option to an organization and choose from available Collections."
}, },

View File

@ -114,7 +114,7 @@ export class Main {
if (process.platform === 'win32') { if (process.platform === 'win32') {
const BiometricWindowsMain = require('jslib/electron/biometric.windows.main').default; const BiometricWindowsMain = require('jslib/electron/biometric.windows.main').default;
this.biometricMain = new BiometricWindowsMain(this.storageService, this.i18nService); this.biometricMain = new BiometricWindowsMain(this.storageService, this.i18nService, this.windowMain);
} else if (process.platform === 'darwin') { } else if (process.platform === 'darwin') {
const BiometricDarwinMain = require('jslib/electron/biometric.darwin.main').default; const BiometricDarwinMain = require('jslib/electron/biometric.darwin.main').default;
this.biometricMain = new BiometricDarwinMain(this.storageService, this.i18nService); this.biometricMain = new BiometricDarwinMain(this.storageService, this.i18nService);

View File

@ -10,6 +10,7 @@ import { WindowMain } from 'jslib/electron/window.main';
export class NativeMessagingMain { export class NativeMessagingMain {
private connected = false; private connected = false;
private socket: any;
constructor(private logService: LogService, private windowMain: WindowMain, private userPath: string, private appPath: string) {} constructor(private logService: LogService, private windowMain: WindowMain, private userPath: string, private appPath: string) {}
@ -19,14 +20,15 @@ export class NativeMessagingMain {
ipc.serve(() => { ipc.serve(() => {
ipc.server.on('message', (data: any, socket: any) => { ipc.server.on('message', (data: any, socket: any) => {
// This is a ugly hack until electron is updated 7.0.0 which supports ipcMain.invoke this.socket = socket;
this.windowMain.win.webContents.send('nativeMessaging', data); this.windowMain.win.webContents.send('nativeMessaging', data);
ipcMain.once('nativeMessagingReply', (event, msg) => { });
if (msg != null) {
this.send(msg, socket); ipcMain.on('nativeMessagingReply', (event, msg) => {
if (this.socket != null && msg != null) {
this.send(msg, this.socket);
} }
}); })
});
ipc.server.on('connect', () => { ipc.server.on('connect', () => {
this.connected = true; this.connected = true;
@ -36,6 +38,7 @@ export class NativeMessagingMain {
'socket.disconnected', 'socket.disconnected',
(socket: any, destroyedSocketID: any) => { (socket: any, destroyedSocketID: any) => {
this.connected = false; this.connected = false;
this.socket = null;
ipc.log( ipc.log(
'client ' + destroyedSocketID + ' has disconnected!' 'client ' + destroyedSocketID + ' has disconnected!'
); );

View File

@ -83,7 +83,11 @@ export default class NativeMessage {
chunks.push(chunk); chunks.push(chunk);
} }
try {
processData(); processData();
} catch(e) {
console.error(e);
}
}); });
} }
} }

View File

@ -8,29 +8,38 @@ import { LogService } from 'jslib/abstractions/log.service';
import { MessagingService } from 'jslib/abstractions/messaging.service'; import { MessagingService } from 'jslib/abstractions/messaging.service';
import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service'; import { PlatformUtilsService } from 'jslib/abstractions/platformUtils.service';
import { UserService } from 'jslib/abstractions/user.service'; import { UserService } from 'jslib/abstractions/user.service';
import { VaultTimeoutService } from 'jslib/abstractions/vaultTimeout.service';
import { Utils } from 'jslib/misc/utils'; import { Utils } from 'jslib/misc/utils';
import { SymmetricCryptoKey } from 'jslib/models/domain/symmetricCryptoKey'; import { SymmetricCryptoKey } from 'jslib/models/domain/symmetricCryptoKey';
import { StorageService } from 'jslib/abstractions';
import { ElectronConstants } from 'jslib/electron/electronConstants';
const MessageValidTimeout = 10 * 1000; const MessageValidTimeout = 10 * 1000;
const EncryptionAlgorithm = 'sha1'; const EncryptionAlgorithm = 'sha1';
export class NativeMessagingService { export class NativeMessagingService {
private sharedSecret: any; private sharedSecrets = new Map<string, SymmetricCryptoKey>();
constructor(private cryptoFunctionService: CryptoFunctionService, private cryptoService: CryptoService, constructor(private cryptoFunctionService: CryptoFunctionService, private cryptoService: CryptoService,
private platformUtilService: PlatformUtilsService, private logService: LogService, private i18nService: I18nService, private platformUtilService: PlatformUtilsService, private logService: LogService, private i18nService: I18nService,
private userService: UserService, private messagingService: MessagingService) { private userService: UserService, private messagingService: MessagingService, private vaultTimeoutService: VaultTimeoutService, private storageService: StorageService) {
ipcRenderer.on('nativeMessaging', async (event: any, message: any) => { ipcRenderer.on('nativeMessaging', async (event: any, message: any) => {
this.messageHandler(message); this.messageHandler(message);
}); });
} }
private async messageHandler(rawMessage: any) { private async messageHandler(msg: any) {
const appId = msg.appId;
const rawMessage = msg.message;
// Request to setup secure encryption // Request to setup secure encryption
if (rawMessage.command === 'setupEncryption') { if (rawMessage.command === 'setupEncryption') {
const remotePublicKey = Utils.fromB64ToArray(rawMessage.publicKey).buffer; const remotePublicKey = Utils.fromB64ToArray(rawMessage.publicKey).buffer;
if (await this.storageService.get<boolean>(ElectronConstants.enableBrowserIntegrationFingerprint)) {
ipcRenderer.send('nativeMessagingReply', {command: 'verifyFingerprint', appId: appId});
const fingerprint = (await this.cryptoService.getFingerprint(await this.userService.getUserId(), remotePublicKey)).join(' '); const fingerprint = (await this.cryptoService.getFingerprint(await this.userService.getUserId(), remotePublicKey)).join(' ');
this.messagingService.send('setFocus'); this.messagingService.send('setFocus');
@ -38,7 +47,7 @@ export class NativeMessagingService {
// Await confirmation that fingerprint is correct // Await confirmation that fingerprint is correct
const submitted = await Swal.fire({ const submitted = await Swal.fire({
title: this.i18nService.t('verifyBrowserTitle'), title: this.i18nService.t('verifyBrowserTitle'),
html: `${this.i18nService.t('verifyBrowserDescription')}<br><br><strong>${fingerprint}</strong>`, html: `${this.i18nService.t('verifyBrowserDesc')}<br><br><strong>${fingerprint}</strong>`,
showCancelButton: true, showCancelButton: true,
cancelButtonText: this.i18nService.t('cancel'), cancelButtonText: this.i18nService.t('cancel'),
showConfirmButton: true, showConfirmButton: true,
@ -49,16 +58,17 @@ export class NativeMessagingService {
if (submitted.value !== true) { if (submitted.value !== true) {
return; return;
} }
}
this.secureCommunication(remotePublicKey); this.secureCommunication(remotePublicKey, appId);
return; return;
} }
const message = JSON.parse(await this.cryptoService.decryptToUtf8(rawMessage, this.sharedSecret)); const message = JSON.parse(await this.cryptoService.decryptToUtf8(rawMessage, this.sharedSecrets.get(appId)));
// Shared secret is invalidated, force re-authentication // Shared secret is invalidated, force re-authentication
if (message == null) { if (message == null) {
ipcRenderer.send('nativeMessagingReply', {command: 'invalidateEncryption'}); ipcRenderer.send('nativeMessagingReply', {command: 'invalidateEncryption', appId: appId});
return; return;
} }
@ -70,14 +80,26 @@ export class NativeMessagingService {
switch (message.command) { switch (message.command) {
case 'biometricUnlock': case 'biometricUnlock':
if (! this.platformUtilService.supportsBiometric()) { if (! this.platformUtilService.supportsBiometric()) {
return this.send({command: 'biometricUnlock', response: 'not supported'}); return this.send({command: 'biometricUnlock', response: 'not supported'}, appId);
}
if (! await this.vaultTimeoutService.isBiometricLockSet()) {
this.send({command: 'biometricUnlock', response: 'not enabled'}, appId);
return await Swal.fire({
title: this.i18nService.t('biometricsNotEnabledTitle'),
text: this.i18nService.t('biometricsNotEnabledDesc'),
showCancelButton: true,
cancelButtonText: this.i18nService.t('cancel'),
showConfirmButton: false,
});
} }
const response = await this.platformUtilService.authenticateBiometric(); const response = await this.platformUtilService.authenticateBiometric();
if (response) { if (response) {
this.send({command: 'biometricUnlock', response: 'unlocked', keyB64: (await this.cryptoService.getKey()).keyB64}); this.send({command: 'biometricUnlock', response: 'unlocked', keyB64: (await this.cryptoService.getKey()).keyB64}, appId);
} else { } else {
this.send({command: 'biometricUnlock', response: 'canceled'}); this.send({command: 'biometricUnlock', response: 'canceled'}, appId);
} }
break; break;
@ -86,19 +108,19 @@ export class NativeMessagingService {
} }
} }
private async send(message: any) { private async send(message: any, appId: string) {
message.timestamp = Date.now(); message.timestamp = Date.now();
const encrypted = await this.cryptoService.encrypt(JSON.stringify(message), this.sharedSecret); const encrypted = await this.cryptoService.encrypt(JSON.stringify(message), this.sharedSecrets.get(appId));
ipcRenderer.send('nativeMessagingReply', encrypted); ipcRenderer.send('nativeMessagingReply', {appId: appId, message: encrypted});
} }
private async secureCommunication(remotePublicKey: ArrayBuffer) { private async secureCommunication(remotePublicKey: ArrayBuffer, appId: string) {
const secret = await this.cryptoFunctionService.randomBytes(64); const secret = await this.cryptoFunctionService.randomBytes(64);
this.sharedSecret = new SymmetricCryptoKey(secret); this.sharedSecrets.set(appId, new SymmetricCryptoKey(secret));
const encryptedSecret = await this.cryptoFunctionService.rsaEncrypt(secret, remotePublicKey, EncryptionAlgorithm); const encryptedSecret = await this.cryptoFunctionService.rsaEncrypt(secret, remotePublicKey, EncryptionAlgorithm);
ipcRenderer.send('nativeMessagingReply', {command: 'setupEncryption', sharedSecret: Utils.fromBufferToB64(encryptedSecret)}); ipcRenderer.send('nativeMessagingReply', {appId: appId, command: 'setupEncryption', sharedSecret: Utils.fromBufferToB64(encryptedSecret)});
} }
} }