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

Add automatic Gmail MFA #160

Merged
merged 2 commits into from
Apr 29, 2021

Conversation

booi
Copy link
Contributor

@booi booi commented Dec 2, 2020

Hi all, I noticed that Arlo was enforcing MFA on all accounts now and this could break the Arlo python library which I use to backup videos.

This is a preliminary PR to add support for automatic MFA retrieval and submission without using SMS or other paid services. The only prerequisite is using a Gmail account. This PR also adds a new LoginMFA method that is conditionally called and contains a process that I've reverse engineered from Arlo's website.

What this PR still needs:

  • I need help packaging this up correctly. I've added some dependencies but they are not reflected in the requirements.txt file. I wasn't able to figure out how to correctly update this file with the new dependencies.
  • The gmail_oauth.py script needs to be made available to users in order to create their credential file.

I'm copy and pasting the content in docs/ARLO_MFA.md here to aid in review.

Instructions

  1. Login with a new or existing Gmail account.
    • The script will have read-only permissions on this gmail account.
    • Care is taken to only search and load emails relevant to Arlo MFA but the script does have access to the entire mailbox.
    • While this implementation is completely private, it's recommended to use a separate gmail account for Arlo login purposes.
  2. Create or use an existing Google Cloud project.
  3. Enable the Gmail API
    • Go to APIs & Services -> Library
    • Search for Gmail
    • Enable the Gmail API
  4. Setup the OAuth consent screen
    • Go to APIs & Services -> OAuth consent screen
    • Setup OAuth consent screen
      • The app name and emails can be anything.
    • Scopes
      • Add Scopes
      • Filter for "Gmail API"
      • Add the scope ".../auth/gmail.readonly"
    • Test Users
      • Add the gmail address of your Arlo login
  5. Create OAuth 2.0 Client ID credentials
    • Click on Create Credentials -> OAuth client id
    • Under Application type, select "Web application"
    • Name can be anything
    • Under "Authorized redirect URIs", add "http://localhost:7788"
    • Click Create
    • Close the window with the credentials, we will save them in the next step.
  6. Save the OAuth client credential package
    • For the newly client id row, click the download button (down arrow) on the right side
    • Save this credential in your project as "google_client_credentials.json"
  7. Run the gmail_oauth.py script
    • This will open a browser and ask you to login and authenticate with Google
    • It may warn you that this is a test application, please force continue
    • Approve of the gmail read only scope on the next screen
    • This script will save a file called gmail.credentials. This file will allow us to persistently access the gmail account programmatically.
  8. Update your project to pass the name of this file into the Arlo class.
    • For example, instead of arlo = Arlo(USERNAME, PASSWORD)
    • Call arlo = Arlo(USERNAME, PASSWORD, '/path/to/gmail.credentials)

How it works

We are creating an OAuth application and registering it with Google. The gmail_oauth.py script forwards you to authenticate with this application and grant your application read-only access to your mailbox.

When we initialize the Arlo class, the LoginMFA function:

  • Authenticates against the Arlo API
  • Fetches valid MFA factors
  • Selects the "EMAIL" factor
  • Begins authentication with this factor
  • Waits 5 seconds
  • Checks your gmail account by searching for new emails (postmarked AFTER the beginning of authentication) with an arlo authentication code.
  • Extract this code and complete the authentication process.

@booi
Copy link
Contributor Author

booi commented Dec 2, 2020

I am able to successfully authenticate with this PR. However, it appears that the api has changed.

After authentication, when I attempt to use the library, I get this error

401 Client Error: Unauthorized for url: https://my.arlo.com/hmsweb/users/library

Looking at my network trace interacting with the website, the API seems to live at myapi.arlo.com now instead of my.arlo.com/hmsweb. I didn't investigate further to see if this is merely a hostname change or a different API altogether.

@booi booi mentioned this pull request Dec 2, 2020
@jeffreydwalter
Copy link
Owner

@booi I haven't taken a look at your code yet, but 2FA is not required yet. With 2FA disabled, this library still works as-is.

When I login using the web interface, I do see the endpoints it's calling are different, and I believe required if you want to use 2FA.

I unfortunately don't really have time to add support for 2FA, but I'd be really happy to accept a PR that makes it all work.

@jeffreydwalter jeffreydwalter changed the base branch from master to mfa-pr April 29, 2021 00:58
@jeffreydwalter jeffreydwalter merged commit 6f7645f into jeffreydwalter:mfa-pr Apr 29, 2021
@jeffreydwalter
Copy link
Owner

@booi I FINALLY got around to integrating your PR into this library. (Had to deal with a bug in requests/urllib3). I have a branch with your code merged in and the auth issue you were describing is fixed (it was the requests/urllib3 bug).

If you're still out there, would appreciate it if you'd give the branch a try and let me know if I merged it correctly.

Thanks!

@booi
Copy link
Contributor Author

booi commented Jul 28, 2021

@jeffreydwalter Hi! Sorry I must have missed the notification of this / don't pay a lot of attention to github emails. It appears to be merged correctly.

You know, I ended up not using it since 2fa was not mandatory back then but it appears to be mandatory now so could come in useful?

@cgmckeever
Copy link

@booi @jeffreydwalter (Apologies if this has been discussed - and I could have sworn I saw this referenced elsewhere). Since these app that is granted gmail permission is in test status, the certs expire in 7 days. Is this correct? My service just started dying, and I found this post reference the 7 day .

Any workarounds to this, or is it just something that needs to be done weekly?

@booi
Copy link
Contributor Author

booi commented Jan 10, 2022

Ah interesting, that's why it stopped working periodically for me. I wonder if this is a (relatively) new behavior. I think the best thing to do would be to promote your app to production and take it out of test mode?

If you end up doing that, please report back

@cgmckeever
Copy link

Not sure how easy it will to be pass this ....

Screen Shot 2022-01-10 at 7 24 42 AM

@cgmckeever
Copy link

@booi looks like there is more you can do within a Google Workspace. I converted, will find out in 7 days ;)
https://stackoverflow.com/questions/70653369/google-cloud-api-services-oauth-with-a-testing-app/70653489#70653489
https://support.google.com/a/answer/7378726?hl=en

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

Successfully merging this pull request may close these issues.

3 participants