branch: externals/url-http-oauth
commit 68e74fbc6ac5060a26d76d3c3424e27824536e99
Author: Thomas Fitzsimmons <[email protected]>
Commit: Thomas Fitzsimmons <[email protected]>

    Import url-http-oauth-demo.el from its own repo
    
    * url-http-oauth-demo.el: New file.
    * url-http-oauth.el: Mention url-http-oauth-demo.el in comment
    header.
---
 url-http-oauth-demo.el | 157 +++++++++++++++++++++++++++++++++++++++++++++++++
 url-http-oauth.el      |   3 +-
 2 files changed, 159 insertions(+), 1 deletion(-)

diff --git a/url-http-oauth-demo.el b/url-http-oauth-demo.el
new file mode 100644
index 0000000000..d22f04e6ab
--- /dev/null
+++ b/url-http-oauth-demo.el
@@ -0,0 +1,157 @@
+;;; url-http-oauth-demo.el --- Demo url-http-oauth -*- lexical-binding: t -*-
+
+;; Copyright (C) 2023 Free Software Foundation, Inc.
+
+;; Author: Thomas Fitzsimmons <[email protected]>
+;;
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; This package demonstrates OAuth 2.0 authentication and
+;; authorization to Sourcehut, using the built-in `url' and
+;; `auth-source'libraries and the new `url-http-oauth' package.
+;;
+;; Background:
+;;
+;; Sourcehut has implemented OAuth 2.0 for its services.  Its
+;; implementation is unique in that it is released as Free Software,
+;; and does not require JavaScript for any of the OAuth 2.0 steps.
+;;
+;; Here is a diagram summarizing the protocol, adapted from RFC 6749:
+;;
+;;           `url' and `url-http-oauth' implement
+;;                  these middle steps
+;; +--------+                               +------------------------+
+;; |        |--(A)- Authorization Request ->|    (Resource Owner)    |
+;; |        |                               |                        |
+;; |        |<-(B)-- Authorization Grant ---| You, the Human,        |
+;; |        |                               | user of Emacs and      |
+;; |        |                               | Sourcehut, performing  |
+;; |        |                               | steps in a web browser |
+;; |        |                               +------------------------+
+;; |        |
+;; |        |                               +----------------------+
+;; |        |--(C)-- Authorization Grant -->|(Authorization Server)|
+;; |(Client)|                               |                      |
+;; |        |<-(D)----- Access Token -------| URLs starting with   |
+;; | Emacs  |                               | meta.sr.ht/oauth2    |
+;; |        |                               +----------------------+
+;; |        |
+;; |        |                               +--------------------+
+;; |        |--(E)----- Access Token ------>| (Resource Server)  |
+;; |        |                               |                    |
+;; |        |<-(F)--- Protected Resource ---| URLs starting with |
+;; |        |                               | meta.sr.ht/query   |
+;; +--------+                               +--------------------+
+;;
+;; For generality¹ there is no web browser automation.  Here is a
+;; breakdown of Steps A and B:
+;;
+;; Step A:
+;;      A.1: A request URL is shown in the minibuffer; the minibuffer
+;;           prompts for a response URL and waits.
+;;      A.2: The user copies the request URL into their web browser of
+;;           choice¹.
+;;      A.3: The user authenticates to Sourcehut, using the web browser.
+;;      A.4: The user authorizes Emacs to access their Sourcehut
+;;           resource, using the web browser.
+;;      A.5: The web browser redirects to a URL; this redirection may
+;;           fail or it may not.  All that matters is the URL itself,
+;;           which will contain a "code" query argument.
+;;      A.6: The user copies the full "code" URL from the web browser.
+;;
+;; Step B:   The user pastes the full "code" URL into the minibuffer
+;;           and presses RET.
+;;
+;; The remaining steps, C through F, are all handled within Emacs.
+;;
+;; 1. For example, when running Emacs in a VT100 terminal emulator
+;;    through two SSH hops.
+;;
+;; 2. For Sourcehut in particular, steps A.2 through A.5 can be done
+;;    using EWW because Sourcehut does not need JavaScript.  Today EWW
+;;    needs to run in a separate process so it does not conflict with
+;;    url-http-oauth, which blocks the minibuffer waiting for the
+;;    response URL.
+
+;;; Code:
+(require 'url-http-oauth)
+
+(defun url-http-oauth-demo-get-profile-name ()
+  "Asynchronously retrieve the Sourcehut profile name.
+Print the result to *Messages*.  Return the name."
+  (interactive)
+  (unless (url-http-oauth-interposed-p "https://meta.sr.ht/query";)
+    ;; Tell Emacs that the URL "https://meta.sr.ht/query"; uses OAuth
+    ;; 2.0 for authentication and authorization.
+    (url-http-oauth-interpose
+     '(;; The client identifier.  Replace "" with a new client
+       ;; identifier generated by the user, or by the Emacs library
+       ;; developer, at "https://meta.sr.ht/oauth2/client-registration";.
+       ("client-identifier" . "")
+       ;; The URL at which the `url-http-oauth-demo' package will access
+       ;; resources.  Everything that follows is for authentication and
+       ;; authorization to satisfy OAuth 2.0 requirements.
+       ("resource-url" . "https://meta.sr.ht/query";)
+       ;; The authorization and token endpoints, published in
+       ;; "https://man.sr.ht/meta.sr.ht/oauth.md";.  There is no way to
+       ;; autodiscover them from "https://meta.sr.ht/query";.
+       ("authorization-endpoint" . "https://meta.sr.ht/oauth2/authorize";)
+       ("access-token-endpoint" . "https://meta.sr.ht/oauth2/access-token";)
+       ;; The list of features to which Emacs is requesting the server
+       ;; grant it access.
+       ("scope" . "meta.sr.ht/PROFILE:RO")
+       ;; The client secret, which will be generated as part of client
+       ;; registration, at
+       ;; "https://meta.sr.ht/oauth2/client-registration";.  If the user
+       ;; generates the client secret, they should note it down.  If the
+       ;; Emacs library developer generates it, they should make it
+       ;; available to the users of their library somehow.  In either
+       ;; case, Emacs will prompt for it, and store it, ideally
+       ;; GPG-encrypted, using `auth-source'.  An example client secret
+       ;; string is "CeuivTBzZbqJ4iTc+VEdPZJODkBHhuCj4bIqQQAONYaOUGubNM0yG
+       ;; ZU3P7ant959W1RkzgvXSeNf2mdxuk5EfA==".  The user would paste this
+       ;; 88 character client secret string into the minibuffer when
+       ;; prompted.
+       ("client-secret-method" . prompt))))
+  (let ((url-request-method "POST")
+        (url-request-extra-headers
+         (list (cons "Content-Type" "application/json")))
+        (url-request-data
+         "{\"query\": \"{ me { canonicalName } }\"}"))
+    (with-current-buffer
+        (url-retrieve-synchronously
+         (url-parse-make-urlobj
+          "https"      ; type
+          nil          ; user
+          nil          ; password, resolved by url-http-oauth
+          "meta.sr.ht" ; host
+          443          ; port
+          "/query"     ; path
+          nil nil t))
+      (goto-char (point-min))
+      (re-search-forward "\n\n")
+      (message "%s" (buffer-substring (point) (point-max)))
+      (gethash
+       "canonicalName"
+       (gethash
+        "me"
+        (gethash
+         "data"
+         (json-parse-buffer)))))))
+
+(provide 'url-http-oauth-demo)
+
+;;; url-http-oauth-demo.el ends here
diff --git a/url-http-oauth.el b/url-http-oauth.el
index 09d503f5b4..4cda772146 100644
--- a/url-http-oauth.el
+++ b/url-http-oauth.el
@@ -29,7 +29,8 @@
 ;;
 ;; Usage:
 ;;
-;; See url-http-oauth-demo.el.
+;; See url-http-oauth-demo.el, which is installed alongside
+;; url-http-oauth.el.
 
 ;;; Code:
 (require 'url-auth)

Reply via email to