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

Two-factor authentication (2FA) not implemented #102

Closed
Bart274 opened this issue Nov 6, 2016 · 60 comments
Closed

Two-factor authentication (2FA) not implemented #102

Bart274 opened this issue Nov 6, 2016 · 60 comments

Comments

@Bart274
Copy link
Contributor

Bart274 commented Nov 6, 2016

Hi,
I use pyicloud in the device_tracker entity in Home Assistant.
My users have noticed 2factor authentication isn't working, it works for 2steps authentication?

@Bart274
Copy link
Contributor Author

Bart274 commented Nov 7, 2016

Instead of basing ourselves by the hsaChallengeRequired key from the API data, can't we base ourselves at these keys: data.dsInfo.hsaEnabled and data.dsInfo.hsaVersion.
For 2 factor authentication, the key hsaEnabled is True and the key hsaVersion is 2. I suspect the hsaVersion is 1 for 2 step authentication.

@rameshT108
Copy link

rameshT108 commented Nov 18, 2016

@Bart274 did you find any solution to achieve 2FA?

@Bart274
Copy link
Contributor Author

Bart274 commented Nov 18, 2016 via email

@rameshT108
Copy link

we can't implement it? is there any way?

@MikeTheCanuck
Copy link

I have been able to get this code to work for my Apple ID (on which two-factor authentication has been enabled):
https://github.com/MikeTheCanuck/CloudContactUpdate/blob/master/Experiments%20in%20authenticating%20to%20iCloud%20using%20pyicloud.ipynb

What is the issue you're experiencing? Maybe I can help by reproducing in my code, or help isolate the difference you might have between your code and mine?

@rameshT108
Copy link

Hello Mike,

While implementing it. It returns unauthorized response

@MikeTheCanuck
Copy link

Thanks but I don't know how to reproduce the outcome either of you are experiencing without much greater detail (and it's likely that the project participants wouldn't be able to either).

To have a fair chance at reproducing your situations, I recommend you supply your issue report with the following:

  • A description of the specific outcome you are expecting to have
  • A description of the specific outcome you are actually experiencing
  • A step-by-step guide to the procedure you're following including at what point
  • A detailed description of your environment (operating system, version of Python being used, versions of libraries being used, version of PyiCloud being used, and any other components that you think might be relevant to reproducing your scenario)
  • If possible, the code/script that you're using that causes the failure

torarnv added a commit to torarnv/pyicloud that referenced this issue Jan 9, 2017
Two-step authentication is an older security method used for
accounts without an Apple device, or who are unable to upgrade
to iOS 9 or OS X El Capitan.

https://support.apple.com/en-us/HT204152

If the account has two-factor authentication enabled, we can still
fall back to the end-points for two-step authentication, as we do
not support 2FA yet.

Issue picklepete#102
@Fonta
Copy link

Fonta commented Jan 12, 2017

When will you support 2 factor authentication?
I would like to use iCloud for presence detection in home-assistant, but without support for 2FA, my iPhone keeps giving popups that someone used my credentials to login.
With that this plugin is unusable, because disabling 2FA on my account makes Homekit externally unavailable.

@torarnv
Copy link
Collaborator

torarnv commented Jan 12, 2017

With the current code, if 2FA is enabled, we will fall back to the 2SA code-path, requesting a validation code from a trusted device, e.g. via SMS, and once you are fully authorised the cookie will be saved for future authorisations, so you shouldn't see the popup every time.

@torarnv
Copy link
Collaborator

torarnv commented Jan 12, 2017

@f0nt4 also, please keep home-assistant issues to the relevant bug tracker. pyicloud is a library and as long as the library provides the primitives to give a authentication workflow that works with 2FA it is up to the home-assistant plugin to implement it.

@Bart274
Copy link
Contributor Author

Bart274 commented Jan 12, 2017 via email

@torarnv
Copy link
Collaborator

torarnv commented Jan 12, 2017

@Bart274: I switched my account over from 2SA to 2FA, and I have a single trusted device presented when going through the 2SA code path, which is the SMS option. Perhaps you don't have a mobile number associated with your account? With 2FA enabled I remember logging in to icloud.com and clicking "Did not get a verification code? ", and then choosing the SMS option, that might have added SMS as a trusted option? Can you try that?

@jldeen
Copy link

jldeen commented Jan 15, 2017

@Bart274 I'm using your icloud component in HA currently and have iCloud 2FA (NOT 2Step) working, but only for a few hours. If I take the code provided by the 2FA prompt from my MBP or iPhone, append it to the end of my iCloud password in the configuration.yaml file it will authenticate for the first time using the pyicloud library. The second time around when it goes to check for updated info for my Apple devices, it will say:

