threadsjs / threads.js

A Node.js library for the Threads API
MIT License
279 stars 29 forks source link

2-Factor Authentication #18

Closed sooluh closed 1 year ago

sooluh commented 1 year ago

I think the title is self-explanatory, hehe

elijah-wright commented 1 year ago

this is going to take some time so I'm going to keep this open. if anyone has any ideas on how to tackle this please send them here lol.

I might be able to enable 2FA on my account and see what calls are being made but I want to make sure I can get all the endpoints first because that's more important right now.

derisiontest commented 1 year ago

It would be great if you can get a a hand on the 2FA issues first, as I believe there are more people with 2FA enabled than 2FA disable. Thanks for the repo!

sooluh commented 1 year ago

I got something here @elijah-wright.

When I call the endpoint /api/v1/bloks/apps/com.bloks.www.bloks.caa.login.async.send_login_request/, as you guys know, we will get huge JSON there.

I noticed one key, namely two_factor_identifier and trusted_notification_polling_nonce. Then at intervals, Threads keep making requests to the endpoint /api/v1/two_factor/check_trusted_notification_status/, where the request header looks like this:

POST /api/v1/two_factor/check_trusted_notification_status/ HTTP/2
Host: i.instagram.com
X-Ig-App-Locale: en_US
X-Ig-Device-Locale: en_US
X-Ig-Mapped-Locale: en_US
X-Pigeon-Session-Id: UFS-fb74e206-bf44-4a25-ac3a-7530b7a66862-0
X-Pigeon-Rawclienttime: 1688869951.542
X-Ig-Bandwidth-Speed-Kbps: -1.000
X-Ig-Bandwidth-Totalbytes-B: 0
X-Ig-Bandwidth-Totaltime-Ms: 0
X-Bloks-Version-Id: 5f56efad68e1edec7801f630b5c122704ec5378adbee6609a448f105f34a9c73
X-Ig-Www-Claim: 0
X-Bloks-Is-Layout-Rtl: false
X-Ig-Device-Id: 3fe9d785-c663-4d65-a377-9772cc086f8f
X-Ig-Family-Device-Id: 36c762e1-dc73-4d87-b02f-0723a0e4e9c1
X-Ig-Android-Id: android-75e76fb4f6897be0
X-Ig-Timezone-Offset: 25200
X-Ig-Nav-Chain: TwoFacLoginVerifyFragment:two_fac:1:button:1688869948.526::
X-Fb-Connection-Type: WIFI
X-Ig-Connection-Type: WIFI
X-Ig-Capabilities: 3brTv10=
X-Ig-App-Id: 3419628305025917
Priority: u=3
User-Agent: Barcelona 289.0.0.77.109 Android (33/13; 560dpi; 1440x3036; Google/google; sdk_gphone_x86_64; emu64xa; ranchu; en_US; 489720161)
Accept-Language: en-US
X-Mid: ZKoXywABAAHrsWHm2AF23gP0lQ2f
Ig-Intended-User-Id: 0
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 251
Accept-Encoding: gzip, deflate
X-Fb-Http-Engine: Liger
X-Fb-Client-Ip: True
X-Fb-Server-Cluster: True

two_factor_identifier=$2FA_IDENTIFIER&username=$USERNAME&device_id=android-$DEVICE_ID&trusted_notification_polling_nonces=%5B%22$NONCE%22%5D

Notes:

I'll try using a 2-factor authentication app, or using OTP via Airtime after this.

elijah-wright commented 1 year ago

awesome, I was just going to leave a comment about how I was going to start working on this. I'll be awaiting your next comment

derisiontest commented 1 year ago

@sooluh are you using frida to ssl unpin? I've tried with installing a certificate at root level, but the app still refuse to serve the requests through my proxy. I can help if I can get a hand on this.

sooluh commented 1 year ago

For 2FA using TOTP, the application makes a request to the /api/v1/accounts/two_factor_login/ endpoint, and takes the signed_body parameter as such

