insanum / gcalcli

Google Calendar Command Line Interface
MIT License
3.26k stars 307 forks source link

Any way to make Google app authorization last longer? #611

Open ajkessel opened 2 years ago

ajkessel commented 2 years ago

I find I have to reauthorize this app (using the same device) at least 1-2x per week, i.e. by running gcalcli with --noauth_local_webserver and my client-id and client-secret, then navigating through the Google prompts to trust the app. Is there any way to make this authorization last longer so I can rely on gcalcli for automated processing without needing to keep checking if it remains authorized?

HussX commented 2 years ago

I second that. Can we reup the app approval to avoid the oauth route? I'm using this on a remote PI to pull data from other locations and update the calendar on the screen. It works with oauth, but the weekly loss will get irritating.

ManuRS commented 2 years ago

I think is google side problem. They revoke super fast the authorization. It's annoying

aristosv commented 2 years ago

anyone found a way to do this?

Nephiel commented 1 year ago

Same as #603, #628, #634

ajkessel commented 1 year ago

Apparently this is a limitation if your app is set to "testing" rather than "published". But when I try to publish, it requires a bunch of information and manual verification from Google, because the app has "sensitive scope". Is there any way to set the Google API scope so it's not "sensitive" requiring verification? Has anyone figured out exactly what scope is necessary for gcalcli to still work?

ajkessel commented 1 year ago