pyicloud.exceptions.PyiCloudFailedLoginException: ('Invalid email/password combination.', PyiCloudAPIResponseError('Misdirected Request',))

If I remove the 6 digit code I appended to the end of my password, and re-save the configuration.yaml file, the error will go away, authentication will complete successfully:

INFO:pyicloud.base:Authenticating as [email-redacted] INFO:pyicloud.base:Authentication completed successfully

and the credentials are stored for what seems to be 6 hours without any new codes being pushed to my devices. After about 6 hours, I have to go through the auth process described all over again. So, it appears 2FA is working with pyicloud, but it's not caching the authentication for the appropriate amount of time.

@bramkragten
Copy link

bramkragten commented Aug 8, 2017

Would using a app-specific password work? As I don't believe you can use 2FA with a non Apple product...

@torarnv
Copy link
Collaborator

torarnv commented Aug 8, 2017 via email

@WhyNotHugo
Copy link
Contributor

I'm having an issue where api.validate_verification_code always returns False even though the code is the one displayed on the iPhone.

I'm slightly unfamiliar with the difference between 2FA and 2SA. Is my scenario part of this issue, or is it some separate bug?

torarnv added a commit that referenced this issue Sep 24, 2017
Two-step authentication is an older security method used for
accounts without an Apple device, or who are unable to upgrade
to iOS 9 or OS X El Capitan.

https://support.apple.com/en-us/HT204152

If the account has two-factor authentication enabled, we can still
fall back to the end-points for two-step authentication, as we do
not support 2FA yet.

Issue #102
@torarnv torarnv changed the title 2factor authenication isn't working, it's two step authentication Two-factor authentication (2FA) not implemented Sep 24, 2017
@torarnv
Copy link
Collaborator

torarnv commented Sep 24, 2017

I've clarified the situation in 69af919

Patches to support 2FA welcome!

@ghost
Copy link

ghost commented Sep 25, 2017

@torarnv because this is acting as a custom web browser, can we just save the authentication cookies for 2fa? With any other browser when you log in you can check the box to save the browser and not require a code the next time. Can we do something similar?

@WhyNotHugo
Copy link
Contributor

Patches to support 2FA welcome!

In the meantime, is it possible to support 2SA on an iOS11 device? Apple docs seem to indicate that iOS9+ support 2FA only, so I guess I'd need a really old device to use this, right?

@WhyNotHugo
Copy link
Contributor

The documentation currently states:

This approach also works if the account is set up for two-factor authentication (2FA), but the authentication will time out after a few hours. Full support for two-factor authentication (2FA) is not implemented in PyiCloud yet. See issue #102.

But after multiple attempts, using the 2FA with that code example, it always returns Failed to verify verification code.

@mariusciziunas
Copy link

Could anyone help me? I cannot disable "Two-Factor Authentification" in my settings. Looks like if you changed it to 2FA once, there is no way back(If you know how to do it, please tell me). The two step thing worked for me just one time. The second time I try to rerun the code I get "pyicloud.exceptions.PyiCloudAPIResponseError: Missing X-APPLE-WEBAUTH-HSA-LOGIN cookie". Is this a known issue?

Thanks

@kylemcdonald
Copy link

Same here as @mariusciziunas I have 2FA and was able to log in the first time using this code:

from pyicloud import PyiCloudService
api = PyiCloudService(icloud_email, icloud_password)
devices = api.trusted_devices
for i, device in enumerate(devices):
    print('%s: %s' % (i, device.get('deviceName', "SMS to %s" % device.get('phoneNumber'))))
api.send_verification_code(devices[0])

Followed by: api.validate_verification_code(devices[0], verification_code)

But the second time I tried it, I got: PyiCloudAPIResponseError: Missing X-APPLE-WEBAUTH-HSA-LOGIN cookie

I tried uninstalling and reinstalling pyicloud, but that didn't help.

I also tried logging in via the browser from the same machine that I was running the code, in the case that the cookies were being shared with the browser somehow.

@patrickpissurno
Copy link

Any updates on this issue?

@cuppywuppy123
Copy link

Yes I have successfully done it.

from pyicloud import PyiCloudService api=PyiCloudService('*********@gmail.com','*****') if api.requires_2fa: devices = api.trusted_devices api.send_verification_code(devices[0]) code = input('Please enter validation code:') if not api.validate_verification_code(devices[0], code): print("Failed to verify verification code") exit(1) else: print("Logged In!!!") api.iphone.play_sound() x=input('exit?[y/n]:') if x=='y' : exit(0) else: api.iphone.play_sound()
If you run the code you're supposed to get 2 notifications on your iPhone, one as a popup and the second as an SMS.
Enter the code that comes with the SMS and the program will work.

