diff options
Diffstat (limited to 'modules/auth-config.el')
| -rw-r--r-- | modules/auth-config.el | 147 |
1 files changed, 141 insertions, 6 deletions
diff --git a/modules/auth-config.el b/modules/auth-config.el index 6b8a8ddb..83a7e2d0 100644 --- a/modules/auth-config.el +++ b/modules/auth-config.el @@ -7,14 +7,23 @@ ;; • auth-source ;; – Forces use of your default authinfo file -;; – Disable external GPG agent in favor of Emacs’s own prompt +;; – Disable external GPG agent in favor of Emacs's own prompt ;; – Enable auth-source debug messages ;; • Easy PG Assistant (epa) -;; – Force using the ‘gpg2’ executable for encryption/decryption operations +;; – Force using the 'gpg2' executable for encryption/decryption operations + +;; • oauth2-auto cache fix (via advice) +;; – oauth2-auto version 20250624.1919 has caching bug on line 206 +;; – Function oauth2-auto--plstore-read has `or nil` disabling cache +;; – This caused GPG passphrase prompts every ~15 minutes during gcal-sync +;; – Fix: Advice to enable hash-table cache without modifying package +;; – Works across package updates +;; – Fixed 2025-11-11 ;;; Code: +(require 'system-lib) (eval-when-compile (require 'user-constants)) ;; defines authinfo-file location ;; -------------------------------- Auth Sources ------------------------------- @@ -24,9 +33,11 @@ :ensure nil ;; built in :demand t ;; load this package immediately :config - (setenv "GPG_AGENT_INFO" nil) ;; disassociate with external gpg agent - (setq auth-sources `(,authinfo-file)) ;; use authinfo.gpg (see user-constants.el) - (setq auth-source-debug t)) ;; echo debug info to Messages + ;; USE gpg-agent for passphrase caching (400-day cache from gpg-agent.conf) + ;; (setenv "GPG_AGENT_INFO" nil) ;; DISABLED: was preventing gpg-agent cache + (setq auth-sources `(,authinfo-file)) ;; use authinfo.gpg (see user-constants.el) + (setq auth-source-debug t) ;; echo debug info to Messages + (setq auth-source-cache-expiry 86400)) ;; cache decrypted credentials for 24 hours ;; ----------------------------- Easy PG Assistant ----------------------------- ;; Key management, cryptographic operations on regions and files, dired @@ -38,7 +49,131 @@ :config (epa-file-enable) ;; (setq epa-pinentry-mode 'loopback) ;; emacs request passwords in minibuffer - (setq epg-gpg-program "gpg2")) ;; force use gpg2 (not gpg v.1) + (setq epg-gpg-program "gpg2") ;; force use gpg2 (not gpg v.1) + + ;; Update gpg-agent with current DISPLAY environment + ;; This ensures pinentry can open GUI windows when Emacs starts + (call-process "gpg-connect-agent" nil nil nil "updatestartuptty" "/bye")) + +;; ---------------------------------- Plstore ---------------------------------- +;; Encrypted storage used by oauth2-auto for Google Calendar tokens. +;; CRITICAL: Enable passphrase caching to prevent password prompts every 10 min. + +(use-package plstore + :ensure nil ;; built-in + :demand t + :config + ;; Cache passphrase indefinitely (relies on gpg-agent for actual caching) + (setq plstore-cache-passphrase-for-symmetric-encryption t) + ;; Allow gpg-agent to cache the passphrase (400 days per gpg-agent.conf) + (setq plstore-encrypt-to nil)) ;; Use symmetric encryption, not key-based + +;; ----------------------------- oauth2-auto Cache Fix ----------------------------- +;; Fix oauth2-auto caching bug that causes repeated GPG passphrase prompts. +;; The package has `or nil` on line 206 that disables its internal cache. +;; This advice overrides the buggy function to enable caching properly. + +(defun cj/oauth2-auto--plstore-read-fixed (username provider) + "Fixed version of oauth2-auto--plstore-read that enables caching. + +This is a workaround for oauth2-auto.el bug where line 206 has: + (or nil ;(gethash id oauth2-auto--plstore-cache) +which completely disables the internal hash-table cache. + +This function re-implements the intended behavior with cache enabled." + (require 'oauth2-auto) ; Ensure package is loaded + (let ((id (oauth2-auto--compute-id username provider))) + ;; Check cache FIRST (this is what the original should do) + (or (gethash id oauth2-auto--plstore-cache) + ;; Cache miss - read from plstore and cache the result + (let ((plstore (plstore-open oauth2-auto-plstore))) + (unwind-protect + (puthash id + (cdr (plstore-get plstore id)) + oauth2-auto--plstore-cache) + (plstore-close plstore)))))) + +;; Apply the fix via advice (survives package updates) +(with-eval-after-load 'oauth2-auto + (advice-add 'oauth2-auto--plstore-read :override #'cj/oauth2-auto--plstore-read-fixed) + (cj/log-silently "✓ oauth2-auto cache fix applied via advice")) + +;; ------------------------ Authentication Reset Utility ----------------------- + +(defun cj/reset-auth-cache (&optional include-gpg-agent) + "Reset authentication caches when wrong password was entered. + +By default, only clears Emacs-side caches (auth-source, EPA file +handler) and leaves gpg-agent's long-term cache intact. This preserves +your 400-day cache for GPG and SSH passphrases. + +With prefix argument INCLUDE-GPG-AGENT (\\[universal-argument]), also +clears gpg-agent's password cache. Use this when gpg-agent itself has +cached an incorrect password. + +Clears: +1. auth-source cache (Emacs-level credential cache) +2. EPA file handler cache (encrypted file cache) +3. gpg-agent cache (only if INCLUDE-GPG-AGENT is non-nil) + +Use this when you see errors like: + - \"Bad session key\" + - \"Decryption failed\" + - GPG repeatedly using wrong cached password" + (interactive "P") + (message "Resetting authentication caches...") + + ;; Clear auth-source cache (Emacs credential cache) + (auth-source-forget-all-cached) + + ;; Clear EPA file handler cache + (when (fboundp 'epa-file-clear-cache) + (epa-file-clear-cache)) + + ;; Only clear gpg-agent cache if explicitly requested + (if include-gpg-agent + (let ((result (shell-command "echo RELOADAGENT | gpg-connect-agent"))) + (if (zerop result) + (message "✓ Emacs and gpg-agent caches cleared. Next access will prompt for password.") + (message "⚠ Warning: Failed to clear gpg-agent cache"))) + (message "✓ Emacs caches cleared. GPG/SSH passphrases preserved for session."))) + +(defun cj/kill-gpg-agent () + "Force kill gpg-agent (it will restart automatically on next use). + +This is a more aggressive reset than `cj/reset-auth-cache'. Use this +when gpg-agent is stuck or behaving incorrectly. + +The gpg-agent will automatically restart on the next GPG operation." + (interactive) + (let ((result (shell-command "gpgconf --kill gpg-agent"))) + (if (zerop result) + (message "✓ gpg-agent killed. It will restart automatically on next use.") + (message "⚠ Warning: Failed to kill gpg-agent")))) + +(defun cj/clear-oauth2-auto-cache () + "Clear the oauth2-auto in-memory token cache. + +This forces oauth2-auto to re-read tokens from oauth2-auto.plist on next +access. Useful when OAuth tokens have been manually updated or after +re-authentication. + +Note: This only clears Emacs's in-memory cache. The oauth2-auto.plist +file on disk is not modified." + (interactive) + (if (boundp 'oauth2-auto--plstore-cache) + (progn + (clrhash oauth2-auto--plstore-cache) + (message "✓ oauth2-auto token cache cleared")) + (message "⚠ oauth2-auto not loaded yet"))) + +;; Keybindings +(with-eval-after-load 'keybindings + (keymap-set cj/custom-keymap "A" #'cj/reset-auth-cache)) + +(with-eval-after-load 'which-key + (which-key-add-key-based-replacements + "C-; A" "reset auth cache")) (provide 'auth-config) ;;; auth-config.el ends here. |