signed_body=SIGNATURE.%7B%22verification_code%22%3A%22$TOTP_VALUE%22%2C%22phone_id%22%3A%22$FAMILY_DEVICE_ID%22%2C%22two_factor_identifier%22%3A%22$2FA_IDENTIFIER%22%2C%22username%22%3A%22$USERNAME%22%2C%22trust_this_device%22%3A%221%22%2C%22guid%22%3A%223fe9d785-c663-4d65-a377-9772cc086f8f%22%2C%22device_id%22%3A%22android-75e76fb4f6897be0%22%2C%22waterfall_id%22%3A%22$WATERFALL_ID%22%2C%22verification_method%22%3A%223%22%7D

There you get the JSON that must be sent, then it is encoded with URI encode and prepend with the string SIGNATURE.

{
  "verification_code": "$TOTP_VALUE",
  "phone_id": "$FAMILY_DEVICE_ID",
  "two_factor_identifier": "$2FA_IDENTIFIER",
  "username": "$USERNAME",
  "trust_this_device": "1",
  "guid": "$IG_DEVICE_ID",
  "device_id": "android-$DEVICE_ID",
  "waterfall_id": "$WATERFALL_ID",
  "verification_method": "3"
}

You may be quite confused by the new variables, and I'll explain.

$TOTP_VALUE must be obtained from your OTP application, and $2FA_IDENTIFIER, $USERNAME and $DEVICE_ID must be known.

$FAMILY_DEVICE_ID is UUID v4 which should be sent with params and request headers when logging in, you can check my previous comment on the X-Ig-Family-Device-Id header.

$IG_DEVICE_ID (guid) is the same as $FAMILY_ID, check the X-Ig-Device-Id header for the value.

$WATERFALL_ID is the same as the v4 UUID and should be sent in the params at login, but not in the header (or maybe I wasn't careful enough).

More or less the params sent at login are like this, they should be

{
  "client_input_params": {
    "device_id": "android-$DEVICE_ID",
    "password": "$PASSWORD",
    "family_device_id": "$FAMILY_DEVICE_ID",
    "contact_point": "$USERNAME"
  },
  "server_params": {
    "device_id": "android-$DEVICE_ID",
    "waterfall_id": "$WATERFALL_ID",
    "credential_type": "password",
    "family_device_id": "$FAMILY_DEVICE_ID"
  }
}

But if $FAMILY_DEVICE_ID, $IG_DEVICE_ID and $WATERFALL_ID are optional, then we don't need to add these right?

elijah-wright commented 1 year ago

yeah, don't add optional parameters for now. anything that we can cut back on in the library, we should. I get what you're saying, it's just a different endpoint

if you think you've figured it out, make a pr and I'll merge it 👍

sooluh commented 1 year ago

I'm working on it, there's an error code in the reply function, there's already a pull request on #25, maybe you can merge it first.

oh btw, where should I put the utility code to parse the response? guide me so that I adapt your coding style.

elijah-wright commented 1 year ago

the request function in the REST manager will handle everything. for advanced POST requests, look at the create function in the post manager. parsing the response isn't necessary since it's turned into JSON. eventually I'll combine it with typings. if you absolutely need utility code, you can put it outside of the class in the manager

sooluh commented 1 year ago

hi, in getToken function, it takes id from this.androidId, while getToken function is outside Client object, how to solve this?

elijah-wright commented 1 year ago

there was some pr that changed that, just fixed it now

sooluh commented 1 year ago

I have just made a pull request on #28. Next, I need to implement the 2FA methods through WhatsApp OTP, authenticator app, and SMS (airtime)

Edit: I changed my mind, how can a static program be interactive and ask to enter an OTP code, it seems unnecessary, hehe.

elijah-wright commented 1 year ago

alr, good work everyone. closing this now, if there are any issues with the pr open another issue