@Suncatcher
Copy link

Suncatcher commented Mar 4, 2019

Since recently 2FA can no longer be disabled, so implementation is highly needed. Can we use https://github.com/ndbroadbent/icloud_photos_downloader implementation? It doesn't require extra coding except accepting auth request on Iphone.

@bickyb
Copy link

bickyb commented Jan 28, 2020

@kylemcdonald and @mariusciziunas were you able to solve your
pyicloud.exceptions.PyiCloudAPIResponseError: Missing X-APPLE-WEBAUTH-HSA-LOGIN cookie
issue?
I am running into the same problem. I can authenticate and do things once, but it seems some sort of cookie needs to be stored in order to login after the session times out.

@thevickypedia
Copy link

With apple currently disabling the option to turn off 2FA, is there a way to use this code without 2FA? I had a similar issue using robinhood's API but I was able to use the backup secret key to skip 2FA. Does apple have a similar option? (something like a secret key which can run without 2FA)

@Quentame
Copy link
Collaborator

With apple currently disabling the option to turn off 2FA, is there a way to use this code without 2FA? I had a similar issue using robinhood's API but I was able to use the backup secret key to skip 2FA. Does apple have a similar option? (something like a secret key which can run without 2FA)

2SA it's working for you ?
It's necesary to pass all steps of login before using the lib (or accept every time on the popup in your device).

Working on my side.

@leres
Copy link

leres commented May 26, 2020

I've been using 2FA with my script for a long time now. I lifted the logic from cmdline.py which checks api.requires_2sa and if necessary (and running interactively) does the verification dance.

In practice when run from cron this triggers about every two months. When that happens I run the script interactively and then it's good for another two months.

cmdline.py also has some nice code for storing the pw in a keyring.

@thevickypedia
Copy link

thevickypedia commented May 30, 2020

2SA it's working for you ?
It's necesary to pass all steps of login before using the lib (or accept every time on the popup in your device).

Working on my side.

It works only after entering the authentication code which apple sends to me. I'm curious about storing pw in a keyring. I will try the implementation steps in
https://github.com/ndbroadbent/icloud_photos_downloader

@leres
Copy link

leres commented May 31, 2020

The keyring code I referred to is in cmdline.py

@thevickypedia
Copy link

@leres I found it later that day, it seem to work. However I'm curious on how it stores the 2fa. Without cmdline.py the 2fa was asked every 24 hours.

@zhiqihuang
Copy link

You can login to icloud.com and get location of your devices without any prompt on your devices. So I think maybe at least find my iPhone service does not need 2FA?

@WhyNotHugo
Copy link
Contributor

FindMyIphone does not require 2FA for an obvious reason: you use it when you've lost your phone and don't have access to that second factor.

@zhiqihuang
Copy link

So can we get location without 2FA (2FA enabled) ?

@thevickypedia
Copy link

So can we get location without 2FA (2FA enabled) ?

@zeeqy I think you mean without the pin that apple generates every time, if so yes you can.. both status and location of a phone can be retrieved without the need of the pin sent to your phone..

@zhiqihuang
Copy link

So can we get location without 2FA (2FA enabled) ?

@zeeqy I think you mean without the pin that apple generates every time, if so yes you can.. both status and location of a phone can be retrieved without the need of the pin sent to your phone..

Thanks, but how do we do it through pyicloud? do you have a code snippet?

@thevickypedia
Copy link

So can we get location without 2FA (2FA enabled) ?

@zeeqy I think you mean without the pin that apple generates every time, if so yes you can.. both status and location of a phone can be retrieved without the need of the pin sent to your phone..

Thanks, but how do we do it through pyicloud? do you have a code snippet?

@zeeqy This script tracks the location of the phone and triggers an email if out of desired location from AWS SES but basically lines 50-59 has what you're looking for. If you want anything other than status and location you might want to uncomment lines 29-47

https://github.com/thevickypedia/iPhone_Locator/blob/master/locator.py

@zhiqihuang
Copy link

So can we get location without 2FA (2FA enabled) ?

@zeeqy I think you mean without the pin that apple generates every time, if so yes you can.. both status and location of a phone can be retrieved without the need of the pin sent to your phone..

Thanks, but how do we do it through pyicloud? do you have a code snippet?

