Skip to content

Initial PoC of spoofing Android OAuth#819

Draft
sigaloid wants to merge 12 commits into
masterfrom
oauth_spoof
Draft

Initial PoC of spoofing Android OAuth#819
sigaloid wants to merge 12 commits into
masterfrom
oauth_spoof

Conversation

@sigaloid

@sigaloid sigaloid commented Jun 6, 2023

Copy link
Copy Markdown
Member

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

sigaloid commented Jun 8, 2023

Copy link
Copy Markdown
Member Author

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

Comment thread Cargo.toml
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
Copy Markdown
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

luphoria commented Jun 9, 2023

Copy link
Copy Markdown

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

sigaloid commented Jun 9, 2023

Copy link
Copy Markdown
Member Author

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

Tokarak commented Jun 23, 2023

Copy link
Copy Markdown
Contributor

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

@sigaloid

Copy link
Copy Markdown
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
Copy Markdown

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

sigaloid commented Dec 6, 2023

Copy link
Copy Markdown
Member Author

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.

4 participants