emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: oauth2 support for Emacs email clients


From: Andrew Cohen
Subject: Re: oauth2 support for Emacs email clients
Date: Wed, 11 Aug 2021 08:43:21 +0800
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

>>>>> "RW" == Roland Winkler <winkler@gnu.org> writes:


[...]


    RW> I just want to confirm I have read your posts with great
    RW> interest, thank you.  I am still in the process of digesting
    RW> them.  These topics (including emacs tools like plstore /
    RW> auth-store / auth-source) have not been my area of expertise.
    RW> So I am still trying to understand better how to put these
    RW> things together so that I get what I want / need.

I hope I can provide useful info. (I keep accidentally typing
"auth-store" instead of "auth-source" so I think that's one less topic to
worry about :))

    RW> In the meanwhile one question:

    RW> With your setup, what happens if you need to restart emacs?  Are
    RW> you storing the oauth2 tokens on disk so that you need not
    RW> re-authenticate (as long as the tokens themselves remain valid,
    RW> which is 30 days for my organizations)?

Yes, the oauth2 credentials are stored on disk. Everything works as
usual upon restarting emacs: gnus uses auth-source to retrieve the
appropriate credentials from the on-disk storage and the existing
refresh-token is used to automatically obtain a new access-token (a
password is requested to decrypt the on-disk storage if the cached value
has timed out, but otherwise no action by the user is needed).

auth-source is a great way to store and retrieve credentials for
accessing services (and other things too). It is used by gnus, smtpmail
(and I think rmail) and probably lots of other service-based things.

A typical entry includes host, user, port, secret (i.e. password) and
whatever other things you like. auth-source has several different
storage backends (netrc, plstore, json, secrets, and several more) and a
simple search mechanism that spans different backends to retrieve
appropriate authentication data.

For my oauth2 imap and smtp access I simply created appropriate entries
(each of which includes a token structure as defined in oauth2.el)
using the plstore backend (so the entry is stored on disk with the
sensitive parts encrypted).

Aside from the slightly funky structure of the auth-store entry
(including an ouath2 token) this works exactly as any other auth-store
entry to using imap or smtp---that was the reason for setting it up this
way, so it looked like any other SASL to the user and didn't require a
new package (just some minor tweaks to existing code).


Aside: I have another minor change to push to auth-source to make this
work. The plstore backend in auth-source only encrypts the :secret
entry, but I want to keep the client-secret and the oauth2 token
structure in the entry encrypted as well. This required some minor
tweaking to  auth-source to allow specifying which parts of the entry
are encrypted and which are unencrypted. Patch below (which I will push
myself in awhile). 

diff --git a/lisp/auth-source.el b/lisp/auth-source.el
index 6919738398..faddbdee1a 100644
--- a/lisp/auth-source.el
+++ b/lisp/auth-source.el
@@ -2120,11 +2120,17 @@ auth-source-plstore-create
          (base-secret '(secret))
          ;; we know (because of an assertion in auth-source-search) that the
          ;; :create parameter is either t or a list (which includes nil)
-         (create-extra (if (eq t create) nil create))
+        (create-secret-extra (plist-get create :encrypted))
+         (create-extra (if (eq t create) nil
+                        (or
+                         (append
+                          (plist-get create :unencrypted) create-secret-extra)
+                            create)))
          (current-data (car (auth-source-search :max 1
                                                 :host host
                                                 :port port)))
          (required (append base-required create-extra))
+        (required-secret (append base-secret create-secret-extra))
          ;; `valist' is an alist
          valist
          ;; `artificial' will be returned if no creation is needed


Best,
Andy


-- 
Andrew Cohen

Director, HKUST Jockey Club Institute for Advanced Study
Lam Woo Foundation Professor and Chair Professor of Physics

The Hong Kong University of Science and Technology



reply via email to

[Prev in Thread] Current Thread [Next in Thread]