Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

login is broken #530

Open
noahfields opened this issue Jan 1, 2025 · 7 comments
Open

login is broken #530

noahfields opened this issue Jan 1, 2025 · 7 comments

Comments

@noahfields
Copy link

noahfields commented Jan 1, 2025

I've tried direct download and pip installation. Always this:

import robin_stocks.robinhood as r
r.login()
Robinhood username: ***********
Robinhood password: ************
Traceback (most recent call last):
File "", line 1, in
r.login()
~~~~~~~^^
File "/home//development/robin_stocks/robin_stocks/robinhood/authentication.py", line 190, in login
_validate_sherrif_id(device_token=device_token, workflow_id=workflow_id, mfa_code=mfa_code)
~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/
/development/robin_stocks/robin_stocks/robinhood/authentication.py", line 230, in _validate_sherrif_id
if challenge_response["status"] == "validated":
KeyError: 'status'

@mitch-zink
Copy link

Hi there, @noahfields

We use GitHub issues as a place to track bugs and other development-related issues.

Please see the link below to our dedicated support line:

Help Center : Click Here

Ticket ID: WB240

Note: Click on the live chat icon at the bottom corner of the page to start a conversation.

@noahfields don’t click the link, he’s not affiliated with robin_stocks

@noahfields
Copy link
Author

noahfields commented Jan 2, 2025

Solution: The login method in robinhood/authentication.py needs the mfa_code argument supplied the first time the function is called (when no valid pickle session is available). This was previously not the case: the method would prompt the user for a console mfa code if required.

I'll try to take a look at some other time to see if I can supply a fix, but for now, add login(mfa_code=****) to your login() calls.

If you have a valid pickle session file available, the mfa_code does not need to be provided to the robin_stocks.robinhood.login method.

@noahfields
Copy link
Author

As mentioned by @mitch-zink please avoid @Brett090. He is probably fishing for login credentials or something.

@dnevinrichards01
Copy link

dnevinrichards01 commented Jan 5, 2025

Solved

I am actually still getting this error despite using the mfa_code. I did some debugging and found out that robinhood is making me do the verification_workflow, which takes me to _validate_sheriff_id where request_post returns "challenge_response: {'detail': 'Challenge has expired.'}".

The only thing I can think of is that maybe the response from the second request_post in login, is giving the incorrect id " data['verification_workflow']['id']"?

I deleted the pickle in ~/.tokens/ and it worked!

@noahfields
Copy link
Author

I submitted a pull request with a fix. This is my first pull request, and I probably messed it up in a thousand ways, but at least it might get the ball rolling.

@AusHar
Copy link

AusHar commented Jan 7, 2025

Hey all! Thanks so much for looking into this and working on a fix. I'm a complete programming noob here, but I tried following the directions in both this thread and #510 and I'm still coming up empty with a "Login failed: 'status'" error.

Here's the code I've got (with a shit ton of help from ChatGPT). What might I be missing/doing wrong yet? I thought I'd implemented the suggested fixes but apparently not...

from flask import Flask, jsonify
import os
import pandas as pd
import vectorbt as vbt
import requests
import pyotp
from dotenv import load_dotenv
import robin_stocks.robinhood as rs

# Load environment variables
load_dotenv(dotenv_path="/Users/aharlan/Documents/Code/austinharlan-web/python/rhacc.env")

# Generate TOTP code dynamically
totp_secret = os.getenv('ROBINHOOD_MFA')  # Ensure this is your TOTP secret from the 3rd party app setup
if not totp_secret:
    raise ValueError("ROBINHOOD_MFA is not set in your environment variables")

totp = pyotp.TOTP(totp_secret).now()

# Retrieve username and password from environment variables
username = os.getenv("ROBINHOOD_USERNAME")
password = os.getenv("ROBINHOOD_PASSWORD")

if not username or not password:
    raise ValueError("ROBINHOOD_USERNAME and ROBINHOOD_PASSWORD must be set in your environment variables")

# Step 1: Perform Login
try:
    print("Logging in to Robinhood...")
    login_data = rs.login(
        username,
        password,
        expiresIn=86400,
        scope="internal",
        store_session=True,
        mfa_code=totp,
        pickle_name="robinhood_session.pkl"
    )
    print("Login Data:", login_data)  # Debugging the response

    # Extract tokens
    access_token = login_data.get("access_token")
    refresh_token = login_data.get("refresh_token")

    if not access_token:
        raise ValueError(f"Login failed: {login_data.get('error', 'Unknown error')}")

    # Update session manually
    rs.update_session("access_token", access_token)
    rs.update_session("refresh_token", refresh_token)

    print("Login successful! Session updated.")

except Exception as e:
    print(f"Login failed: {e}")
    exit(1)

# Step 2: Flask App for Portfolio Data
app = Flask(__name__)

@app.route('/api/portfolio', methods=['GET'])
def get_portfolio():
    try:
        # Fetch current holdings
        holdings = rs.build_holdings()
        symbols = list(holdings.keys())

        # Fetch historical price data for each symbol
        prices = pd.DataFrame()
        for symbol in symbols:
            historical_data = rs.stocks.get_stock_historicals(
                symbol, interval='day', span='week'
            )
            if not historical_data:
                print(f"No historical data for {symbol}")
                continue
            prices[symbol] = [float(day['close_price']) for day in historical_data]

        # Analyze portfolio with vectorbt
        portfolio = vbt.Portfolio.from_prices(prices)

        # Extract portfolio stats
        stats = portfolio.stats().to_dict()
        total_return = portfolio.total_return().to_dict()

        # Return data as JSON
        return jsonify({
            "stats": stats,
            "total_return": total_return
        })
    except Exception as e:
        return jsonify({"error": str(e)}), 500

if __name__ == '__main__':
    app.run(debug=True)

@noahfields
Copy link
Author

@AusHar Check out @pulkitcollier's pull request linked here. This may fix your issue, although I don't have experience with totp mfa codes.
Fix: #526

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants
@noahfields @dnevinrichards01 @mitch-zink @AusHar and others