Fix the ever-changing device_token - #300
Conversation
While working on a small script for fetching my RH order history I noticed that I kept getting "ERROR: There was an issue with the pickle file..." and would have to do the MFA dance yet again. Eventually that annoyed me enough to look into the problem. At first I tried deleting the pickle file and starting over, but that didn't help. Then I tried looking at the list of authenticated devices in my RH account and noticed 41 new devices! That seemed strange, especially given (I assumed) that the pickle file was saving some sort of authentication token. But clearly RH thought I was using a new device every time. Very strange...
I added a bit of `print()` debugging and discovered that the `device_token` being sent to RH was different every time, and wasn't what was saved in the pickle file.
```
% ./fetch_robinhood.py
pickle_path='/Users/bfoz/.tokens/robinhood.pickle'
pickle_data={'token_type': 'Bearer', 'access_token': '', 'refresh_token': '', 'device_token': '427bac7c-a31f-bb0c-0d8b-48880a1b1065'}
payload['device_token']='427bac7c-a31f-bb0c-0d8b-48880a1b1065'
ERROR: There was an issue loading pickle file. Authentication may be expired - logging in normally.
Enter Robinhood code for validation:
Found Additional pages.
Loading page 2 ...
Loading page 3 ...
% ./fetch_robinhood.py
pickle_path='/Users/bfoz/.tokens/robinhood.pickle'
pickle_data={'token_type': 'Bearer', 'access_token': '', 'refresh_token': '', 'device_token': '796191eb-3d55-422a-f658-637960239022'}
payload['device_token']='796191eb-3d55-422a-f658-637960239022'
ERROR: There was an issue loading pickle file. Authentication may be expired - logging in normally.
Enter Robinhood code for validation:
Found Additional pages.
Loading page 2 ...
Loading page 3 ...
```
It turns out that if a login fails for any reason, and then succeeds after the user enters the SMS code, the device token that's stored in the pickle file is not the one that was sent to RH in the successful login payload (or the unsuccessful one, for that matter). This appears to be due to the call to `pickle.dump()` saving the `device_token` that was generated when `payload` was first initialized (line 94) rather than the one from the pickle file. Loading the pickle file overwrites the value in `payload` (which is what is sent to RH) but the call to `pickle.dump()` stores `device_token` rather than `payload['device_token']`, which ends up being the original device token, not the one loaded from the pickle file.
All subsequent API calls will fail because the "wrong" device token that was written to the pickle file is loaded and sent to RH, which rightly rejects the login attempt. The user then enters the code which causes login to succeed with the saved device token, but once again the "wrong" token is then written to the pickle file, which causes the next login attempt to also fail...and around we go.
The submitted patch may not be the most elegant way to solve this, but it is simple.
|
I tried installing this branch but I am still prompted for a MFA with every login attempt |
|
While it appears this fix prevents the repeated creation of devices on Robinhood, it seems the PR #313's approach I believe fixes both, though I would personally write lines 128-128 as: Given that PR #313's approach works, does that suggest something changed on Robinhood's API which enables it to detect your session without any |
|
I'm surprised to see this merge. It seems to me that reusing the As mentioned, it seems to me that the #313 approach fixes the systemic issue and is the approach I have been using with success for several months now. In several months of testing this approach seems to both:
|
While working on a small script for fetching my RH order history I noticed that I kept getting "ERROR: There was an issue with the pickle file..." and would have to do the MFA dance yet again. Eventually that annoyed me enough to look into the problem. At first I tried deleting the pickle file and starting over, but that didn't help. Then I tried looking at the list of authenticated devices in my RH account and noticed 41 new devices! That seemed strange, especially given (I assumed) that the pickle file was saving some sort of authentication token. But clearly RH thought I was using a new device every time. Very strange...
I added a bit of
print()debugging and discovered that thedevice_tokenbeing sent to RH was different every time, and wasn't what was saved in the pickle file.It turns out that if a login fails for any reason, and then succeeds after the user enters the SMS code, the device token that's stored in the pickle file is not the one that was sent to RH in the successful login payload (or the unsuccessful one, for that matter). This appears to be due to the call to
pickle.dump()saving thedevice_tokenthat was generated whenpayloadwas first initialized (line 94) rather than the one from the pickle file. Loading the pickle file overwrites the value inpayload(which is what is sent to RH) but the call topickle.dump()storesdevice_tokenrather thanpayload['device_token'], which ends up being the original device token, not the one loaded from the pickle file.All subsequent login attempts will fail because the "wrong" device token that was written to the pickle file will be loaded and sent to RH, which rightly rejects the login attempt. The user then enters the code which causes login to succeed with the saved device token, but once again the "wrong" token is then written to the pickle file, which causes the next login attempt to also fail...and around we go.
The submitted patch may not be the most elegant way to solve this, but it is simple.