Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial PoC of spoofing Android OAuth #819

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from
Draft

Initial PoC of spoofing Android OAuth #819

wants to merge 12 commits into from

Conversation

sigaloid
Copy link
Member

@sigaloid sigaloid commented Jun 6, 2023

This is a proof of concept of using the Android OAuth endpoints to create an anonymous "android user" that then authorizes all requests. Couple of caveates:

  • Does not use GraphQL endpoints at all.
    • GQL is faster and less rate-limited
    • GQL is likely going to be more stable or at least harder to block - android client doesn't necessarily use the OAuth endpoints I've used here so it's theoretically possible for them to block (the mobile clients do use these endpoints)
    • GQL would likely require at least a whole new library dedicated to GraphQL API, whereas this was as easy as token handling + replacing www.reddit.com with oauth.reddit.com

For these reasons I want to pivot to GQL endpoints in the future hopefully, but as these endpoints are used by the official client, it's not strictly necessary to match behavior.

  • DOES identify itself as an Android device, in headers.
    • DOES NOT need the HMAC secret key that was reverse engineered out of the APK, since no accounts are logging in
  • DOES NOT handle re-authenticating. Looks like the token expires after 24 hours. I'd like to figure out the proper way to refresh a token so the behavior more closely matches. Not sure exactly how to do that right now. Technically, since I'm just using OAuth endpoints, I could refresh them the normal way, but perhaps there's something special the real client does? (I worry that I must match the behavior exactly or else this will just be a cat and mouse game) Update: Simply sending the same request is sufficient. There's no state kept between tokens to ensure continuity. Sending x-reddit-loid header along doesn't hurt though, to look more realistic.
  • Technically, does not actually pretend to be an android client to the letter - it just asks to log in as one then authenticates into the regular OAuth endpoints. This is definitely not standard behavior - for that I'd need to implement GQL. I doubt they're doing intense checking of this though. The official clients do use these endpoints in addition to GQL.

Related to #785 #818.

HUGE thanks to @hogseedy and @/costco on Hacker News for the sample code. I'm just dipping my toes in with the OAuth endpoints, haven't yet touched the GQL ones.

TODO:

  • Token refreshing

@sigaloid
Copy link
Member Author

sigaloid commented Jun 8, 2023

I've added automatic token refreshing, it should now handle retrieving a new token when the expiry time elapses.

Comment on lines +33 to +38
uuid = { version = "1.3.3", features = ["v4"] }
base64 = "0.21.2"
fastrand = "1.9.0"
log = "0.4.18"
pretty_env_logger = "0.5.0"
dotenvy = "0.15.7"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uuid: Used for spoofing the device clients
base64: Used for generating the HTTP Basic Auth header
fastrand: Used to generate random devices to spoof
log, pretty_env_logger, dotenvy: Used to improve logging

@sigaloid sigaloid mentioned this pull request Jun 8, 2023
@luphoria
Copy link

luphoria commented Jun 9, 2023

Is it planned/considered to wrap the oauth spoof around a proxy which functions like original reddit API? I think a setup like that would be better longterm to avoid hardcoding lots of endpoints, and then those endpoints changing

@sigaloid
Copy link
Member Author

sigaloid commented Jun 9, 2023

I'm not sure what you mean by wrapping the oauth spoof around a proxy. It's currently just using the same endpoints that we used before, except with oauth.reddit.com as the root domain instead of www.reddit.com. I don't expect the OAuth API endpoints to change, as this is what real paying API consumers will use. The endpoints I use aren't really "private", just the method used to generate the tokens that makes it appear it's from the official client. (That's the only really "hacky" part of this PR - spoofing of the device)

If we are to use the GraphQL queries in the future, that would definitely be an issue - I wrote a simple library that will allow the map of action titles to action ID's to be updated from the GitHub, without having to update the whole program. But I haven't started the work on that.

@sigaloid sigaloid added this to the 0.31.0 milestone Jun 9, 2023
@Tokarak
Copy link
Contributor

Tokarak commented Jun 23, 2023

BTW is alpha/beta testing required before the June 30th API changes?

@sigaloid
Copy link
Member Author

It works currently, but I've no clue whether it will work after the changes. We're basically stalled until then.

More importantly this code will unfortunately likely never be merged due to legal issues (#785). We will add custom API keys (it'll likely be necessary), but we cannot distribute code that automatically spoofs an official client and generates an API key, due to a myriad of trademark and copyright issues.

The beauty of open source means we can fork whenever we want. 🍴

@maxexcloo
Copy link

Works well! Wonder if it would be worth to merge this and some other PRs (such as #738) into a fork (as it seems like the main repo is dead?)

@sigaloid
Copy link
Member Author

sigaloid commented Dec 6, 2023

I'll be creating a fork like that soon. The legality is on the same level as youtube-dl as I understand it so my previous comment stands corrected.

I'll put a date on it so I force myself to. By the end of this year I'll have created a fork with this and all of the relevant backlogged PRs. I seem to be the only active maintainer so i'll keep that in mind w.r.t. maintenance.

Edit: As promised. https://github.com/redlib-org/redlib/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants