diff options
author | Yuchen Pei <id@ypei.org> | 2024-12-26 10:53:30 +1100 |
---|---|---|
committer | Yuchen Pei <id@ypei.org> | 2024-12-26 10:53:30 +1100 |
commit | 9e59bd0e850a6042093a9f3fd8341d73d44578ef (patch) | |
tree | 7b4e01e3ec459bc0b47235c8002d83afd7eea1a9 | |
parent | fffd9a8326a7b676338c339e04aaba15c7da72b3 (diff) |
Adding a "test" for request signing
The test is the example from twitter developer document.
Also adding references to the document about various steps.
-rw-r--r-- | exitter.el | 68 |
1 files changed, 52 insertions, 16 deletions
@@ -105,6 +105,8 @@ (setq request-message-level 'blather) (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 () (let ((oauth-consumer-key-secret (base64-encode-string @@ -128,6 +130,13 @@ (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 () (when exitter-debug (message "entering exitter-get-guest-token")) (request exitter-url-activate @@ -299,12 +308,36 @@ (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_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"))) (all-params (sort (seq-concatenate 'list url-params oauth-params) (lambda (a b) (string< (car a) (car b))))) @@ -327,18 +360,19 @@ "\\+" "%20" param-to-sign-unencoded))))) (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 - (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" signature (mapconcat @@ -403,6 +437,7 @@ ONEPLUS A3010 Build/PKQ1.181203.001)") `(("variables" . ,variables) ("features" . ,exitter-default-features))))) +;;; utilities (require 'bindat) (defun exitter-nonce () @@ -417,7 +452,8 @@ ONEPLUS A3010 Build/PKQ1.181203.001)") (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. KEY and MESSAGE must be unibyte strings. The result is a unibyte |