I've made some progress. It's possible to remove all the sensitive scope authorizations if you set gcalcli to post to a secondary calendar. Then you should be able to publish your app without Google verification. However, to do this, you need to set redirect_uri to something other than urn:ietf:wg:oauth:2.0:oob (e.g. http://localhost:0, or a custom URL on your own server that could print out the activation code).

I patched the gcalcli code to allow a --redirect-uri parameter. However, it appears that [https://github.com/googleapis/oauth2client/issues/317] tools.run_flow ignores this setting, and that code is no longer maintained.

Anyone with better Python and googleapi knowledge than me able to fix this?

Alternatively, gcalcli code be rewritten to use google-auth rather than oauth2client, as the latter is now deprecated. https://google-auth.readthedocs.io/en/latest/oauth2client-deprecation.html . But this seems like a significant undertaking.

Nephiel commented 1 year ago

I've made some progress. It's possible to remove all the sensitive scope authorizations if you set gcalcli to post to a secondary calendar. Then you should be able to publish your app without Google verification. However, to do this, you need to set redirect_uri to something other than urn:ietf:wg:oauth:2.0:oob (e.g. http://localhost:0, or a custom URL on your own server that could print out the activation code).

I patched the gcalcli code to allow a --redirect-uri parameter. However, it appears that [https://github.com/[googleapis/oauth2client/issues/317](https://github.com/googleapis/oauth2client/issues/317)] tools.run_flow ignores this setting, and that code is no longer maintained.

Anyone with better Python and googleapi knowledge than me able to fix this?

Alternatively, gcalcli code be rewritten to use google-auth rather than oauth2client, as the latter is now deprecated. https://google-auth.readthedocs.io/en/latest/oauth2client-deprecation.html . But this seems like a significant undertaking.

I agree, IMO replacing oauth2client with google-auth in gcalcli would be the proper solution. Meanwhile, I may have found another (ugly) way to avoid the deprecated OOB flow.

First, create a new OAuth 2.0 Client ID for gcalcli, but instead of Desktop, choose Web Application. On this new Client ID for Web application, set an Authorized redirect URI to http://localhost and save the changes. Then retrieve the Client ID and Client secret values and ensure they are passed to gcalcli when running it (e.g. set them in ~/.gcalclirc).

Then, edit the oauth2client library (in my case located at /usr/lib/python3/dist-packages/oauth2client/client.py) and replace the deprecated OOB URN value OOB_CALLBACK_URN = 'urn:ietf:wg:oauth:2.0:oob' with OOB_CALLBACK_URN = 'http://localhost' (yes, that is the ugly part).

Run gcalcli from a command line. When it presents the authorization URL and asks for the verification code, open the URL on a browser, log in to the Google account you want to use, check the scopes and stuff it's asking for, and if you're OK with that, allow it. Your browser will then take you to an error page, but the verification code you need should be in the address bar in the form http://localhost/?code=xxxx&scope=.... Copy only the code (xxxx) from there (note that it may begin with a digit and a slash) and paste it back on the commandline where gcalcli is waiting. It should reply with Authentication successful.

It remains to be seen if this method requires reauthorization every 7 days. I will test and report back.

ajkessel commented 1 year ago

I've created a slightly less ugly fix. Below is a patch to python-oauth2client (v4.1.3 from Ubuntu) that allows you to set OOB_CALLBACK_URN via environmental variable. I've also posted an unsigned DEB at https://adam.rosi-kessel.org/deb/python3-oauth2client_4.1.3-2.1_all.deb .

You can also make the process less ugly by setting a real URL rather than localhost. I have a simple PHP page that just returns the code passed to it (code below).

So here is the full workflow:

  1. Install my modified python3-oauth2client package, or patch the code yourself
  2. Set up a PHP page (I use "code.php") with the PHP code below, to catch the oauth2 redirect
  3. Create a new OAuth 2.0 Client ID on Google API as a Web Application, including your redirect URL as authorized
  4. Publish your Google app so it is no longer in testing
  5. export OOB_CALLBARK_URN = 'http://yourdomain.com/code.php'
  6. Generate a new token with gcalcli in the normal way

Patch code:

Description: Allow user to set oob_callback_urn via environmental variable
Author: Adam Kessel <ajkessel@gmail.com>
Forwarded: no
Last-Update: 2021-01-07

--- python-oauth2client-4.1.3.orig/oauth2client/client.py
+++ python-oauth2client-4.1.3/oauth2client/client.py
@@ -61,7 +61,11 @@
 ID_TOKEN_VERIFICATON_CERTS = ID_TOKEN_VERIFICATION_CERTS

 # Constant to use for the out of band OAuth 2.0 flow.
-OOB_CALLBACK_URN = 'urn:ietf:wg:oauth:2.0:oob'
+# 2022-08-04 AJK patch to check for environmental variable set to OOB_CALLBACK_URN
+if os.getenv("OOB_CALLBACK_URN") is not None:
+   OOB_CALLBACK_URN = os.getenv("OOB_CALLBACK_URN")
+else:
+   OOB_CALLBACK_URN = 'urn:ietf:wg:oauth:2.0:oob'

 # The value representing user credentials.
 AUTHORIZED_USER = 'authorized_user'

PHP code:

<html>
<body>
<?php
  echo htmlspecialchars($_GET["code"]);
?>
</body>
</html>

An even spiffier solution would be for gcalcli to grab the code from the code.php URL, so that the user doesn't need to copy and paste back to the CLI. This wouldn't be much work to implement, although if this solution "sticks" so that regenerating the token is very rare, it may not be necessary.

Nephiel commented 1 year ago

It remains to be seen if this method requires reauthorization every 7 days. I will test and report back.

My test gcalcli setup asks for autorization again, so I guess this approach still doesn't solve the issue.

ajkessel commented 1 year ago

My solution posted above is working for me. I do run gcalcli hourly (gcalcli agenda > /dev/null 2>&1 as a cronjob) to make sure the token is regularly refreshed. I've been using it for more than a week now with no re-authorization required.

Nephiel commented 1 year ago

Looking at the contents of ~/.gcalcli_oauth right after authorization, apparently the value of token_expiry is set one hour in the future, so unless gcalcli is run regularly at least once per hour, it will eventually ask for authorization again :(

ajkessel commented 1 year ago

Running gcalcli via cron every hour appears to have solved the problem completely for me.

NightMachinery commented 1 year ago

Running gcalcli via cron every hour appears to have solved the problem completely for me.

Does this only work with your patched version?

NightMachinery commented 1 year ago

Running gcalcli via cron every hour appears to have solved the problem completely for me.

Is there a way to share the auth between a server and my laptop? I can't run a job every N hour on a laptop.

hramrach commented 4 months ago

Interestingly I do not see this problem but not sure what the difference is.