-
Notifications
You must be signed in to change notification settings - Fork 0
journal 2020 09 08: A "bug" in `oauthenticated`
I was moving along, super slowly but super surely, to make an OAuth-signed request to Twitter. The example endpoint I chose was
However after a lot of failed attempts and lots of print debugging, I realised that the oauthenticated
library was for some reason not outputting the access token in the oauth_token
component of the Authorization
header of my intended signed request. This component is supposed to hold the access token, as discussed in Twitter's guiding documentation. It also makes sense from an OAuth conceptual point-of-view: you can't just omit a part of the signature base string and still hope the signature checks out.
Since my request is missing that OAuth param, of course it isn't going to work --- but how come?? Haskell libraries are almost never broken like this, so I was almost immediately furious...
... until I found this oauthParams
function in oauthenticated
source code that has a comment that exactly addresses my question:
oauthParams :: Oa ty -> Server -> H.Query
oauthParams (Oa {..}) (Server {..}) =
let
OaPin {..} = pin
infix 8 -:
s -: v = (s, H.toQueryValue v)
-- **NOTE** dfithian: It worked for my use case to move oauth_token into these params. From the
-- PR:
--
-- I presume one very controversial thing I did was to move `oauth_token` into `workflowParams`.
-- I came to this conclusion by skimming through the [RFC](https://tools.ietf.org/html/rfc5849)
-- and deciding that since I only ever saw `oauth_token` in conjunction with either
-- `oauth_callback` or `oauth_verifier` that they should go together. I'd be perfectly happy to
-- instead pass in some function of the settings telling it whether or not to include
-- `oauth_token` for a given request. Whatever the conclusion, the service I'm integrating to
-- specifically does NOT want the `oauth_token` so that was the motivation.
workflowParams Standard = []
workflowParams (TemporaryTokenRequest callback) =
[ "oauth_callback" -: callback
, "oauth_token" -: (getResourceTokenDef credentials ^. key) ]
workflowParams (PermanentTokenRequest verifier) =
[ "oauth_verifier" -: verifier
, "oauth_token" -: (getResourceTokenDef credentials ^. key) ]
in
[ "oauth_version" -: oAuthVersion
, "oauth_consumer_key" -: (credentials ^. clientToken . key)
, "oauth_signature_method" -: signatureMethod
, "oauth_timestamp" -: timestamp
, "oauth_nonce" -: nonce
] ++ workflowParams workflow
Oh well! Let's say, I definitely laughed to myself at the tacit understanding with another Haskell developer I've never met.
Looks like I'll have to copy-paste patch it in order to get it to do what I want.
Update: I found a hack, and it worked first-time. LOL!
diff --git a/src/TwitAnalysis/TwitterApiCallDemo.hs b/src/TwitAnalysis/TwitterApiCallDemo.hs
index 3e6a27c..4e12137 100644
--- a/src/TwitAnalysis/TwitterApiCallDemo.hs
+++ b/src/TwitAnalysis/TwitterApiCallDemo.hs
@@ -55,7 +55,16 @@ fetchCurrentUser Env {envHttpMan} cred srv = do
, ("include_email", Just "false")
]
initReq
- signedReq <- OAuthSigning.oauth cred srv unsignedReq
+ oax <- OAuthParams.freshOa cred
+ -- Hack around a difference-in-understanding compared to the author of oauthenticated.
+ -- The `oauth_token` component would be omitted from the `Authorization` header otherwise.
+ -- See journal for back-story:
+ -- - https://github.com/easoncxz/twitanalysis/wiki/journal-2020-09-08:-A-%22bug%22-in-%60oauthenticated%60
+ let hackedOax :: OAuthParams.Oa Permanent
+ hackedOax =
+ oax {OAuthParams.workflow = OAuthParams.PermanentTokenRequest "bogus"}
+ putStrLn $ "Here are the generated OAuth params: " ++ show hackedOax
+ let signedReq = OAuthSigning.sign hackedOax srv unsignedReq
putStrLn $ "About to make this request: " ++ show signedReq
let headers = (HC.requestHeaders signedReq)
putStrLn $ "In particular, the headers are: " ++ show headers
And voilà, my Twitter user, presented in pretty-printed JSON as a <pre>
element: