Explorar o código

Adding a "test" for request signing

The test is the example from twitter developer document.

Also adding references to the document about various steps.
Yuchen Pei hai 11 meses
pai
achega
9e59bd0e85
Modificáronse 1 ficheiros con 52 adicións e 16 borrados
  1. 52 16
      exitter.el

+ 52 - 16
exitter.el

@@ -105,6 +105,8 @@
     (setq request-message-level 'blather)
     (setq request-message-level 'blather)
   (setq request-message-level -1))
   (setq request-message-level -1))
 
 
+;;; Get an oauth2 bearer token
+;;; https://developer.x.com/en/docs/authentication/api-reference/token
 (defun exitter-get-access-token ()
 (defun exitter-get-access-token ()
   (let ((oauth-consumer-key-secret
   (let ((oauth-consumer-key-secret
          (base64-encode-string
          (base64-encode-string
@@ -128,6 +130,13 @@
                      (message "Got error: %S" error-thrown)))
                      (message "Got error: %S" error-thrown)))
       )))
       )))
 
 
+;;; Use the twitter frontend flow and the oauth2 bearer token to
+;;; obtain a user oauth token aka user access token.
+
+;;; The official way of doing so is by oauth 1.0a documented at
+;;; https://developer.x.com/en/docs/authentication/oauth-1-0a, but
+;;; here we use the twitter frontend flow, similar to how one logs in
+;;; the twitter web client
 (defun exitter-get-guest-token ()
 (defun exitter-get-guest-token ()
   (when exitter-debug (message "entering exitter-get-guest-token"))
   (when exitter-debug (message "entering exitter-get-guest-token"))
   (request exitter-url-activate
   (request exitter-url-activate
@@ -299,12 +308,36 @@
                    (message "Got error: %S" error-thrown)))
                    (message "Got error: %S" error-thrown)))
     ))
     ))
 
 
-(defun exitter-get-sign-oauth (link url-params method)
-  (let* ((oauth-params `(("oauth_consumer_key" . ,exitter-oauth-consumer-key)
-                         ("oauth_nonce" . ,(exitter-nonce))
+;;; Example at
+;;; https://developer.x.com/en/docs/authentication/oauth-1-0a/creating-a-signature
+;;; should produce signature "Ls93hJiZbQ3akF3HF3x1Bz8%2FzU4%3D"
+(defun exitter-example-sign-oauth ()
+  (exitter-get-sign-oauth
+   "https://api.x.com/1.1/statuses/update.json" ;link
+   '(("status" . "Hello Ladies + Gentlemen, a signed OAuth request!")
+     ("include_entities" .	"true"))             ;url-params
+   "POST"                                        ;method
+   "xvz1evFS4wEEPTGEFPHBog"                      ;oauth-consumer-key
+   "kAcSOqF21Fu85e7zjz7ZN2U4ZRhfV3WpwPAoE3Z7kBw" ;oauth-consumer-secret
+   "370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb" ;oauth-token
+   "LswwdoUaIvS8ltyTt5jkRh4J50vUPVVHtR2YPi5kE"  ;oauth-token-secret
+   "kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg" ;oauth-nonce
+   "1318622958"                                 ;oauth-timestamp
+   ))
+
+;;; see
+;;; https://developer.x.com/en/docs/authentication/oauth-1-0a/creating-a-signature
+;;; https://developer.x.com/en/docs/authentication/oauth-1-0a/authorizing-a-request
+(defun exitter-get-sign-oauth (link url-params method &optional
+                                    oauth-consumer-key oauth-consumer-secret
+                                    oauth-token oauth-token-secret
+                                    oauth-nonce oauth-timestamp)
+  (let* ((oauth-params `(("oauth_consumer_key" .
+                          ,(or oauth-consumer-key exitter-oauth-consumer-key))
+                         ("oauth_nonce" . ,(or oauth-nonce (exitter-nonce)))
                          ("oauth_signature_method" . "HMAC-SHA1")
                          ("oauth_signature_method" . "HMAC-SHA1")
-                         ("oauth_timestamp" . ,(format-time-string "%s" (current-time)))
-                         ("oauth_token" . ,exitter-oauth-token)
+                         ("oauth_timestamp" . ,(or oauth-timestamp (format-time-string "%s" (current-time))))
+                         ("oauth_token" . ,(or oauth-token exitter-oauth-token))
                          ("oauth_version" . "1.0")))
                          ("oauth_version" . "1.0")))
          (all-params (sort (seq-concatenate 'list url-params oauth-params)
          (all-params (sort (seq-concatenate 'list url-params oauth-params)
                            (lambda (a b) (string< (car a) (car b)))))
                            (lambda (a b) (string< (car a) (car b)))))
@@ -327,18 +360,19 @@
               "\\+" "%20"
               "\\+" "%20"
               param-to-sign-unencoded)))))
               param-to-sign-unencoded)))))
          (to-sign (format "%s&%s&%s" method-up hexed-link param-to-sign))
          (to-sign (format "%s&%s&%s" method-up hexed-link param-to-sign))
+         (signing-key (format "%s&%s"
+                              (or oauth-consumer-secret
+                                  exitter-oauth-consumer-secret)
+                              (or oauth-token-secret
+                                  exitter-oauth-token-secret)))
          (signature (url-hexify-string
          (signature (url-hexify-string
-                     (base64-encode-string
-                      (hmac-sha1 (encode-coding-string
-                                  (format "%s&%s"
-                                          exitter-oauth-consumer-secret
-                                          exitter-oauth-token-secret)
-                                  'utf-8)
-                                 (encode-coding-string to-sign 'utf-8)))))
+                     (print (base64-encode-string
+                             (exitter-hmac-sha1 (encode-coding-string signing-key 'utf-8)
+                                                (encode-coding-string to-sign 'utf-8))))))
          )
          )
-    (message "PARAM-TO-SIGN-UNENC: %s" (prin1-to-string param-to-sign-unencoded))
-    (message "PARAM-TO-SIGN: %s" (prin1-to-string param-to-sign))
-    (message "TO-SIGN: %s" (prin1-to-string to-sign))
+    ;; (message "PARAM-TO-SIGN-UNENC: %s" (prin1-to-string param-to-sign-unencoded))
+    ;; (message "PARAM-TO-SIGN: %s" (prin1-to-string param-to-sign))
+    ;; (message "TO-SIGN: %s" (prin1-to-string to-sign))
     (format "OAuth realm=\"http://api.twitter.com/\", oauth_signature=\"%s\", %s"
     (format "OAuth realm=\"http://api.twitter.com/\", oauth_signature=\"%s\", %s"
             signature
             signature
             (mapconcat
             (mapconcat
@@ -403,6 +437,7 @@ ONEPLUS A3010 Build/PKQ1.181203.001)")
      `(("variables" . ,variables)
      `(("variables" . ,variables)
        ("features" . ,exitter-default-features)))))
        ("features" . ,exitter-default-features)))))
 
 
+;;; utilities
 (require 'bindat)
 (require 'bindat)
 
 
 (defun exitter-nonce ()
 (defun exitter-nonce ()
@@ -417,7 +452,8 @@ ONEPLUS A3010 Build/PKQ1.181203.001)")
 
 
 (require 'sha1)
 (require 'sha1)
 
 
-(defun hmac-sha1 (key message)
+;;; Source: https://www.emacswiki.org/emacs/HmacShaOne
+(defun exitter-hmac-sha1 (key message)
   "Return an HMAC-SHA1 authentication code for KEY and MESSAGE.
   "Return an HMAC-SHA1 authentication code for KEY and MESSAGE.
 
 
 KEY and MESSAGE must be unibyte strings.  The result is a unibyte
 KEY and MESSAGE must be unibyte strings.  The result is a unibyte