Skip to content

Brainstorming on the interaction with the Tiltify API #15

@Alastor-git

Description

@Alastor-git

How things currently are :

  • ClientId and ClientSecret are embedded in the code of the integration
  • On Tiltify's side, the app client account creates an application in the website declaring the App name, Redirect URI and description. Client Id and Secret are App specific
  • They are used in the requests, and the redirect URI is MUST match between Website and Request.
  • User grants authorization following OAuth2 code grant flow.
  • Token and refresh tokens are then used to make requests to the API endpoints
  • Client Secret and Id are provided in the body of the requests.

Knee jerk reaction:

  • Uh oh, credentials being part of the code is BAD. This Must be eliminated.
  • Ideal would be to ask user to configure their own credentials and provide them as script parameters.

It would require users to configure the App on their Tiltify website, but if that's just creating an App with a link, that's still doable with clear enough instructions. Although not ideal.

The problem:

  • Currently, we're requesting new donations on a regular basis. But that a lot of unnecessary requests and can only access public data.
  • There is an EventSub interface with webhooks that could have several advantages.
    • Reduction in number of requests
    • Reduced delays in receiving data
    • Able to access private data such as custom answer
  • BUT the drawback is :
    • Webhooks must be declared on the website.
      That becomes impractical to ask each user to do it, this is significantly more burden than just declaring the App.
    • Webhooks can't redirect to localhost.
      Does that mean I'd need a publically available server to interface ?
      That would make the whole thing impractical.

So that triggered me to do a little bit of reading.

Relevant RFCs

What they have to say on the topic

TLDR on the RFCs

  • We are what's considered a public client, and more specifically a native app.
  • Our code being hosted on the client side, we can't be protected from reverse engineering of our code and credentials.
  • As such, our client secret is useless. At best, it's redundant with our client Id.
  • Our client secret shouldn't be relied on as proof that we're us.

Client types

RFC6749 - The OAuth 2.0 Authorization Framework - Section 2.1

Public

Clients incapable of maintaining the confidentiality of their credentials (e.g., clients executing on the device used by the resource owner, such as an installed native application or a web browser-based application), and incapable of secure client authentication via any other means.

Native Application

A native application is a public client installed and executed on the device used by the resource owner. Protocol data and credentials are accessible to the resource owner. It is assumed that any client authentication credentials included in the application can be extracted. On the other hand, dynamically issued credentials such as access tokens or refresh tokens can receive an acceptable level of protection. At a minimum, these credentials are protected from hostile servers with which the application may interact. On some platforms, these credentials might be protected from other applications residing on the same device.

Don't Store Credentials in Code or Resources Bundled with Software Packages

RFC6819 - OAuth 2.0 Threat Model and Security Considerations - Section 5.3.1

Because of the number of copies of client software, there is limited benefit in creating a single client id and secret that is shared by all installations of an application. Such an application by itself would be considered a "public" client, as it cannot be presumed to be able to keep client secrets. A secret, burned into the source code of the application or an associated resource bundle, cannot be protected from reverse engineering. Secondly, such secrets cannot be revoked, since this would immediately put all installations out of work. Moreover, since the authorization server cannot really trust the client's identifier, it would be dangerous to indicate to end users the trustworthiness of the client.

Client Authentication

RFC8252 - OAuth 2.0 for Native Apps - Section 8.5

Secrets that are statically included as part of an app distributed to multiple users should not be treated as confidential secrets, as one user may inspect their copy and learn the shared secret. For this reason, and those stated in Section 5.3.1 of [RFC6819], it is NOT RECOMMENDED for authorization servers to require client authentication of public native apps clients using a shared secret, as this serves little value beyond client identification which is already provided by the "client_id" request parameter.
Authorization servers that still require a statically included shared secret for native app clients MUST treat the client as a public client (as defined by Section 2.1 of OAuth 2.0 [RFC6749]), and not accept the secret as proof of the client's identity. Without additional measures, such clients are subject to client impersonation (see Section 8.6).

Current thoughts on the topic

The only thing Tiltify relies on using our client Id and Secret is to know the redirect URI for our authentication requests.
Our Id and Secret can't expose anything on the maintainer's account.
So having them bundled with the App isn't so bad.
The secret is useless and I would come to question why we're required to provide it, but on the other hand, it doesn't pose a security threat as things are.

The client Id is the one that identifies our app, and all the important information is which user granted our app access to its campaign and on which scopes (even though currently, the only scope is public, soooo ...).
So even if someone were to take our client Id and Secret and were to impersonate us, they couldn't do anything with that except for emulating Firebot's backend API to request an access grant from the user. AKA the exact same they could do with any other account, but more impractical. No benefit.

Using EventSub would be nice.
It would shift the burden from us making many requests to Tiltify, most of them useless, to Tiltify sending us just as many requests as required.
But I have no current idea how webhooks would work within Firebot and I'm not even certain this is feasible without setting up a relay server.
My current intuition is it's much more complicated to setup than it should.
Having the Tiltify server initiate contact with the user would also pose serious questions in terms of firewalls etc.

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationenhancementNew feature or request

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions