branch: externals/url-http-oauth commit f5b953197b880c8de162c50428d9e7c26ab6f3ea Author: Thomas Fitzsimmons <fitz...@fitzsim.org> Commit: Thomas Fitzsimmons <fitz...@fitzsim.org>
Fix auth-source-search for path and scope * url-http-oauth.el(url-http-oauth-port): Fix whitespace. (url-http-oauth-auth-source-search): New function. (url-http-oauth-get-access-token-grant): Search using new function before saving client secret. (url-http-oauth-port): Fix whitespace. (url-http-oauth-get-bearer): Make use of new function. --- url-http-oauth.el | 92 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/url-http-oauth.el b/url-http-oauth.el index 8ec20bc314..40e7b4e72f 100644 --- a/url-http-oauth.el +++ b/url-http-oauth.el @@ -104,9 +104,27 @@ This function does the opposite of `url-http-oauth-interpose'." Assume an HTTPS URL that does not specify a port uses 443." (let ((port-number (url-port url))) (if port-number - (number-to-string port-number) + (number-to-string port-number) (when (string= "https" (url-type url)) "443")))) +(defun url-http-oauth-auth-source-search (&rest spec) + "Like `auth-source-search' but search for all of SPEC in all backends. +Filter out nil spec entries prior to searching." + (let* ((auth-source-do-cache nil) + (all (apply #'auth-source-search :max 5001 spec)) ; no :max 'all + (spec (cl-loop for i below (length spec) by 2 + unless (null (nth (1+ i) spec)) + collect (nth i spec) + unless (null (nth (1+ i) spec)) + collect (nth (1+ i) spec))) + (result (cl-loop for entry in all + when (auth-source-specmatchp spec entry) + collect entry))) + (unless (eq (length result) 1) + (warn "url-http-oauth-auth-source-search produced multiple results for %s" + spec)) + result)) + (defun url-http-oauth-get-access-token-grant (url code) "Get an access token for URL using CODE." (let* ((url-request-method "POST") @@ -120,18 +138,21 @@ Assume an HTTPS URL that does not specify a port uses 443." url-settings))) (auth-result (when client-secret-method - (car (let ((auth-source-creation-prompts - '((secret . "Client secret for %u at %h"))) - ;; Do not cache nil result. - (auth-source-do-cache nil)) - (auth-source-search - :user client-identifier - :host (url-host access-token-object) - :port (url-http-oauth-port access-token-object) - :path (url-filename access-token-object) - :scope scope - :create '(path) - :max 1))))) + (car (let* ((auth-source-creation-prompts + '((secret . "Client secret for %u at %h"))) + ;; Do not cache nil result. + (auth-source-do-cache nil) + (spec (list :user client-identifier + :host (url-host access-token-object) + :port (url-http-oauth-port + access-token-object) + :path (url-filename access-token-object) + :scope scope)) + (existing-entry + (apply #'url-http-oauth-auth-source-search spec))) + (or existing-entry + (apply #'auth-source-search + :create '(path scope) spec)))))) (client-secret (auth-info-password auth-result)) (save-function (plist-get auth-result :save-function)) (authorization (when client-secret @@ -197,20 +218,20 @@ The time is in seconds since the epoch." (defun url-http-oauth-get-bearer (url) "Prompt the user with the authorization endpoint for URL. URL is a parsed object." - (let* ((url-settings (url-http-oauth-settings url)) + (let* ((url (url-http-oauth-url-object url)) + (url-settings (url-http-oauth-settings url)) (path-and-query (url-path-and-query url)) (path (car path-and-query)) (scope (cadr (assoc "scope" url-settings))) (bearer-current (auth-info-password (car (let ((auth-source-do-cache nil)) - (auth-source-search - :user (or (url-user url) "") + (url-http-oauth-auth-source-search + :user (url-user url) :host (url-host url) :port (url-http-oauth-port url) :path path - :scope scope - :max 1)))))) + :scope scope)))))) (unless url-settings (error "%s is not interposed by url-http-oauth" (url-http-oauth-url-string url))) @@ -223,23 +244,24 @@ URL is a parsed object." (url-http-oauth-extract-authorization-code response-url)) (grant (url-http-oauth-get-access-token-grant url code)) (bearer-retrieved (gethash "access_token" grant)) - (auth-result (let ((auth-source-do-cache nil)) - (auth-source-search - :user (or (url-user url) "") - :host (url-host url) - :port (url-http-oauth-port url) - :path path - :scope (if (string= (gethash "scope" grant) - scope) - scope - (error - (concat "url-http-oauth:" - " Returned scope did not" - " match requested scope"))) - :expiry (url-http-oauth-expiry-string grant) - :secret bearer-retrieved - :create '(path scope expiry) - :max 1))) + (spec (list :user (or (url-user url) "") + :host (url-host url) + :port (url-http-oauth-port url) + :path path + :scope (if (string= (gethash "scope" grant) + scope) + scope + (error + (concat "url-http-oauth:" + " Returned scope did not" + " match requested scope"))) + :expiry (url-http-oauth-expiry-string grant) + :secret bearer-retrieved)) + (auth-result + (unless (apply #'url-http-oauth-auth-source-search spec) + (let ((auth-source-do-cache nil)) + (apply #'auth-source-search + :create '(path scope expiry) spec)))) (save-function (plist-get (car auth-result) :save-function))) ;; Success; save bearer. (when (functionp save-function)