gmusicapi
gmusicapi copied to clipboard
Webclient requires additional steps to log in from new ip
The docs state "Users who don’t use two-factor auth will likely need to enable less secure login. If this is needed, a warning will be logged during login (which will print to stderr in the default logging configuration)."
However, I cannot get login to work. I've tried with 2-step & app-specific passwords, and I've tried without 2-step & less secure login enabled. Either way, when I login, it always returns false. When looking at the log file, I see the following entry: "gmusicapi.Webclient3 (webclient:61) [INFO]: failed to authenticate". Mobileclient and Musicmanager login just fine.
I know it's suggested to not use the Webclient, but as far as I can tell, it's the only way I can get my cover art uploaded correctly (Webclient.upload_album_art). When uploading music via Musicmanager, my cover art is removed from the MP3.
Is Webclient login no longer working?
Got it! Started running session.py line-by-line over SSH, and found that after submitting the password, there was a third screen where it was asking me to do one of 4 things:
- Get a text message with a verification code at (•••) •••-••99
- Get a phone call with a verification code at (•••) •••-••99
- Confirm the recovery phone you added to this account
- Confirm the recovery email you added to this account
I simulated submitting one of these steps over SSH, and then Webclient.login worked perfectly.
form_candidates = response.soup.select("form")
form = form_candidates[3]
response = browser.submit(form, 'https://accounts.google.com/ServiceLoginAuth')
form_candidates = response.soup.select("form")
form = form_candidates[0]
form.select('[name=email]')[0]['value'] = '[email protected]'
response = browser.submit(form, 'https://accounts.google.com/ServiceLoginAuth')
I suspect I needed to do this step since I'm running gmusicapi off of a remote webserver, and therefore Google was trying to block the login since it didn't appear to be a known IP address. This is just a theory, but it makes sense.
Wonder if this flow could somehow be integrated into the Webclient login?
Ah. Yeah, we've had trouble with webclient auth on remote machines: I actually turned off webclient testing from travis because of it.
I don't think there's an easy solution. The webclient just wasn't built for programmatic auth.
It's all good. Now that I've successfully logged in with the work-around above, that IP address is now known to Google, and I am longer having login issues. Hopefully this thread helps someone else who is having the same issue. You should probably also look into putting a notice in the docs about remote connections not working. I could not find a single thread of information about this anywhere.
I had some problems with using a TFA account with WebClient - it won't accept an app-specific password, but it's not possible to use less-secure login with TFA. I added the following lines in session.py after submitting the password. I also had to change the login method in WebClient to accept kwargs so as to be able to pass the TFA token across; now I can log in using something like wc.login("email", "password", totp="TFATokenFromAuthenticator")
if 'totp' in kwargs: # Using 2FA
form_candidates = response.soup.select("form")
#commented out as there is another form to try a different option
# if len(form_candidates) > 1:
# log.error("Google login form dom has changed; there are %s candidate forms:\n%s",
# len(form_candidates), form_candidates)
# return False
form = form_candidates[0]
form.select("#totpPin")[0]['value'] = kwargs["totp"]
response = browser.submit(form, 'https://accounts.google.com/signin/challenge/totp/2')
try:
response.raise_for_status()
except requests.HTTPError:
log.exception("submitting OTP form failed")
return False
Had the same issue. Just False
login status, same messages in logs. Added application password in google and used it instead of mine. worked.