dequis / purple-facebook

Facebook protocol plugin for libpurple (moved from jgeboski/purple-facebook)
GNU General Public License v2.0
954 stars 88 forks source link

Two-factor no longer works? #445

Open jaymzh opened 6 years ago

jaymzh commented 6 years ago

I reported this in the Workplace bug, but it looks like this is now happening on non-workplace. Two-factor no longer works either in app-password mode, nor in login-approval-code mode.

If you use an app password, you just get permission denied (tried with both "username" and "email" as username).

If you use normal password, Pidgin will tell you about the approval code, you then put it in, and it tries to connect for a minute or so, and then eventually you get invalid username or password (401).

jaymzh commented 6 years ago

Oh - so it looks like you can make it work, if, before you put in the 2fac code, you go to the site, then click the "did you log in", click yes, then click "save browser", THEN go back to pidgin and put in the code it works, at least for normal fb.

jaymzh commented 6 years ago

OH! And it works for Workplace too [but the alert comes up on non-workplace]. I'll leave this open for others to find and I'll comment on the workplace thread.

jaymzh commented 6 years ago

Aaaand, no that stopped working. :(

jaymzh commented 5 years ago

@dequis - as of now there's no Facebook or Workplace if you use 2fac (which ... I hope most people do). Pretty please for christmas all I want is a chat client? :) :)

dequis commented 5 years ago

Can't repro :/

19:44 <@dx|fb-2> ac on
19:44 <@root> Trying to get all accounts connected...
19:44 <@root> facebook - Logging in: Authenticating
19:44 <@root> facebook - Login error: Login approvals are on. Expect an SMS shortly with a code to use for log in (406)
19:44 <@root> facebook - Logging in: Signing off..
19:44 <@root> facebook - Logging in: Reconnecting in 5 seconds..
19:44 <@dx|fb-2> ac off
19:44 <@root> Deactivating all active (re)connections...
19:45 <@dx|fb-2> ac facebook set password '028470'
19:45 <@root> Setting changed successfully
19:45 <@dx|fb-2> ac facebook on
19:45 <@root> facebook - Logging in: Authenticating
19:45 <@root> facebook - Logging in: Fetching contacts
19:45 <@root> facebook - Logging in: Connecting
19:45 <@root> facebook - Logging in: Logged in
19:50 <@dx|fb-work2> ac add facebook [...]
19:50 <@root> Account successfully added with tag facebook
19:50 <@root> You can now use the /OPER command to enter the password
19:50 <@root> Password added to IM account facebook
19:50 <@dx|fb-work2> ac facebook set work on
19:50 <@root> work = `on'
19:50 <@dx|fb-work2> ac facebook on
19:50 <@root> facebook - Logging in: Authenticating
19:50 <@root> facebook - Login error: Login approvals are on. Expect an SMS shortly with a code to use for log in (406)
19:50 <@root> facebook - Logging in: Signing off..
19:50 <@root> facebook - Logging in: Reconnecting in 5 seconds..
19:50 <@dx|fb-work2> ac facebook off
19:50 <@root> Reconnect cancelled
19:50 <@dx|fb-work2> ac facebook set password 736178
19:50 <@root> Setting changed successfully
19:50 <@dx|fb-work2> ac facebook on
19:50 <@root> facebook - Logging in: Authenticating
19:50 <@root> facebook - Logging in: Fetching contacts
19:50 <@root> facebook - Logging in: Connecting
19:50 <@root> facebook - Logging in: Logged in
jaymzh commented 5 years ago

I should have sent you a debug log, I suck. Doing so now.

jaymzh commented 5 years ago

So I sent you pidgin debug logs, but just for fun I also tried bitlbee:

11:50 <@phil> account add facebook jaymzh "XXXXXXXXXXXXXXXXXX"
11:50 <@root> Account successfully added with tag facebook
11:50 <@phil> ac on
11:50 <@root> Trying to get all accounts connected...
11:50 <@root> facebook - Logging in: Authenticating
11:51 <@root> facebook - Login error: Login approvals are on. Expect an SMS shortly with a code to use for log in (406)
11:51 <@root> facebook - Logging in: Signing off..
11:51 <@root> facebook - Logging in: Reconnecting in 5 seconds..
11:51 <@root> facebook - Logging in: Authenticating
11:51 <@root> facebook - Login error: Login approvals are on. Expect an SMS shortly with a code to use for log in (406)
11:51 <@root> facebook - Logging in: Signing off..
11:51 <@root> facebook - Logging in: Reconnecting in 15 seconds..
11:51 <@phil> ac off
11:51 <@root> Deactivating all active (re)connections...
11:51 <@phil> ac facebook set password '881202'
11:51 <@root> Setting changed successfully
11:51 <@phil> ac on
11:51 <@root> Trying to get all accounts connected...
11:51 <@root> facebook - Logging in: Authenticating
11:51 <@root> facebook - Login error: Invalid username or password (401)
11:51 <@root> facebook - Logging in: Signing off..
dequis commented 5 years ago

I looked around, seems that there's a new auth path like this:

I drafted an implementation of this with a python script, but the server doesn't like something about it, says "error_msg":"An unknown error occurred (1)". I'm going to need to sniff actual requests to find what i'm doing wrong, and my debugging tooling is in a different continent... Seems unlikely that I'll have time to rebuild that soon.

dequis commented 5 years ago

FWIW my dirty request signing script (python2)

import cgi
from urllib import urlencode
import hashlib

FB_API_KEY = '256002347743983'
FB_API_SECRET = '374e60f8b9bb6b8cbb30f78030438895'

def fb_sig(data):
    params = ''.join(['%s=%s' % x for x in sorted(data.items())])
    data['sig'] = hashlib.md5(params + FB_API_SECRET).hexdigest()
    return data

data = {}
data['api_key'] = FB_API_KEY
data['format'] = 'json'
data['method'] = 'auth.login'
data['email'] =... '...'
data['password'] = '...'

#data['credentials_type'] = 'two_factor'
#data['error_detail_type'] = 'button_with_disabled'
#data['first_factor'] = '...'
#data['twofactor_code'] = '...'
#data['password'] = data['twofactor_code']

print("curl 'https://b-api.facebook.com/method/auth.login' -v --data-binary '" + urlencode(fb_sig(data)) + "'")

Replace the ..., run, run its output, uncomment block of #data, fill their .... Not really adding many details here because I'm sure some part is wrong. If I leave out credentials_type it works, but that's just because my "server" still supports the old method of using password for twofactor_code, I bet.

If you somehow manage to get it working, set the hidden setting token to the value of access_token. In purple it's accounts.xml stuff I think.

jaymzh commented 5 years ago

OK, I'm trying to play with this, but what is data['first_factor'] supposed to be? I treid setting it to data['password'] but that still gives me An unknown error occurred.

dequis commented 5 years ago

The error message of the first login attempt has a login_first_factor string in it, I copied that. It could be wrong, though.

jaymzh commented 5 years ago

Ah I see now, I missed that. So I tried that, and I tried both overriding data['password'] as you did, but also leaving it with the password, and both ways I get:

{"error_code":1,"error_msg":"An unknown error occurred (1)","request_args":[{"key":"method","value":"auth.login"},{"key":"api_key","value":"256002347743983"},{"key":"format","value":"json"},{"key":"first_factor","value":"XXXXXXXXXXXXXXX"},{"key":"credentials_type","value":"two_factor"},{"key":"sig","value":"YYYYYYYYYYYYYy"},{"key":"twofactor_code","value":"AAAAAAAAA"},{"key":"password","value":"--sanitized--"},{"key":"error_detail_type","value":"button_with_disabled"},{"key":"email","value":"phil\u0040ipom.com"}]}
jaymzh commented 5 years ago

BTW, for anyone else playing along at home, I modified the script slightly to make it a bit easier to use:

#!/usr/bin/python

import sys
import cgi
from urllib import urlencode
import hashlib
import getpass

FB_API_KEY = '256002347743983'
FB_API_SECRET = '374e60f8b9bb6b8cbb30f78030438895'

def fb_sig(data):
    params = ''.join(['%s=%s' % x for x in sorted(data.items())])
    data['sig'] = hashlib.md5(params + FB_API_SECRET).hexdigest()
    return data

data = {}
data['api_key'] = FB_API_KEY
data['format'] = 'json'
data['method'] = 'auth.login'
data['email'] = 'YOUR_EMAIL_HERE'

if len(sys.argv) > 1:
    data['credentials_type'] = 'two_factor'
    data['error_detail_type'] = 'button_with_disabled'
    data['first_factor'] = sys.argv[1]
    data['twofactor_code'] = sys.argv[2]
    data['password'] = data['twofactor_code']
else:
    data['password'] = getpass.getpass()

print("curl 'https://b-api.facebook.com/method/auth.login' -v --data-binary '" + urlencode(fb_sig(data)) + "'")

You can run it once with no argument, and then the second time pass in the first_factor as arg1 and the SMS code as the second arg, like:

$ fb_test.py
Password: <enter your password here>
curl ....
$ fb_test.py XXXXXX 123456
curl ....
jaymzh commented 5 years ago

Continuing to mess with this I made the script just do the requests for you and prompt you for the bits it needs:

#!/usr/bin/python

import sys
import cgi
from urllib import urlencode
import hashlib
import getpass
import httplib
import urllib
import json
from optparse import OptionParser

DEBUG = False

FB_API_KEY = '256002347743983'
FB_API_SECRET = '374e60f8b9bb6b8cbb30f78030438895'

def fb_sig(data):
    newdata = data.copy()
    params = ''.join(['%s=%s' % x for x in sorted(data.items())])
    newdata['sig'] = hashlib.md5(params + FB_API_SECRET).hexdigest()
    return newdata

def debug(msg):
    global DEBUG
    if DEBUG:
        print "DEBUG: %s", msg

parser = OptionParser()
parser.add_option('-d', '--debug', action='store_true', dest='debug', default=False)
(options, args) = parser.parse_args()

if options.debug:
    DEBUG = True

data = {}
data['api_key'] = FB_API_KEY
data['format'] = 'json'
data['method'] = 'auth.login'
data['email'] = ''
if data['email'] == '':
    print "ERROR: set an email address, please"
    sys.exit()
data['password'] = getpass.getpass()

headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "*/*"}
conn = httplib.HTTPSConnection('b-api.facebook.com:443')
params = urllib.urlencode(fb_sig(data))
conn.request('POST', '/method/auth.login', params, headers)
response = conn.getresponse()
debug("status, reason: %s, %s" % (response.status, response.reason))
response_data = response.read()
debug("undecoded response: %s" % response_data)
response = json.loads(response_data)
debug(response)
first_fac = json.loads(response['error_data'])['login_first_factor']

data['credentials_type'] = 'two_factor'
data['error_detail_type'] = 'button_with_disabled'
data['first_factor'] = first_fac
data['twofactor_code'] = getpass.getpass('Code: ')
data['password'] = data['twofactor_code']

params = urllib.urlencode(fb_sig(data))
conn.request('POST', '/method/auth.login', params, headers)
response = conn.getresponse()
debug("status, reason: %s, %s" % (response.status, response.reason))
response_data = response.read()
debug("undecoded response: %s" % response_data)
response = json.loads(response_data)
print response
jaymzh commented 5 years ago

Hey @dequis what's the easiest way to see what the official apps do? I can try debugging, but since it's all SSL, I'm not sure the easiest way to see what's going on..

dequis commented 5 years ago

Yeah I just need to rebuild my MITM setup, see:

I'm going to need to sniff actual requests to find what i'm doing wrong, and my debugging tooling is in a different continent... Seems unlikely that I'll have time to rebuild that soon.

For values of "soon" of "one week" which is over now. I'll look into this and other things this weekend, because apparently someone broke other parts of fb, sync sequences are sometimes gone and receiving messages goes on a different queue. Also the TLS 1.3 thing because why not.

FWIW I documented the stuff I did with earlier versions at https://wiki.dequis.org/notes/facebook/ - but it's been long enough that I bet the cert pinning methods changed again.

jaymzh commented 5 years ago

OK cool, thanks. If I get time to set that stuff up, I'll poke at it, but I'm guessing you'll get to the bottom of this faster than I will.

jaymzh commented 5 years ago

I didn't have a big enough block of time this weekend to try to setup the whole MITM setup unfortunately. Did you get a chance to look?

dequis commented 5 years ago

Nope, I only had enough time to sort the other issues (and one of them was just because someone else came up with the fix which was just bumping a version in the user agent lol).

On the bright side I am no longer technically-homeless!

jaymzh commented 5 years ago

Having a place to live is definitely more important than fixing my bugs! I'm glad you have a place to live :)

jaymzh commented 5 years ago

Thought I'd follow up here and see if you had made any progress. As always, happy to donate to you (or your favorite charity) to help the cause.

dequis commented 5 years ago

Hi! Sorry, nothing. My next two weekends are already fully booked and evenings ceased to exist. Also thanks for the offer (i genuinely appreciate it) but it wouldn't really buy me more time.

jaymzh commented 5 years ago

I just tried again (in case they reverted whatever thing they were rolling out), and neither normal Facebook nor workplace work with 2fac, so I (and probably others) still have no ability to use purple-facebook at all.

rbshadow commented 5 years ago

@jaymzh @dequis Just active app password in FB. Settings > Security and Login > App Password > Create an app password. Then login with that password and your FB username.

It's working for me.

Thanks

jaymzh commented 5 years ago

This did not work for me when I filed the Issue, but it does work now! It even works on Workplace!

tofurky commented 5 years ago

nice. works for me now, too. previously app passwords did not work.

builuc1998 commented 4 years ago
{"error_code":1,"error_msg":"An unknown error occurred (1)","request_args":[{"key":"method","value":"auth.login"},{"key":"api_key","value":"256002347743983"},{"key":"format","value":"json"},{"key":"first_factor","value":"XXXXXXXXXXXXXXX"},{"key":"credentials_type","value":"two_factor"},{"key":"sig","value":"YYYYYYYYYYYYYy"},{"key":"twofactor_code","value":"AAAAAAAAA"},{"key":"password","value":"--sanitized--"},{"key":"error_detail_type","value":"button_with_disabled"},{"key":"email","value":"phil\u0040ipom.com"}]}

Hi. Have you solved this problem yet? please help me

jackblk commented 3 years ago

Very late to the party but if someone needs this, these parameters should work

        base_data = {
            "fb_api_req_friendly_name": "authenticate",
            "locale": "en",
            "email": self.email,
            "password": self.password,
            "format": "json",
            "api_key": FB_ANDROID_MESSENGER_API_KEY,
            "method": "auth.login",
            "generate_session_cookies": "1",
            "generate_machine_id": "1",
            "device_id": self.device_id,
        }

        data = base_data.copy()
        data["twofactor_code"] = input("2fa code here: ")

        data["credentials_type"] = "two_factor"
        data["error_detail_type"] = "button_with_disabled"
        data["first_factor"] = error_data["login_first_factor"]
        data["password"] = data["twofactor_code"]
        data["userid"] = error_data["uid"]
        data["machine_id"] = error_data["machine_id"]
        # data_dict["currently_logged_in_userid"] = data_dict["0"] # does not need i think
jaymzh commented 3 years ago

@jackblk given that FB just killed app passwords, this is very timely.

Where you able to use this to somehow get the pidgin plugin to work?

jaymzh commented 3 years ago

Also where are you getting self.device_id from, @jackblk ?

jaymzh commented 3 years ago

OK, just shoving in a UUID seems to work. Combining @jackblk 's stuff with my previous script, this seems to work. Jam your email and a random UUID at the top

#!/usr/bin/python2.7

import sys
import cgi
from urllib import urlencode
import hashlib
import getpass
import httplib
import urllib
import json
from optparse import OptionParser

DEBUG = False
# put a UUID in here
MACHINE_ID = ''
# put your email in here
EMAIL = ''
FB_API_KEY = '256002347743983'
FB_API_SECRET = '374e60f8b9bb6b8cbb30f78030438895'

def fb_sig(data):
    newdata = data.copy()
    params = ''.join(['%s=%s' % x for x in sorted(data.items())])
    newdata['sig'] = hashlib.md5(params + FB_API_SECRET).hexdigest()
    return newdata

def debug(msg):
    global DEBUG
    if DEBUG:
        print "DEBUG: %s", msg

if EMAIL == '':
    print "ERROR: set an email address, please"
    sys.exit()

if MACHINE_ID == '':
    print "ERROR: set a machine id (to any UUID), please"
    sys.exit()

parser = OptionParser()
parser.add_option('-d', '--debug', action='store_true', dest='debug', default=False)
(options, args) = parser.parse_args()

if options.debug:
    DEBUG = True

data = {
    "fb_api_req_friendly_name": "authenticate",
    "locale": "en",
    "format": "json",
    "api_key": FB_API_KEY,
    "method": "auth.login",
    "generate_session_cookies": "1",
    "generate_machine_id": "1",
    "email": EMAIL,
    "device_id": MACHINE_ID,
}
data['password'] = getpass.getpass()

headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "*/*"}
conn = httplib.HTTPSConnection('b-api.facebook.com:443')
params = urllib.urlencode(fb_sig(data))
conn.request('POST', '/method/auth.login', params, headers)
response = conn.getresponse()
debug("status, reason: %s, %s" % (response.status, response.reason))
response_data = response.read()
debug("undecoded response: %s" % response_data)
response = json.loads(response_data)
debug(response)
error_data = json.loads(response['error_data'])
first_fac = error_data['login_first_factor']

data['credentials_type'] = 'two_factor'
data['error_detail_type'] = 'button_with_disabled'
data['first_factor'] = first_fac
data['twofactor_code'] = getpass.getpass('Code: ')
data['password'] = data['twofactor_code']
data['userid'] = error_data['uid']
data['machine_id'] = error_data['machine_id']

params = urllib.urlencode(fb_sig(data))
conn.request('POST', '/method/auth.login', params, headers)
response = conn.getresponse()
debug("status, reason: %s, %s" % (response.status, response.reason))
response_data = response.read()
debug("undecoded response: %s" % response_data)
response = json.loads(response_data)
print response

But doing as @dequis recommended and putting the resulting access_token into token into accounts.xml does not work for me, I still get a "Login approvals are on..." error. Also 'stoken' keeps showing up. I put the token into both token and stoken, but I haven't made it work yet. Anyone else?

jackblk commented 3 years ago

@jackblk given that FB just killed app passwords, this is very timely.

Where you able to use this to somehow get the pidgin plugin to work?

Well app password is dead so my app is dead too, so I try to find a way for 2fa. I currently don't use pidgin anymore so I'm not sure 😢. But the token & cookies are usable for my app.

giabao06 commented 3 years ago

OK, just shoving in a UUID seems to work. Combining @jackblk 's stuff with my previous script, this seems to work. Jam your email and a random UUID at the top

#!/usr/bin/python2.7

import sys
import cgi
from urllib import urlencode
import hashlib
import getpass
import httplib
import urllib
import json
from optparse import OptionParser

DEBUG = False
# put a UUID in here
MACHINE_ID = ''
# put your email in here
EMAIL = ''
FB_API_KEY = '256002347743983'
FB_API_SECRET = '374e60f8b9bb6b8cbb30f78030438895'

def fb_sig(data):
    newdata = data.copy()
    params = ''.join(['%s=%s' % x for x in sorted(data.items())])
    newdata['sig'] = hashlib.md5(params + FB_API_SECRET).hexdigest()
    return newdata

def debug(msg):
    global DEBUG
    if DEBUG:
        print "DEBUG: %s", msg

if EMAIL == '':
    print "ERROR: set an email address, please"
    sys.exit()

if MACHINE_ID == '':
    print "ERROR: set a machine id (to any UUID), please"
    sys.exit()

parser = OptionParser()
parser.add_option('-d', '--debug', action='store_true', dest='debug', default=False)
(options, args) = parser.parse_args()

if options.debug:
    DEBUG = True

data = {
    "fb_api_req_friendly_name": "authenticate",
    "locale": "en",
    "format": "json",
    "api_key": FB_API_KEY,
    "method": "auth.login",
    "generate_session_cookies": "1",
    "generate_machine_id": "1",
    "email": EMAIL,
    "device_id": 'aba9641c-fed9-4af8-8d32-d12e0dafd506',
}
data['password'] = getpass.getpass()

headers = {"Content-type": "application/x-www-form-urlencoded", "Accept": "*/*"}
conn = httplib.HTTPSConnection('b-api.facebook.com:443')
params = urllib.urlencode(fb_sig(data))
conn.request('POST', '/method/auth.login', params, headers)
response = conn.getresponse()
debug("status, reason: %s, %s" % (response.status, response.reason))
response_data = response.read()
debug("undecoded response: %s" % response_data)
response = json.loads(response_data)
debug(response)
error_data = json.loads(response['error_data'])
first_fac = error_data['login_first_factor']

data['credentials_type'] = 'two_factor'
data['error_detail_type'] = 'button_with_disabled'
data['first_factor'] = first_fac
data['twofactor_code'] = getpass.getpass('Code: ')
data['password'] = data['twofactor_code']
data['userid'] = error_data['uid']
data['machine_id'] = error_data['machine_id']

params = urllib.urlencode(fb_sig(data))
conn.request('POST', '/method/auth.login', params, headers)
response = conn.getresponse()
debug("status, reason: %s, %s" % (response.status, response.reason))
response_data = response.read()
debug("undecoded response: %s" % response_data)
response = json.loads(response_data)
print response

But doing as @dequis recommended and putting the resulting access_token into token into accounts.xml does not work for me, I still get a "Login approvals are on..." error. Also 'stoken' keeps showing up. I put the token into both token and stoken, but I haven't made it work yet. Anyone else?

I was able to use this script and add the token and it worked. This is what I added into accounts.xml in the settings section: <setting name='token' type='string'>(value of access_token)</setting>

jaymzh commented 3 years ago

I was able to use this script and add the token and it worked. This is what I added into accounts.xml in the settings section: <setting name='token' type='string'>(value of access_token)</setting>

Aha!! I was missing the type attribute. Thanks!! That works!

jaymzh commented 3 years ago

Eh, I spoke to soon. It worked briefly. Then my account got locked. I unlocked it and now that gives me invalid username or password

jaymzh commented 3 years ago

Eh, I spoke to soon. It worked briefly. Then my account got locked. I unlocked it and now that gives me invalid username or password

Oh scratch that. Had to update the password in pidgin (didn't realize it used that once it had a token).

giabao06 commented 3 years ago

Yeah me too. But I was able to solve it this way:

  1. Put the new password into pidgin
  2. Close pidgin, open accounts.xml
  3. Clear the stoken and token setting (as in, delete all those settings, not the value)
  4. Reauthenticate, get new token, put new token in accounts.xml again
liskin commented 3 years ago
"device_id": 'aba9641c-fed9-4af8-8d32-d12e0dafd506',

I had to replace this with MACHINE_ID and generate my own uuid into MACHINE_ID, but then it worked! Thanks a lot for the script.

jaymzh commented 3 years ago
"device_id": 'aba9641c-fed9-4af8-8d32-d12e0dafd506',

I had to replace this with MACHINE_ID and generate my own uuid into MACHINE_ID, but then it worked! Thanks a lot for the script.

Ooops, fixed. Thanks!

jaymzh commented 3 years ago

I put some work into the script to make it a bit easier for people not familiar with python or dicts or other stuff. It will spit out errors in some common cases instead of crashing. It's also now in py3. Here's a script, that when you run it, looks like this:

$ pidgin-fb-login-test.py
Access Token generator for Facebook 2factor login

This tool will perform 2-factor login to FB and then print out an
access token needed for the FB plugin for bitlbee and pidgin. Take
the resulting code and put it in the "token" tag in accounts.xml

Password: 
Code: 
Access token: <.....>

You need to edit the script to add your email and a UUID (which you can get by running uuidgen), but that's it. The script is here:

https://gist.github.com/jaymzh/3ed8817cf8c20222ca09ce33a544b695

akhepcat commented 3 years ago

Question about this process that I didn't see an obvious answer to:

if one does:

$ grep -A90 -i prpl-facebook accounts.xml | sed -n '/<\/account>/q;p' | grep setting | egrep 'id|token'

you can see that there already exists some data that looks like it's trying to use in the script:

                        <setting name='cid' type='string'>${CID-base64}</setting>
                        <setting name='uid' type='string'>${UID-base10}</setting>
                        <setting name='did' type='string'>${DID-uuid}</setting>
                        <setting name='mid' type='string'>${MID-base10}</setting>
                        <setting name='token' type='string'>${TOKEN-base64}</setting>

or at the very least, is returned by the python script above:

{u'machine_id': u'${MID-base64}', u'uid': ${UID-base10},u'access_token': u'${TOKEN-base64}'

(the only one not in the response is "cid")

Should we be making sure to update those lines from the response into accounts.xml as well, or just TOKEN?

Also, would it make sense, if it's available, to just use the 'did' from accounts.xml in the python script?

just thinking out loud here...

jaymzh commented 3 years ago

So, the short answer is: as long as the token is set, it doesn't seem to matter much. And to be clear, this script is just a short-term stop gap until @grimmy get is PR up that implements this natively, otherwise I'd be trying to make it parse-and-edit the accounts.xml, but I didn't care that much for something that I hope dies in a week or two.

All that said, those are all good questions. I actually used mid as my device_id, but I'm not sure. I imagine, looking at the flow you're supposed to pass in a device_id, and then use the machine_id you get back when you auth, but I don't actually know

grimmy commented 3 years ago

Yeah, sorry I'm super busy the next few days and not sure when I'll be able to finish this, but I'm hoping I'll have it done next week.

Azizb750 commented 3 years ago

I put some work into the script to make it a bit easier for people not familiar with python or dicts or other stuff. It will spit out errors in some common cases instead of crashing. It's also now in py3. Here's a script, that when you run it, looks like this:

$ pidgin-fb-login-test.py
Access Token generator for Facebook 2factor login

This tool will perform 2-factor login to FB and then print out an
access token needed for the FB plugin for bitlbee and pidgin. Take
the resulting code and put it in the "token" tag in accounts.xml

Password: 
Code: 
Access token: <.....>

You need to edit the script to add your email and a UUID (which you can get by running uuidgen), but that's it. The script is here:

https://gist.github.com/jaymzh/3ed8817cf8c20222ca09ce33a544b695

actually you must use 'did' (device_id) mentioned in the accounts.xml instead of an random uuid, this is how worked on me

giabao06 commented 2 years ago

Tip: the stoken setting is actually the OAuth2 secret. Entering that in solved the problem of facebook straight up locking my account after using Pidgin

Azizb750 commented 2 years ago

This is how I logged in successfully (a more detailed version for those who are begginers with pidgin):

  1. Setup the fb account from pidgin and add the account.
  2. Open the accounts.xml and check for 'did''s value and copy it
  3. Setup the python file, put your accounts.xml's 'did'(which indeed is an UUID) to the MACHINE_ID, write your email and save it
  4. Open the terminal and execute the python file
  5. Write down your password and the code you got from the SMS
  6. Copy the token, go to the value <setting name='token' /> and modify it so it must look something like this <settings name='token' type='string'>(the token you got)</setting>
  7. Save the accounts.xml file, then go to the pidgin>buddies>quit
  8. Open the pidgin again, so the program will login using the token instead of resending login request and deleting it.
  9. Now you have logged in successfully.

Yeah me too. But I was able to solve it this way:

1. Put the new password into pidgin

2. Close pidgin, open accounts.xml

3. Clear the stoken and token setting (as in, delete all those settings, not the value)

4. Reauthenticate, get new token, put new token in accounts.xml again
akhepcat commented 2 years ago

Suddenly unable to use 2fa again, using the script above.
(or using my merged script that parses accounts.xml, grabs the correct data, and call the fb login page: https://raw.githubusercontent.com/akhepcat/Miscellaneous/master/pidgin-fb-login-2fa.py )

Don't have enough skills to burp this and figure out what's changed, only that it's not working anymore for me.

blacklight commented 2 years ago

@akhepcat it broke for me as well in the past 24h, but I have managed to get my bitlbee-facebook account back online by simply generating another token.

tonitch commented 2 years ago

On my side, I keep getting 401 invalid username or password even tho I'm pretty sure I did everything right !

Metalhead33 commented 2 years ago

@Azizb750 's instructions with the script worked perfectly for me.