robinhood-unofficial / pyrh

Python Framework to make trades with the unofficial Robinhood API
https://pyrh.readthedocs.io/en/latest/
MIT License
1.78k stars 603 forks source link

Authentication with 2FA #221

Closed GarryKnimble closed 4 years ago

GarryKnimble commented 4 years ago

I was attempting to use the library, but because of 2FA it is not able to login to Robinhood. Is there a way to authenticate with 2FA enabled?

adithyabsk commented 4 years ago

@GarryKnimble you will have to install the project from source. That feature is currently only on the master branch.

GarryKnimble commented 4 years ago

This is probably a trivial question, but how does one install the library from the master branch?

adithyabsk commented 4 years ago

@GarryKnimble no worries, basically you can point pip to a git repo and ask it to download that specific repo like so:

$ pip install git+https://github.com/robinhood-unofficial/pyrh.git#egg=pyrh
GarryKnimble commented 4 years ago

Thank you, that worked.

GarryKnimble commented 4 years ago

How does this version deal with the 2FA? When I run it, it still gets the following:

No 2FA Given email code:

Do I need to have some way of getting inputs for it to receive the email code?

adithyabsk commented 4 years ago

@GarryKnimble you only need to type the email code once, and you can save the oauth token to disk as mentioned in the docs. Afterward the system will auto-refresh the token for you.

GarryKnimble commented 4 years ago

I attempted to enter the code, but then this error occurred

Traceback (most recent call last):
  File "<directory>/robinhood.py", line 215, in login
    res2.raise_for_status()
  File "<directory>/models.py", line 941, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 404 Client Error: Not Found for url: https://api.robinhood.com/challenge//respond/

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<pyshell#3>", line 1, in <module>
    rh.login(username="<email>", password="<password>")
  File "<directory>/robinhood.py", line 228, in login
    raise RH_exception.LoginFailed()
pyrh.exceptions.LoginFailed

Looking at the error, it seems self.challenge_id never gets assigned, or gets an empty string, resulting in the url that causes a 404 exception.


                res = self.session.post(endpoints.login(), data=payload, timeout=15)
                res_data = res.json()

                if (
                    "access_token" in res_data.keys()
                    and "refresh_token" in res_data.keys()
                ):
                    self.auth_token = res_data["access_token"]
                    self.refresh_token = res_data["refresh_token"]
                    self.headers["Authorization"] = "Bearer " + self.auth_token
                    return True

                if self.challenge_id == "" and "challenge" in res_data.keys():
                    self.challenge_id = res_data["challenge"]["id"]
                self.headers[
                    "X-ROBINHOOD-CHALLENGE-RESPONSE-ID"
                ] = self.challenge_id  # has to add this to stay logged in
                sms_challenge_endpoint = (
                    "https://api.robinhood.com/challenge/"
                    "{}/respond/".format(self.challenge_id)
                )

EDIT: I did some digging, and I noticed that res_data returns the following json

{'mfa_required': <content>, 'mfa_type': '<content>'}

Which makes sense why challenge_id is blank.

EDIT2: Turns out the issue was I needed to uninstall the library and then reinstall it. Everything works now.

adithyabsk commented 4 years ago

yep, that's right

jakesong1015 commented 4 years ago

i have the same result: No 2FA Given email code. "you only need to type the email code once, and you can save the oauth token to disk as mentioned in the docs." Can I get some help on how to enter the code? appreciate it

GarryKnimble commented 4 years ago

i have the same result: No 2FA Given email code. "you only need to type the email code once, and you can save the oauth token to disk as mentioned in the docs." Can I get some help on how to enter the code? appreciate it

If you are running the script in IDLE, you should be able to enter the code you were sent via SMS. You will probably have to click under the "No 2FA Given email code" text. Also, make sure you are pulling from the master branch and installing that module.

trentwiles commented 1 year ago

oauth

Can you show me where this is in the docs? I cant find anywhere in the docs that mentions saving the token to the disk.

trentwiles commented 1 year ago

cc @adithyabsk

variousred commented 1 year ago

putting here because i believe it is related ... i'm getting a strange error logging in with

>>> rh = Robinhood(username="xxx", password="xxx", mfa="123456789012")
>>> rh.login

then


2023-05-30 06:44:43,759 - pyrh.models.sessionmanager - DEBUG - Logging in to Robinhood
2023-05-30 06:44:43,759 - pyrh.models.sessionmanager - DEBUG - POSTing to https://api.robinhood.com/oauth2/token
2023-05-30 06:44:43,760 - pyrh.models.sessionmanager - DEBUG - POSTing to https://api.robinhood.com/oauth2/token
2023-05-30 06:44:43,760 - pyrh.models.sessionmanager - DEBUG - POST data: {'password': 'xxx', 'username': 'xxx', 'grant_type': 'password', 'client_id': 'c82SH0WZOsabOXGP2sxqcj34FxkvfnWRZBKlBjFS', 'expires_in': 734000, 'scope': 'internal', 'device_token': 'xxx', 'challenge_type': 'sms'}
2023-05-30 06:44:44,076 - pyrh.models.sessionmanager - DEBUG - oauth: OAuth(detail='Method "GET" not allowed.')
2023-05-30 06:44:44,076 - pyrh.models.sessionmanager - DEBUG - oauth is not valid
variousred commented 1 year ago

ok if i change raise_errors to true in the

oauth = self.post(
            urls.OAUTH,
            data=oauth_payload,
            raise_errors=True,
            auto_login=False,
            schema=OAuthSchema(),
        )

I get a new error requests.exceptions.HTTPError: 405 Client Error: Method Not Allowed for url: https://api.robinhood.com/oauth2/token/

noxor0 commented 1 year ago

@variousred I'm getting the same error as well - with and without mfa enabled. Doesn't seem like the login POST request is going through