jmfernandes / robin_stocks

This is a library to use with Robinhood Financial App. It currently supports trading crypto-currencies, options, and stocks. In addition, it can be used to get real time ticker information, assess the performance of your portfolio, and can also get tax documents, total dividends paid, and more. More info at
http://www.robin-stocks.com
MIT License
1.69k stars 457 forks source link

Suddenly MFA requests every time i call the API #296

Closed alenknight closed 3 years ago

alenknight commented 3 years ago

everything was working fine for a while... suddnly today... July 1, 2021 @ exactly 4pm PST (i run the script every 15 min via a batch)..... all my logins started throwing the "please enter MFA"

i know they time expire like after a week... so i reran... but it won't stop. can't log in anymore automatically.
Please type in the MFA code: <<<<< this keeps popping up... and after 5 attempts i get put on hold for 10 min.

i've tried disabling 2FA.... reenabling it... changing passwords. i will say it's doing a weird rotation

sometimes it complains pickle file expired soemtimes it just asks "robinhood code" sometimes it asks "MFA code"

i also tried these params ... no luck.

by_sms=False, store_session=False, expiresIn=86400
ssmanji89 commented 3 years ago

same - noticing weird charecters in the robinhood.pickle file; have been able to confirm its for sure cached creds (immediate api calls after auth work as expected)

want to say i started seeing this around the same time as you

ssmanji89 commented 3 years ago

same - noticing weird charecters in the robinhood.pickle file; have been able to confirm its for sure cached creds (immediate api calls after auth work as expected)

want to say i started seeing this around the same time as you

