Skip to content

Commit

Permalink
Improve auth setup experience with more self-contained explanations/l…
Browse files Browse the repository at this point in the history
…inks
  • Loading branch information
dbarnett committed Aug 25, 2024
1 parent 0b88004 commit b4ebcdd
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 35 deletions.
2 changes: 0 additions & 2 deletions gcalcli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
__program__ = 'gcalcli'
__version__ = 'v4.3.0'
__author__ = 'Eric Davis, Brian Hartvigsen, Joshua Crowgey'
__API_CLIENT_ID__ = '232867676714.apps.googleusercontent.com'
__API_CLIENT_SECRET__ = '3tZSxItw6_VnZMezQwC8lUqy'
4 changes: 2 additions & 2 deletions gcalcli/argparsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
from .printer import valid_color_name

PROGRAM_OPTIONS = {
'--client-id': {'default': gcalcli.__API_CLIENT_ID__,
'--client-id': {'default': None,
'type': str,
'help': 'API client_id'},
'--client-secret': {'default': gcalcli.__API_CLIENT_SECRET__,
'--client-secret': {'default': None,
'type': str,
'help': 'API client_secret'},
'--config-folder': {'default': None, 'type': str,
Expand Down
27 changes: 27 additions & 0 deletions gcalcli/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
from google_auth_oauthlib.flow import InstalledAppFlow # type: ignore
from google.auth.transport.requests import Request # type: ignore


def authenticate(client_id: str, client_secret: str):
flow = InstalledAppFlow.from_client_config(
client_config={
"installed": {
"client_id": client_id,
"client_secret": client_secret,
"auth_uri":
"https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url":
"https://www.googleapis.com/oauth2/v1/certs",
"redirect_uris": ["http://localhost"]
}
},
scopes=['https://www.googleapis.com/auth/calendar']
)
credentials = flow.run_local_server(open_browser=False)
return credentials


def refresh_if_expired(credentials) -> None:
if credentials.expired:
credentials.refresh(Request())
6 changes: 2 additions & 4 deletions gcalcli/deprecations.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
import functools
from typing import Any, Dict

import gcalcli

from .printer import Printer, valid_color_name

printer = Printer()
Expand Down Expand Up @@ -73,8 +71,8 @@ def __call__(self, parser, namespace, values, option_string=None):

OPTIONS: Dict[str, Dict[str, Any]] = {
'program': {
"--client_id": {'default': gcalcli.__API_CLIENT_ID__},
"--client_secret": {'default': gcalcli.__API_CLIENT_SECRET__},
"--client_id": {'default': None},
"--client_secret": {'default': None},
"--configFolder": {'default': None},
"--defaultCalendar": {'default': [], 'action': DeprecatedAppend}
},
Expand Down
62 changes: 35 additions & 27 deletions gcalcli/gcal.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,10 @@
from dateutil.parser import parse
from dateutil.relativedelta import relativedelta
from dateutil.tz import tzlocal
from google_auth_oauthlib.flow import InstalledAppFlow # type: ignore
from googleapiclient.discovery import build # type: ignore
from googleapiclient.errors import HttpError # type: ignore
from google.auth.transport.requests import Request # type: ignore

from . import actions, utils
from . import actions, auth, utils
from ._types import Cache, CalendarListEntry
from .actions import ACTIONS
from .conflicts import ShowConflicts
Expand Down Expand Up @@ -131,6 +129,7 @@ def _retry_with_backoff(self, method):

def _google_auth(self):
if not self.credentials:
# Try loading cached credentials
if self.options['config_folder']:
oauth_filepath = os.path.expanduser(
'%s/oauth' % self.options['config_folder']
Expand All @@ -139,31 +138,40 @@ def _google_auth(self):
oauth_filepath = os.path.expanduser('~/.gcalcli_oauth')
if os.path.exists(oauth_filepath):
with open(oauth_filepath, 'rb') as gcalcli_oauth:
credentials = pickle.load(gcalcli_oauth)
else:
flow = InstalledAppFlow.from_client_config(
client_config={
"installed": {
"client_id": self.options['client_id'],
"client_secret": self.options['client_secret'],
"auth_uri":
"https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url":
"https://www.googleapis.com/oauth2/v1/certs",
"redirect_uris": ["http://localhost"]
}
},
scopes=['https://www.googleapis.com/auth/calendar']
self.credentials = pickle.load(gcalcli_oauth)
if not self.credentials:
# No cached credentials, start auth flow
self.printer.msg(
'Not yet authenticated. Starting auth flow...\n', 'yellow')
self.printer.msg(
'NOTE: See https://github.com/insanum/gcalcli for '
'help/troubleshooting.\n')
missing_info = [opt for opt in ['client_id', 'client_secret']
if self.options.get(opt) is None]
if missing_info:
self.printer.msg(
f"You'll be asked for a {' and '.join(missing_info)} "
'that you should have set up for yourself in Google '
'dev console.\n'
)
credentials = flow.run_local_server(open_browser=False)
with open(oauth_filepath, 'wb') as gcalcli_oauth:
pickle.dump(credentials, gcalcli_oauth)

if credentials.expired:
credentials.refresh(Request())

self.credentials = credentials
client_id = self.options.get('client_id')
if client_id is None:
self.printer.msg('Client ID: ', 'magenta')
client_id = input()
client_secret = self.options.get('client_secret')
if client_secret is None:
self.printer.msg('Client Secret: ', 'magenta')
client_secret = input()
self.printer.msg(
'Now click the link below and follow directions to '
'authenticate.\n', 'yellow')
self.printer.msg(
'You will likely see a security warning page and need to '
'click "Advanced" and "Go to gcalcli (unsafe)" to proceed.\n')
self.credentials = auth.authenticate(client_id, client_secret)
with open(oauth_filepath, 'wb') as gcalcli_oauth:
pickle.dump(self.credentials, gcalcli_oauth)
auth.refresh_if_expired(self.credentials)
return self.credentials

def get_cal_service(self):
Expand Down

0 comments on commit b4ebcdd

Please sign in to comment.