@@ -289,10 +289,35 @@ for reference) and the
289289`BDAY <https://www.rfc-editor.org/rfc/rfc6350#section-6.2.5 >`_ property is not
290290synced when only partial date information is present (e.g. the year is missing).
291291
292- At first run you will be asked to authorize application for Google account
293- access.
292+ Authentication
293+ ++++++++++++++
294294
295- To use this storage type, you need to install some additional dependencies::
295+ There are two ways to handle OAuth authentication with Google:
296+
297+ 1. **Built-in OAuth flow ** (``token_file `` + ``client_id `` + ``client_secret ``):
298+ Vdirsyncer manages the OAuth2 flow, including token storage and refresh. At
299+ first run you will be asked to authorize the application via a browser.
300+
301+ 2. **External token command ** (``token_command ``): An external command is
302+ executed to obtain a fresh access token on demand. Vdirsyncer passes the
303+ token as a ``Bearer `` header and re-runs the command on 401 responses.
304+
305+ With ``token_command ``, you do not need to register a Google Cloud project or
306+ install ``aiohttp-oauthlib ``. Any OAuth helper that prints an access token to
307+ stdout works, e.g. `oama <https://github.com/pdobsan/oama >`_::
308+
309+ [storage my_google_cal]
310+ type = "google_calendar"
311+ token_command = ["oama", "access", "my-google-account"]
312+
313+ The command can be specified as a list (executed directly) or a string (run via
314+ shell).
315+
316+ Built-in OAuth setup
317+ ++++++++++++++++++++
318+
319+ To use the built-in OAuth flow, you need to install some additional
320+ dependencies::
296321
297322 pip install vdirsyncer[google]
298323
@@ -344,15 +369,22 @@ itself or write anything to it.
344369 token_file = "..."
345370 client_id = "..."
346371 client_secret = "..."
372+ #token_command = null
347373 #start_date = null
348374 #end_date = null
349375 #item_types = []
350376
351377 Please refer to :storage: `caldav ` regarding the ``item_types `` and timerange parameters.
352378
353- :param token_file: A filepath where access tokens are stored.
379+ :param token_file: A filepath where access tokens are stored. Optional if
380+ ``token_command `` is set.
354381 :param client_id/client_secret: OAuth credentials, obtained from the Google
355- API Manager.
382+ API Manager. Optional if ``token_command ``
383+ is set.
384+ :param token_command: Command to fetch an OAuth access token. Can be a list
385+ of arguments or a string (run via shell). The command
386+ must print a valid bearer token to stdout. When set,
387+ ``token_file `` and OAuth credentials are not required.
356388
357389.. storage :: google_contacts
358390
@@ -365,14 +397,22 @@ itself or write anything to it.
365397 token_file = "..."
366398 client_id = "..."
367399 client_secret = "..."
400+ #token_command = null
368401
369- :param token_file: A filepath where access tokens are stored.
402+ :param token_file: A filepath where access tokens are stored. Optional if
403+ ``token_command `` is set.
370404 :param client_id/client_secret: OAuth credentials, obtained from the Google
371- API Manager.
372-
373- The current flow is not ideal, but Google has deprecated the previous APIs used
374- for this without providing a suitable replacement. See :gh: `975 ` for discussion
375- on the topic.
405+ API Manager. Optional if ``token_command ``
406+ is set.
407+ :param token_command: Command to fetch an OAuth access token. Can be a list
408+ of arguments or a string (run via shell). The command
409+ must print a valid bearer token to stdout. When set,
410+ ``token_file `` and OAuth credentials are not required.
411+
412+ The built-in OAuth flow is not ideal, but Google has deprecated the previous
413+ APIs used for this without providing a suitable replacement. See :gh: `975 ` for
414+ discussion on the topic. Using ``token_command `` with an external OAuth helper
415+ sidesteps these issues.
376416
377417Local
378418+++++
0 commit comments