Mandate auth token to connect over TCP

Summary:
Until now, launching flipper-server with TCP would accept any incoming connection as long as it comes from the same origin (localhost) using web socket host origin verification.

This is not entirely secure as origin can be spoofed with tools like curl.

Our team created a security review and a proposal was written:
https://docs.google.com/document/d/16iXypCQibPiner061SoaQUFUY9tLVAEpkKfV_hUXI7c/

Effectively, Flipper can generate a token which is then used by the client to authenticate.

This diff contains the changes required to generate, obtain, and validate authentication tokens from clients connecting to flipper over TCP connections.

The token itself is a JWT token. JWT was chosen because it is a simple industry standard which offers three features which can immediately benefit us:

- Expiration handling. No need for Flipper to store this information anywhere.
- Payload. Payload can be used to push any data we deem relevant i.e. unix username.
- Signing. Signed and verified using the same server key pair which is already in place for certificate exchange.

Additionally, the token is stored in the Flipper static folder. This ensures that the browser and PWA clients have access to it.

Reviewed By: mweststrate

Differential Revision: D45179654

fbshipit-source-id: 6761bcb24f4ba30b67d1511cde8fe875158d78af
This commit is contained in:
Lorenzo Blasa
2023-05-05 07:52:13 -07:00
committed by Facebook GitHub Bot
parent 70cdc9bedc
commit 238f40f55d
9 changed files with 209 additions and 75 deletions

View File

@@ -21,6 +21,7 @@ import {initCompanionEnv} from 'flipper-server-companion';
import {startFlipperServer, startServer} from 'flipper-server-core';
import {isTest} from 'flipper-common';
import exitHook from 'exit-hook';
import {getAuthToken} from 'flipper-server-core';
const argv = yargs
.usage('yarn flipper-server [args]')
@@ -163,7 +164,7 @@ process.on('unhandledRejection', (reason, promise) => {
});
start()
.then(() => {
.then(async () => {
if (!argv.tcp) {
console.log('Flipper server started and listening');
return;
@@ -171,7 +172,8 @@ start()
console.log(
'Flipper server started and listening at port ' + chalk.green(argv.port),
);
const url = `http://localhost:${argv.port}`;
const token = await getAuthToken();
const url = `http://localhost:${argv.port}?token=${token}`;
console.log('Go to: ' + chalk.green(chalk.bold(url)));
if (argv.open) {
open(url);