fdgt-apis / rfcs

0 stars 0 forks source link

[RFC] Shared sandboxes #1

Open trezy opened 3 years ago

trezy commented 3 years ago
Authors @trezy
To be reviewed by 06 October, 2020

Need

Developers using fdgt to develop their Twitch applications (bots, overlays, extensions, etc) are often confused by the way that fdgt sandboxes connections. A common refrain is, "I've connected my bot to fdgt... now how do I connect with a chat client to send commands?" This confusion is caused because every connection is isolated inside of its own sandbox. This creates two important conditions:

  1. The benefit is that commands sent to one connection won't affect other connections (e.g., When Bob sends a command, Sally won't see the effects of that command because their connections are completely isolated.
  2. The downside is that developers can't have multiple clients interact with each other. A command scenario would be a streamer creating both a bot and an overlay. Events triggered by the chat connection should trigger actions in both the overlay and the bot simultaneously. This is currently impossible because of the isolated sandbox.

To clear up this confusion and introduce the functionality that developers expect, we need to allow multiple clients to share a sandbox.

Approach

To introduce shared sandboxes, we'll need a few new pieces of infrastructure to be implemented. These span both the fdgt API and website.

  1. Accounts/Logins To create and manage shared sandboxes, users will need to create a fdgt account (not necessarily custom accounts, could also be login with a third party account like Google, Twitter, Github, or Twitch). This allows us to track who is using shared sandboxes in case we need to lock down accounts that are abusing the system.
  2. Sandbox Storage Connections to fdgt will remain isolated in code, but they will be connected by a backend that shares data to all connections that are using the same sandbox.
  3. Programmatic Sandbox API We'll want to create a new API endpoint that allows users to create new sandboxes programmatically. This will be helpful for automated tests to spin create a new sandbox for a test instance, then delete that sandbox after the tests have finished.

Benefits

Introducing shared sandboxes will allow the testing of multiple different scenarios...

Simple manual testing and interaction

When testing a bot against the actual Twitch API, developers can connect their application and a chat client and affect the application by sending messages from their client. Currently, there is no way for multiple clients to interact via the fdgt chat API. This prevents developers from using simple manual testing to verify their connections to fdgt before writing full-fledged tests.

Automated testing

Currently, testing an application against fdgt requires commands to be sent on the same connection as the application being tested. This is problematic if the tests are watching that connection to verify message sending/receipt, or if the framework connecting the application to fdgt needs to be monkey patched to allow the connection to be shared.

Interacting clients

It's not difficult to imagine a developer creating a bot and an overlay and making them both react to the same commands in chat. A contrived example might be a bot that updates a counter field in a database when the !count command is called, while that same command causes the overlay to update an on-screen counter.

Alternatives

Remove sandboxes

This is just a straight up bad idea, but here's the pitch: instead of creating personalized sandboxes, we would remove sandboxes entirely and encourage users to create unique rooms for their test suites.

This is the worst of ideas because it virtually encourages abuse. One user could, in theory, create an application that brute force connects to channels, then sends random messages. This would interfere anytime the application connects to a channel that is currently in use by a test suite. The application could also capture any data sent on the channel, potentially exposing sensitive data that was expected to be sent in secret.

Acknowledgements

Big thanks to @callowcreation, @sadmoody, and @Layla-P for helping flesh out the need for this upgrade

sadmoody commented 3 years ago

You're overthinking it imo @trezy ! One of the nice things about fdgt is that you don't need to change anything except for the server in order for you to connect to it. I think that part of the workflow should remain. Going down the road of user accounts will add an additional barrier to "just getting it working".

I wonder if there's something in the setups already - whether you can use an immediately hashed OAuth token that people have already set up to access a different sandbox. The potential number of hashes that can be created out of the token that's sent to you anyway should be so large that its not worth bruteforcing.

Or maybe even allowing for a subsubdomain to determine the sandbox you join. That way, if someone wants to test something with another user (say, live on twitch), they can easily configure the subsubdomain so that they can connect to the same sandbox.

trezy commented 3 years ago

@sadmoody I really like the subsubdomain idea. That's a keeper, I think. In terms of implementation details, I've been wrestling a bit with how applications would connect to the shared sandbox. Other strategies I had considered...

I wonder if there's something in the setups already - whether you can use an immediately hashed OAuth token that people have already set up to access a different sandbox. The potential number of hashes that can be created out of the token that's sent to you anyway should be so large that its not worth bruteforcing.

I'm not sure I follow on this. Are you saying that fdgt would generate a token when a connection is created, then that token could be used by other applications to connect to the same sandbox? Or that we should support arbitrary tokens, so a test suite could theoretically generate a new token before it connects and use the same token with multiple applications?

sadmoody commented 3 years ago

I'm not sure I follow on this. Are you saying that fdgt would generate a token when a connection is created, then that token could be used by other applications to connect to the same sandbox?

An IRC client cannot connect to the twitch server without supplying an OAuth token. You can use that token to determine the sandbox it gets. So if you want to connect two clients together, they'll both have the same OAuth token. This is already being sent to fdgt as a PASS once a client is connected. Since most of the time, this OAuth token is already there and unique to each person, you can just hash it so you're not storing it on your side in an unsafe way, and use that instead of the subsubdomain.

With that, you'll essentially convert the authentication part of the connection sequence into determining which sandbox the client ends up entering. (i.e. they go to the one which is a hash of whatever they send you as a password - which will be their OAuth token).

That being said, people are sending you their OAuth creds when they connect to fdgt are they not? That's possibly a problem (probably not yours), but I'm not sure what you can do about it exactly.

I still think a subsubdomain is a cleaner solution here.

AlcaDesign commented 3 years ago

An IRC client cannot connect to the twitch server without supplying an OAuth token.

You are definitely able to connect without an OAuth token.

trezy commented 3 years ago

@sadmoody As @AlcaDesign, you can indeed connect without a token.

The issue I'm referring to, though, is that a user may want to perform E2E tests with multiple applications, i.e. multiple tokens. That user should still be able to connect both applications to the sandbox without having to modify anything other than the domain. I think you're right that the subsubdomain approach is still the best option.

sadmoody commented 3 years ago

You are definitely able to connect without an OAuth token.

My mistake, @AlcaDesign and @trezy - I've only had very limited exposure to connections to Twitch chat and my memory of my experience is fuzzy. It was all on stream and done in haste!

If that's the case, then it looks like your two options are either a token/account based approach, or a subsubdomain approach. I'm much more in favour of the latter as it removes additional steps. From a networking/business perspective, it may be valuable to force people to create accounts in order for you to have their emails at least.

You can take both approaches. Do the subsubdomain thing. When people connect to a chatroom, you can send a message to the chatroom on join saying "thank you for using fdgt. you are welcome to continue using this for free. buy me a coffee at _____. If you would like to remove this message, create a free account at link and use the token, otherwise, feel free to ignore" or something a bit more eloquent than that. It'll be pretty non-intrusive, it'll give people a path to removing it, and best of all, not really matter if they don't.