RobinHood icon indicating copy to clipboard operation
RobinHood copied to clipboard

MFA Requirement

Open kmohammadi6 opened this issue 2 years ago • 30 comments

Hello, I just wanted to begin by saying thank you for all the speedy work to get the package up to date with the new API, I really appreciate it!

Looking at the GitHub version of the package, it seems that MFA is now required in order to use the package. Like many others, I have a script that I run automatically for order placement, as such having to use MFA each time would be impractical. Given the API change, is MFA enrollment going to be a prerequisite going forward?

If it is required, would saving the RH object as an rds and loading the rds file each time work indefinitely as a work around?

For example, RH <- RobinHood(username = "my_username", password = "my_password, mfa_code = "my_mfa_code") save(RH, file = "RH_account.Rdata")

In other words, do you know if the MFA code needs to be the live MFA code from the authenticator app?

kmohammadi6 avatar May 16 '22 19:05 kmohammadi6

Hi, thanks im glad you enjoy the package. I will work on reenabling the non MFA login. I wanted to get something working quickly and make sure there were no other breaks. I have addressed all of the known api issues so ill turn my attention to this one.

JestonBlu avatar May 16 '22 20:05 JestonBlu

After looking at my account settings, i dont see an option to disable MFA, only edit my existing MFA. Unless I am missing something obvious. Can you point me to it?

JestonBlu avatar May 16 '22 20:05 JestonBlu

Looking at it I don't think you can. I have access to two accounts, one with MFA one without. In the MFA enabled one I don't see a way to turn it off...

I was able to test the solution I had above, saving the RH object after using the MFA Code once seems to work. But I'm not sure if that's a reliable solution going forward.

RH <- RobinHood(username = "my_username", password = "my_password, mfa_code = "my_mfa_code") save(RH, file = "RH_account.Rdata") rm("RH") load("RH.Rdata")

kmohammadi6 avatar May 16 '22 21:05 kmohammadi6

okay, they must be pushing that... so something that people might not know is that the access token you get lasts for quite a while. Ive added the expiration (which i think is in seconds) to the RH object. Ive used one token for multiple days so its not like you have to login every time you do an action.

Looking at the api im wondering if the command would basically be the same. Ill change the function to not fail if you dont supply a mfa token. Then maybe you can test it and see if that works?

JestonBlu avatar May 17 '22 03:05 JestonBlu

That sounds good, so you're saying that the mfa_code argument would be NULL by default, which is how it was previously right? Let me know when I should give it a try!

kmohammadi6 avatar May 17 '22 03:05 kmohammadi6

I have not signed up for MFA but I was using an older version of the package and it suddenly stopped working two weeks ago. I am happy to test as well, but something tells me that MFA might be required. I played with some of the source code and it was giving me 404 anytime I didn’t provide mfa

exploringfinance avatar May 18 '22 17:05 exploringfinance

im planning to push a new branch tonight attached to this issue that will prevent the function from failing if you dont provide an mfa code. Im not going to change any of the other structure yet so the API call will still try to push an MFA, it will just be null (or i can hardcode an arbitrary value). If someone can install the separate branch version and give me some feedback that would be appreciated.

I sent an email to RH customer service on downgrading from MFA, but i have not received a response. Im guessing they are really pushing towards this and are planning on making it mandatory at some point.

JestonBlu avatar May 18 '22 18:05 JestonBlu

Sounds good! Using the current git version (1.6.8), I tried supplying a random number (as a character) for the MFA code on a non-MFA enabled account and I get a Bad Request error. Supplying NULL results in an error from the api_login function. The body dataframe cannot be built in the api_login function.

This is what I tried on the non-MFA enabled account: mfa_token <- paste0(sample(0:9, size = 6, replace = T), collapse = "") RH <- RobinHood(username = "my_user_name", password = "my_password", mfa_code = mfa_token) And it resulted in the HTTP 400 Error

kmohammadi6 avatar May 18 '22 18:05 kmohammadi6

I am happy to try it but not sure it will work. I passed ‘’ and random strings. 404 error for all of them. It wouldn’t let me pass a NULL value. If they require mfa there won’t be a way to fully automate. I wrote packages for etrade and TD. They both allow for refreshing tokens allowing you to go indefinitely. TD uses oauth 2. Maybe Robinhood can allow something similar?

exploringfinance avatar May 18 '22 19:05 exploringfinance

If someone could try this out I would appreciate it.

JestonBlu avatar May 19 '22 12:05 JestonBlu

400 Bad request

I used this code:

RobinHood <- function(username, password, mfa_code = NULL) {
    
    # If MFA is null, set to 0 and remove later
    if (is.null(mfa_code) == TRUE) mfa_code <- "000000"
  RH <- RobinHood::api_login(username, password, mfa_code)
  accounts <- RobinHood::api_accounts(RH)
  url_account_id <- accounts$url
  RH <- c(RH, url = list(account_id = url_account_id))
  if (is.null(RH$api_response.access_token)) {
    cat("Login not successful, check username and password.")
  }
  class(RH) <- "RobinHood"
  return(RH)
}

And the response was this:

Error in RobinHood::api_login(username, password, mfa_code) : 
 Bad Request (HTTP 400). 

exploringfinance avatar May 19 '22 13:05 exploringfinance

I got the same thing, pulled down the latest commit of the pkg using: devtools::install_github("jestonblu/RobinHood@062641f36a779b40cea884c49fd8857613fe9811") When I tried to run it on my non-MFA account I get a the same Bad Request HTTP 400 error.

Not sure how helpful this is, but I took a closer look inside the api_login function and noticed when you run this line: dta <- dta %>% content(type = "json") %>% rawToChar() %>% jsonlite::fromJSON() %>% as.list()

The dta list has an element named "detail" which returns: "Request blocked, challenge type required."

I am able to run the api_login function from the inside and it returns a list, but when I try to run: accounts <- RobinHood::api_accounts(RH) I get an Unauthorized (HTTP 401) error

Given that you're trying to pass an MFA code to an account that doesn't have MFA enabled the error makes sense, but at the same time it seems that Robinhood is making it impossible to use the API without a MFA enrollment. Did you ever hear back from RH support?

kmohammadi6 avatar May 19 '22 15:05 kmohammadi6

@kmohammadi6 could you clarify how you are obtaining the mfa_code for the MFA-enabled and non-enabled accounts? We have two Robinhood accounts - one which we've turned on standard SMS MFA (and now can't see any way to disable it), one which we have MFA disabled.

Here are the $detail text from the HTTP 400 error:

For the account with no MFA (and we enter a empty string in mfa_code): $detail [1] "Request blocked, challenge type required."

For the account with SMS MFA, and we enter the 6-digit SMS code as a string: $detail [1] "Unable to log in with provided credentials."

For the mfa-enabled account, do you log in on your Robinhood phone app first to get the SMS code? then plug that code into R's api_login before you complete the log in on your phone?

sneijder12 avatar May 19 '22 19:05 sneijder12

For the MFA enabled account I get the code from the Duo mobile app and pass it as a character to the Robinhood function. This has worked for me on the MFA enabled account. As JestonBlu mentioned, the token seems to be good for a number of days so I saved the RH object as an RDS and can reuse it. RH <- RobinHood(username = "my_username", password = "my_password, mfa_code = "my_mfa_code")

For the MFA disabled there is obviously no MFA code to pass, I've tried passing: NULL, "000000", or another random 6 digit number string: mfa_token <- paste0(sample(0:9, size = 6, replace = T), collapse = "") None of these approaches have worked, and I've hit the same issue you have.

kmohammadi6 avatar May 19 '22 19:05 kmohammadi6

For the MFA enabled account I get the code from the Duo mobile app and pass it as a character to the Robinhood function. This has worked for me on the MFA enabled account. As JestonBlu mentioned, the token seems to be good for a number of days so I saved the RH object as an RDS and can reuse it. RH <- RobinHood(username = "my_username", password = "my_password, mfa_code = "my_mfa_code")

For the MFA disabled there is obviously no MFA code to pass, I've tried passing: NULL, "000000", or another random 6 digit number string: mfa_token <- paste0(sample(0:9, size = 6, replace = T), collapse = "") None of these approaches have worked, and I've hit the same issue you have.

Thanks for the info. For some reason my mfa-enabled account still isn't working. Is it the 6-digit code from DUO (that expires every 30 secs) what you plug into argument mfa_code? Or is it a alphanumeric code?

sneijder12 avatar May 27 '22 18:05 sneijder12

I'm using the 6 digit code from the DUO App, passing it as a character

Not sure if this is the issue, but in the the app it might look like it's showing a space between the 3rd and 4th digit, but you just need to pass it as a 6 digit code with no space.

kmohammadi6 avatar May 27 '22 18:05 kmohammadi6

I'm using the 6 digit code from the DUO App, passing it as a character

Not sure if this is the issue, but in the the app it might look like it's showing a space between the 3rd and 4th digit, but you just need to pass it as a 6 digit code with no space.

Hmm interesting.. that is what I'm doing. Under the Two-Factor Authentication settings page - I have "Authenticator app" and "Backup code" under "Manage your Methods". Then I try to run the api_login/RobinHood functions during that 30 seconds when the Duo code is still live.

sneijder12 avatar May 27 '22 19:05 sneijder12

I'm doing a couple different things it sounds like. Firstly, I'm just using the top level Robinhood function but that shouldn't be an issue.

It sounds like you're going through the RH app to get the code? I'm just going to the duo mobile app directly, you can add accounts and store them in the DUO app. I never open up the RH app to get the code.

kmohammadi6 avatar May 27 '22 19:05 kmohammadi6

Iam still having this issue, any resolutions. Error in RobinHood::api_login(username, password, mfa_code) : Bad Request (HTTP 400).

samboy84 avatar Jul 30 '22 16:07 samboy84

Are you using the latest github version? I checked this morning and it worked fine for me. Its been a while since I have pushed to CRAN, i will try to prioritize and update soon.

On Sat, Jul 30, 2022 at 11:40 AM samboy84 @.***> wrote:

Iam still having this issue, any resolutions. Error in RobinHood::api_login(username, password, mfa_code) : Bad Request (HTTP 400).

— Reply to this email directly, view it on GitHub https://github.com/JestonBlu/RobinHood/issues/157#issuecomment-1200249252, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAZPNBPBTDJBFK662XT2D4DVWVLITANCNFSM5WCSN34Q . You are receiving this because you were assigned.Message ID: @.***>

JestonBlu avatar Jul 31 '22 16:07 JestonBlu

Can you please provide the syntax that was working.

samboy84 avatar Jul 31 '22 16:07 samboy84

Its the standard connection command. Are you sure you are using the github version? Should say 1.6.9

RH <- RobinHood(username, password, mfa_code = '123456')

JestonBlu avatar Aug 01 '22 23:08 JestonBlu

Thanks Jeston, Yes Iam using same command. Do I need to update github version in R-Studio. Iam using R-Studio.

On Monday, August 1, 2022, Jeston @.***> wrote:

Its the standard connection command. Are you sure you are using the github version? Should say 1.6.9

RH <- RobinHood(username, password, mfa_code = '123456')

— Reply to this email directly, view it on GitHub https://github.com/JestonBlu/RobinHood/issues/157#issuecomment-1201830098, or unsubscribe https://github.com/notifications/unsubscribe-auth/A2JPYZJVUCJYVG57OYUZ53DVXBLIJANCNFSM5WCSN34Q . You are receiving this because you commented.Message ID: @.***>

samboy84 avatar Aug 02 '22 03:08 samboy84

Yes, that is the easiest way. You will need the devtools package to install it from github.

install.packages("devtools")
devtools::install_github("jestonblu/RobinHood")

JestonBlu avatar Aug 03 '22 12:08 JestonBlu

Thanks Jeston, I installed devtools and install_github("jestonblu/RobinHood") but Still Iam getting below error.

RH <- RobinHood @.", "****", mfa_code = "812792") Error in RobinHood::api_login(username, password, mfa_code) : Bad Request (HTTP 400).

Error in get_quote(RH, symbol = SYMBOLS[i]) : object 'RH' not found

On Wed, Aug 3, 2022 at 7:47 AM Jeston @.***> wrote:

Yes, that is the easiest way. You will need the devtools package to install it from github.

install.packages("devtools")devtools::install_github("jestonblu/RobinHood")

— Reply to this email directly, view it on GitHub https://github.com/JestonBlu/RobinHood/issues/157#issuecomment-1203905019, or unsubscribe https://github.com/notifications/unsubscribe-auth/A2JPYZJJSITQ6BMNI5QLSZDVXJS57ANCNFSM5WCSN34Q . You are receiving this because you commented.Message ID: @.***>

samboy84 avatar Aug 03 '22 15:08 samboy84

Jeston,

Iam getting this error now.

Error in RobinHood::api_quote(RH, quote_url) : Not Found (HTTP 404)

On Wed, Aug 3, 2022 at 10:51 AM sam t @.***> wrote:

Thanks Jeston, I installed devtools and install_github("jest onblu/RobinHood") but Still Iam getting below error.

RH <- RobinHood @.", "****", mfa_code = "812792") Error in RobinHood::api_login(username, password, mfa_code) : Bad Request (HTTP 400).

Error in get_quote(RH, symbol = SYMBOLS[i]) : object 'RH' not found

On Wed, Aug 3, 2022 at 7:47 AM Jeston @.***> wrote:

Yes, that is the easiest way. You will need the devtools package to install it from github.

install.packages("devtools")devtools::install_github("jestonblu/RobinHood")

— Reply to this email directly, view it on GitHub https://github.com/JestonBlu/RobinHood/issues/157#issuecomment-1203905019, or unsubscribe https://github.com/notifications/unsubscribe-auth/A2JPYZJJSITQ6BMNI5QLSZDVXJS57ANCNFSM5WCSN34Q . You are receiving this because you commented.Message ID: @.***>

samboy84 avatar Aug 14 '22 15:08 samboy84

I'm getting the Bad Request (HTTP 404) error on the api_login as well.

I'm using the Google Authenticator app on my mobile phone for the MFA code. Is that the correct method to get the code?

IEORTools avatar Dec 02 '23 17:12 IEORTools

I forked the auth piece and you can see how I am doing it here: https://github.com/exploringfinance/RobinHood/blob/main/R/RobinHood.R

exploringfinance avatar Dec 02 '23 18:12 exploringfinance

I forked the auth piece and you can see how I am doing it here: https://github.com/exploringfinance/RobinHood/blob/main/R/RobinHood.R

does your fork require the otp package?

IEORTools avatar Dec 03 '23 14:12 IEORTools

Yes, but it should be in there if you take the dev tools GitHub install.

On Dec 3, 2023, at 09:03, Larry @.***> wrote:

I forked the auth piece and you can see how I am doing it here: https://github.com/exploringfinance/RobinHood/blob/main/R/RobinHood.R

does your fork require the otp package?

— Reply to this email directly, view it on GitHub https://github.com/JestonBlu/RobinHood/issues/157#issuecomment-1837490060, or unsubscribe https://github.com/notifications/unsubscribe-auth/AK24F7UV3PRKOWJCYVJLUGDYHSBEVAVCNFSM5WCSN342U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCOBTG42DSMBQGYYA. You are receiving this because you commented.

exploringfinance avatar Dec 03 '23 14:12 exploringfinance