@zeeqy This script tracks the location of the phone and triggers an email if out of desired location from AWS SES but basically lines 50-59 has what you're looking for. If you want anything other than status and location you might want to uncomment lines 29-47

https://github.com/thevickypedia/iPhone_Locator/blob/master/locator.py

Thank you! You save my little project hah

@bickyb
Copy link

bickyb commented Sep 9, 2020

I would like to trigger the iPhone find my phone functionality programmatically so my phone will beeping so it can be found. Last I tried this, I was dealing with some cookie issues. Has someone figured out a way to get it to work?

@thevickypedia
Copy link

I would like to trigger the iPhone find my phone functionality programmatically so my phone will beeping so it can be found. Last I tried this, I was dealing with some cookie issues. Has someone figured out a way to get it to work?

I don't quite get what you mean by cookie issues. All you need is the play_sound() function. Elaborate your issue if you're looking for something further.

@ajjack50n
Copy link

ajjack50n commented Dec 8, 2020

Hi just been playing with this library - works great. Is the issue with 2FA likely to be resolved? It works but times-out after a few hours.

@B3DTech
Copy link

B3DTech commented Dec 8, 2020

I just set this up and while it appears to be working - things like battery graphs are updated properly. But every half hour I get:

2020-12-08 08:23:49 INFO (SyncWorker_2) [pyicloud.base] Authenticating as user@gmail.com
2020-12-08 08:23:50 INFO (SyncWorker_2) [pyicloud.base] Authentication completed successfully

When this happens I get the notification on my phone that a device is attempting to log in and allow or deny it, and it prompts with the pass code if I allow it, but even if I deny it, which I have been doing for a day now, everything still updates properly.

Any ideas?

@thevickypedia
Copy link

@ajjack50n @B3DTech Apple made the 2FA mandatory in new devices so as far as my knowledge there is no way around it. You can try the keychain option but still you need an initial authentication to kick start any script using this lib, it works without needing a 2FA for ~12 hours after which it will prompt for the auth code.

As of now Apple hasn't launched any authenticator (like Duo or Okta) to do this. If they do launch one, then it might be easy to authenticate using a secret bypassing the annoying 2FA by Apple.

@ajjack50n
Copy link

@thevickypedia @B3DTech

I am not certain I fully understand. Do not apple use, themselves, the same services to enable their own devices to subscribe to iCloud? Why is it that I do not have to keep authenticating my phone for instance? Is it not not possible to exploit the same integration patterns?

@zhiqihuang
Copy link

zhiqihuang commented Dec 12, 2020

I just set this up and while it appears to be working - things like battery graphs are updated properly. But every half hour I get:

2020-12-08 08:23:49 INFO (SyncWorker_2) [pyicloud.base] Authenticating as user@gmail.com
2020-12-08 08:23:50 INFO (SyncWorker_2) [pyicloud.base] Authentication completed successfully

When this happens I get the notification on my phone that a device is attempting to log in and allow or deny it, and it prompts with the pass code if I allow it, but even if I deny it, which I have been doing for a day now, everything still updates properly.

Any ideas?

You can do nothing about it. I ping my iPhone location every 4 hours. Location service is designed for lost and found, so 2FA is not required since you might not have your device to allow it. But that is a login attempt, it will pop up the notification on your device. As far as I know, there is no way to avoid that annoying allow or deny prompt.

@thevickypedia
Copy link

@thevickypedia @B3DTech

I am not certain I fully understand. Do not apple use, themselves, the same services to enable their own devices to subscribe to iCloud? Why is it that I do not have to keep authenticating my phone for instance? Is it not not possible to exploit the same integration patterns?

In layman's terms, it is because your phone has other security measures and it is verified by Apple so it is possible to launch iCloud on your phone without the need of a 2FA, when you use the pyicloud api Apple recognizes the source isn't what your device is so it is natural to kick off a 2FA.
For instance, you can launch iCloud app on an iPhone or iPad or iMac without 2FA but when you use a browser to open iCloud from the same device you will be asked for a verification.
Hope that explains.

@joelmoses
Copy link

Quick update:
A PR has been merged as of January 27, 2021 that brings support for 2FA to pyicloud.
#310

Some work has to be done to merge one other fix and update the documentation, but we are close to closure on this issue.

@nzapponi
Copy link
Collaborator

nzapponi commented Feb 1, 2021

We will be able to close this with #321

@ajjack50n
Copy link

Fantastic news this guys!

@joelmoses
Copy link

@nzapponi - Just saw it pass review on HA/core/dev branch. Congratulations - it's getting closer!

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

No branches or pull requests