testing with a brand new installation and WAN IP, still no resolution. issue to be with the way robinhood.pickle is being formatted (i don't know how pickle works well enough to know otherwise)

alenknight commented 3 years ago

interesting.... so it's not just me. could be something Robinhood doing? thursdays.... at around this time... for most financial institutions is "outside chief operating window"... which is when they update code and changes.... could be their system is doing it.... i'm hoping maybe it's temporary though? (for a few days i can just run manually... but long term... ooooof)

as to your pickle formatting ... i mean could be... but i'm not familiar how pickle's getting formatted. though if i use the "store_session=false" param... pickle should never be called.

ssmanji89 commented 3 years ago

so i just tried to re-enable MFA and can't get a code to validate. yeah, i wonder if its something internal to RH?

definitely fingers-crossed it's temporary

ssmanji89 commented 3 years ago

so i just tried to re-enable MFA and can't get a code to validate. yeah, i wonder if its something internal to RH?

definitely fingers-crossed it's temporary

confirmed also that store_session=false does allow functionality 😢

alenknight commented 3 years ago

so i just tried to re-enable MFA and can't get a code to validate. yeah, i wonder if its something internal to RH? definitely fingers-crossed it's temporary

confirmed also that store_session=false does allow functionality 😢

so sorry.... can you explain this part? so when you use "store_session=false".... allows functionality of.... pickle being ignored, right? (or did you mean something else?)

ssmanji89 commented 3 years ago

so i just tried to re-enable MFA and can't get a code to validate. yeah, i wonder if its something internal to RH? definitely fingers-crossed it's temporary

confirmed also that store_session=false does allow functionality 😢

so sorry.... can you explain this part? so when you use "store_session=false".... allows functionality of.... pickle being ignored, right? (or did you mean something else?)

right; apologies. with store_session=false i am able to log in and interact with the API.

alenknight commented 3 years ago

oh... it skips the MFA ? you don't need to put a code in to authenticate ?

ssmanji89 commented 3 years ago

no, you provide your SMS/MFA code and it's valid for that one session

alenknight commented 3 years ago

ahhhhh yeah so you still have to provide the code... yeah that still won't work as i have this running every 15 min on a batch .... really REALLY hope they bring this back to how it was... prior to just a few hours ago lol

btw... how'd you find where the pickle file is?

ssmanji89 commented 3 years ago

ahhhhh yeah so you still have to provide the code... yeah that still won't work as i have this running every 15 min on a batch .... really REALLY hope they bring this back to how it was... prior to just a few hours ago lol

btw... how'd you find where the pickle file is?

just backtracked the source

https://robin-stocks.readthedocs.io/en/stable/_modules/robin_stocks/authentication.html

image


ssmanji89 commented 3 years ago

wow, so it seems like auth expires within seconds (one of my functions cannot poll historical data even after a one-time authentication

alenknight commented 3 years ago

yikes... yeah so they doing something.... i bet they will resume prior state soon... cause i imagine a lot of people will start complaining in the next few days if it stays like this

thanks for the tip on the pickle

alenknight commented 3 years ago

actually... now that i think about it.... it's a good thing it times out so quick. (i know it sucks) but.... this means someone at RH will likely look at it and they will address. if it was JUST the MFA requirement - then it might be some regulation/compliance mandate they following... but if it times out that quick... it's likely an oopsie they will start to hear a LOT of people complaining about.

julianwagle commented 3 years ago

this thread scared the hell out of me! all my tests and scripts seem to be authenticating (and staying authd) just fine still .. maybe a version issue? I saw there were recently some MFA related updates about 10 days ago? if you're sifting through the pickle file i'm guessing you downloaded the raw code to your project, have you played around with the login function at all aside from setting store session to false? any conflicting global values? How is authenticating directly into the app (manually) going? any account issues?

alenknight commented 3 years ago

this thread scared the hell out of me! all my tests and scripts seem to be authenticating (and staying authd) just fine still .. maybe a version issue? I saw there were recently some MFA related updates about 10 days ago? if you're sifting through the pickle file i'm guessing you downloaded the raw code to your project, have you played around with the login function at all aside from setting store session to false? any conflicting global values? How is authenticating directly into the app (manually) going? any account issues?

i updated my robin_stocks version now just to be sure (2.0.4)... still same..... (i'm using PyCharm and got the modules through "settings >> pythond interpreters" install (been working fine for almost a year now)

where did you see there were MFA updates? (like on robinhood site or patch notes somewhere?) asking as i'd like to read about it and maybe in future i'll try to keep up to date with it....

as for trying various functions... yep. even just a straight up login doesn't work....


import robin_stocks.robinhood as r

login = r.login("username@email.com","password",by_sms=False, store_session=False, expiresIn=86400)


this fails and asks for MFA constantly. tried on 2 machines as well.

ssmanji89 commented 3 years ago

this thread scared the hell out of me! all my tests and scripts seem to be authenticating (and staying authd) just fine still .. maybe a version issue? I saw there were recently some MFA related updates about 10 days ago? if you're sifting through the pickle file i'm guessing you downloaded the raw code to your project, have you played around with the login function at all aside from setting store session to false? any conflicting global values? How is authenticating directly into the app (manually) going? any account issues?

just pulled from https://github.com/jmfernandes/robin_stocks.git with no differences

julianwagle commented 3 years ago

this thread scared the hell out of me! all my tests and scripts seem to be authenticating (and staying authd) just fine still .. maybe a version issue? I saw there were recently some MFA related updates about 10 days ago? if you're sifting through the pickle file i'm guessing you downloaded the raw code to your project, have you played around with the login function at all aside from setting store session to false? any conflicting global values? How is authenticating directly into the app (manually) going? any account issues?

i updated my robin_stocks version now just to be sure (2.0.4)... still same..... (i'm using PyCharm and got the modules through "settings >> pythond interpreters" install (been working fine for almost a year now)

where did you see there were MFA updates? (like on robinhood site or patch notes somewhere?) asking as i'd like to read about it and maybe in future i'll try to keep up to date with it....

as for trying various functions... yep. even just a straight up login doesn't work....

import robin_stocks.robinhood as r

login = r.login("username@email.com","password",by_sms=False, store_session=False, expiresIn=86400)

this fails and asks for MFA constantly. tried on 2 machines as well.

im not sure if you're really using that exact login function or if you just mistakenly typed it in like that for github but my understanding is that you should be one: calling rh.authentication.login (note that the login function is found within the authentication module) and two: including the MFA code with the auth call. For example:

import robin_stocks.robinhood as rh
from pyotp import TOTP as otp

def robinhood_login():
    totp = otp(env('RH_DEVICE_TOKEN')).now()
    rh.authentication.login(
        username=env('RH_USERNAME'),
        password=env('RH_PASSWORD'),
        mfa_code=totp
    )
    print('logged in to dahood.')
alenknight commented 3 years ago

the way i had it worked for the past year .... but i saw the format you using as well.. and i can try that. one question --- the mfa code.... i saw tutorials around this requiring me to use 2FA and the "other" option.... that's no longer available. sms or google authenticator are only options now on robinhood.... any info on how to address that?

julianwagle commented 3 years ago

yea thats tricky ... or atleast it may be in the future ... i remember having to use the robinhood website instead of the app and being worried after seeing it not available on the app but that was months ago and it may be gone from site as well now.

ssmanji89 commented 3 years ago

doesn't seem like using *.authentication.login() helps my particular scenario (wondering if we have different issues)

alenknight commented 3 years ago

oh i was doing through the app and i saw there's no more "other" option....

ssmanji89 commented 3 years ago

sadtimes (will probably delete this screenshot soon) image

alenknight commented 3 years ago

Yep. I keep getting the expired authentication thing too.

I’ll try the option written above …. But without the “other” and MFA token persisting … not sure how I’d get it to work

NicketUttarwar commented 3 years ago

I started getting the same error as everyone here - all my scripts were having trouble using the pickle file, and I needed to re-authenticate for every script...so I thought I'd try out the TOTP MFA suggestion here https://github.com/jmfernandes/robin_stocks/issues/296#issuecomment-872689629

That worked great! I setup 2FA, but instead of scanning it with using Google Authenticator(that btw is incredibly stateful and you can't clone codes out of your phone) I clicked the button on the bottom left ("didn't scan" or "need help" something along those lines) to get a 16 character alphanumeric key. That can be used instead of the scanner QR code to set the rotating OTP code. Then I used the same login code block from @julianwagle and passed in my 16 character alphanumeric key totp = otp(<my-16-character-alphanumeric-key>).now()

Success! And as a fringe benefit i don't need to use the finicky SMS 2FA code

alenknight commented 3 years ago

THAT WORKED!!! yay!
critical to note - you have to do this on your phone.... the option can't be seen on the web browser

mikelavrik commented 3 years ago

i was also using

import robin_stocks.robinhood as r from dotenv import load_dotenv login = r.login('username','password')

i have tried to switch it to the token example above but getting this error

NameError: name 'env' is not defined

any chance someone can paste a more detailed code example for the people that are not so familiar with python.

ssmanji89 commented 3 years ago

(1) make sure to update r.login() to r.authentication.login() (2) https://github.com/jmfernandes/robin_stocks/compare/v1.2.0...v1.3.0

image

ssmanji89 commented 3 years ago

(1) make sure to update r.login() to r.authentication.login() (2) v1.2.0...v1.3.0

image

this works but i don't think the underlying cached creds issue is resolved 😢

ssmanji89 commented 3 years ago

if anyone needs a version that uses stored variables

os.environ['totpCode'] = 'ERYTASFUGJ'
os.environ['rhusername'] = '@gmail.com'
os.environ['rhpassword'] = 'DAH00D'

# 7. Test authentication using below
curUser = os.environ.get('rhusername')
curPass = os.environ.get('rhpassword')
curTotp = os.environ.get('totpCode')

totp  = pyotp.TOTP(curTotp).now()
rs.authentication.login(curUser,curPass, mfa_code=totp)
ssmanji89 commented 3 years ago

if anyone needs a version that uses stored variables

os.environ['totpCode'] = 'ERYTASFUGJ'
os.environ['rhusername'] = '@gmail.com'
os.environ['rhpassword'] = 'DAH00D'

# 7. Test authentication using below
curUser = os.environ.get('rhusername')
curPass = os.environ.get('rhpassword')
curTotp = os.environ.get('totpCode')

totp  = pyotp.TOTP(curTotp).now()
rs.authentication.login(curUser,curPass, mfa_code=totp)

sort... of... like this way better?

mikelavrik commented 3 years ago

i switched to MFA but still have the same problem. asks for authentication every time.

phthon3 test.py quote BTC ERROR: There was an issue loading pickle file. Authentication may be expired - logging in normally. Please type in the MFA code: 694428 33447.055000

yidea commented 3 years ago

same here, every time it asked for a RB code, even w the store_session=True, seems RB did some update that we need to catchup w the change in the repo

ssmanji89 commented 3 years ago

figured out a scalable workaround using MPU and few pickle files (why? why not :smh) - see below; you will need to provide user/pass/totp code/key/whatever


# 6. Store appropriate values to custom pickle

python3.8
import mpu
your_data = {'hood_user': 'hood@email.com'}
mpu.io.write('/root/sully_rh_user.pickle', your_data)

your_data = {'hood_pass': 'hoodPassword'}
mpu.io.write('/root/sully_rh_pass.pickle', your_data)

your_data = {'hood_code': 'totpCode'}
mpu.io.write('/root/sully_rh_totpCode.pickle', your_data)

exit() 

#######
python3.8
import os 
import time
import robin_stocks.robinhood as rs
import math
import sys
import random
from datetime import date, datetime, timedelta
import pyotp
import robin_stocks as rs
import mpu 

# 7. Test authentication using below

curUser = mpu.io.read('/root/sully_rh_user.pickle')['hood_user']
curPass = mpu.io.read('/root/sully_rh_pass.pickle')['hood_pass']
curTotp = mpu.io.read('/root/sully_rh_totpCode.pickle')['hood_code']

totp  = pyotp.TOTP(curTotp).now()
rs.authentication.login(curUser,curPass, mfa_code=totp)

exit()
ssmanji89 commented 3 years ago

i switched to MFA but still have the same problem. asks for authentication every time.

phthon3 test.py quote BTC ERROR: There was an issue loading pickle file. Authentication may be expired - logging in normally. Please type in the MFA code: 694428 33447.055000

seems like a change in authentication for the better... annoying but better

real-time opposed to cached creds (this understanding led me to accommodating the updated requirement)

smw5qz commented 3 years ago

SOLVED, this works for me.

In the authentication.py file in the robin_stocks package, typically found at:

/home/USERNAME/.local/lib/pythonX/site-packages/robin_stocks/robinhood

You can comment out this line: res.raise_for_status()

By doing so the script doesn't try to check if you're still logged into a session, because if it does it will get a 401 response and enter the except block with another MFA.

mikelavrik commented 3 years ago

yes, that fixed it for me.

jmfernandes commented 3 years ago

SOLVED, this works for me.

In the authentication.py file in the robin_stocks package, typically found at:

/home/USERNAME/.local/lib/pythonX/site-packages/robin_stocks/robinhood

You can comment out this line: res.raise_for_status()

By doing so the script doesn't try to check if you're still logged into a session, because if it does it will get a 401 response and enter the except block with another MFA.

@smw5qz what line number?

smw5qz commented 3 years ago

@jmfernandes 130

smw5qz commented 3 years ago

@jmfernandes It's just bypassing checking if the token is still valid. A temporary fix at least until the token validity check can successfully return a 200 code.

ssmanji89 commented 3 years ago

yeh my thing may as well be a feature lol (builds on 1.3.x)

alenknight commented 3 years ago

ya'll are awesome! even though mine was resolved last night... there's SO much good stuff here you all put that i'm bookmarking it to leverage later... this will help me understand bettter about the otp ... as it's likely gonna be common in many projects i'm building...

kimardenmiller commented 3 years ago

Started noticing the ERROR: There was an issue loading pickle file. a few days back as well. Then RH asked me to change my password. Looking at my RH account I noticed my RH device list was adding a device each time I executed robin_stocks.robinhood.login, my MFA setting had been turned off, and I started getting codes by text and being asked for them.

Reading this thread I located and commented out /robin_stocks/robinhood/authentication.py:130, which not only stopped the error, but stopped adding a new device to my RH account on each execution of robin_stocks.robinhood.login. Without stopping the infinite adding of devices, my sense is that my password will get reset again at some point.

image

@jmfernandes thank you in advance for having a look. image

alenknight commented 3 years ago

oh man i just saw this now.... yeah it's happening to me too. as i'm running a batch every 15 min... yeah... HUNDREDS of devices haha i'll try your fix.... man this was a lifesaver

alenknight commented 3 years ago

Just this part of the code in authentication.py? I tried this, but it's still creating new devices every time my login runs....

                # res.raise_for_status()  <<<<<<<<<<<<<<<<<<<<<<<<<just this comment out>
                return({'access_token': access_token, 'token_type': token_type,
                        'expires_in': expiresIn, 'scope': scope, 'detail': 'logged in using authentication in {0}'.format(creds_file),
                        'backup_code': None, 'refresh_token': refresh_token})
        except:

image

kimardenmiller commented 3 years ago

Make sure you found the right file, at THIS path /robin_stocks/robinhood/authentication.py:130

alenknight commented 3 years ago

Make sure you found the right file, at THIS path /robin_stocks/robinhood/authentication.py:130

yep.... that's where i found it. i'll close this ticket as the issue itself is resolved... i'll likely have to open a new one to see why it's not working...