Renato
Renato

Reputation: 13720

How to allow a public app to connect to the GitHub API v4 without an access token?

I have decided to try to manage releases of one of my apps on GitHub as with GitHub Actions, I can build on Mac, Linux and Windows and automatically push the artifacts to the GitHub Releases page, where anyone can go and download the app from.

However, I want my app to self-update, so the app itself also needs to be able to query what's the latest version in the repo releases, and then download the relevant asset for the user's OS... which I thought would be a non-issue... however, there's no way to access the GitHub API v4 without either an OAuth app or a personal access token.

I don't want an OAuth app because the users of my app are absolutely not expected to be GitHub customers. So I tried to use a personal access token whose only scope was access to public release assets (which, again, is a public resource anyone can go and manually download).

As this token can't do anything you or anyone else can't do manually, even without a GitHub account, I thought it would be fine to put the token in the source code of my application, but GitHub revokes the token when it detects it on a commit.

Is there a good way to work around this? Should I put the token in a GitHub secret and then try to replace a placeholder with it during compilation?? I wanted to avoid that as that makes it hard for me to test the app locally, and also, it doesn't solve anything as anyone can easily decompile the app and find the token there (supposing GitHub would not detect the secret is present in the "processed" sources during compilation).

Any suggestions would be appreciated.

Upvotes: 5

Views: 2967

Answers (1)

Brendan Forster
Brendan Forster

Reputation: 2718

however, there's no way to access the GitHub API v4 without either an OAuth app or a personal access token.

The GitHub API v3 does support unauthenticated calls, but it's limited to 60 requests/hr per IP address: https://developer.github.com/v3/#rate-limiting

For unauthenticated requests, the rate limit allows for up to 60 requests per hour. Unauthenticated requests are associated with the originating IP address, and not the user making requests.

The Latest Release API docs will show you what information is returned, but I suspect you'll need to make a secondary call to List Assets for a release to know the files the client needs to download.

If that's not satisfactory (e.g. you know you'll have many clients try to update using the same IP address), and you'd like to ensure they aren't being rate-limited, read on for a different approach.

Is there a good way to work around this?

How I would tackle this is by deploying a small web service (e.g. Heroku dyno) that your app can will call without needing authentication, which then performs the actual lookup for the latest version (using a PAT that gets embedded as an environment variable) and returns a simple JSON response that the client will understand.

Benefits:

  • no token embedded in client
    • development mode can even call same service
  • add logic to service that the client would perform to simplify your app
    • e.g. call /latest/beta or /latest/stable to indicate it's looking for a specific channel
    • perform both API calls and return the assets that the client needs
  • can update token in service whenever necessary (e.g. to refresh token) without changing client
  • can cache response to reduce risk of being rate-limited

Downsides:

  • more moving parts to manage in your overall architecture
  • need to worry about uptime of the service if there are lots of clients connecting
    • this can be offset by making the client resilient to failure cases

Upvotes: 1

Related Questions