How to configure OAuth with Goodreads in Clojure

眉间皱痕 提交于 2019-12-23 05:07:57

问题


I am trying to configure OAuth to use it to access data from the Goodreads API using Clojure and Compojure framework. I basically want to get a list of firends that a Goodreads member has. I should mention that I am new to Clojure and completely new to OAuth and in general to API authentication so I would really appreciate it if it could be explained as simply as possible.

I tried to find the answer online but was unable to find one that would help me as many sites deal with specific OAuth API configurations and those seem to differ widely from API to API in terms of configuring access with OAuth. Furthermore not many of them use Clojure to explain OAuth API configuration and those that do differ too much in terms of what is required for that specific API access. The Goodreads API page was not really helpful either. Finally I found the answer to this question and tried to use it as a template to configure my OAuth access to the Goodreads API. It uses the clj-oauth which I tried to use in combination with the answer to the above mentioned question since simply replacing the data from the answer to that question with Goodreads addresses didn't work. This is what I have now but it just returns a 401 error and I have no idea what I am doing wrong:

(def okey "goodreads-key")

(def osecret "goodreads-secret")

(def consumer (oauth/make-consumer okey
                                   osecret
                                   "http://www.goodreads.com/oauth/request_token"
                                   "http://www.goodreads.com/oauth/access_token"
                                   "http://www.goodreads.com/oauth/authorize"
                                   :hmac-sha1))

(def request-token (oauth/request-token consumer nil))

(oauth/user-approval-uri consumer 
                         (:oauth_token request-token))

(def access-token-response (oauth/access-token consumer 
                                               request-token
                                               nil))

(defn test-get []
  (let [credentials (oauth/credentials consumer
                                       (:oauth_token access-token-response)
                                       (:oauth_token_secret access-token-response)
                                       :GET
                                       "https://www.goodreads.com/friend/user/user-id-number?format=xml")]
    (http/get "https://www.goodreads.com/friend/user/user-id-number?format=xml" {:query-params credentials})))

The clj-oauth says in the Client Example that there should be a callback-uri in the request-token and a verifier in the access-token-response, but since I am not familiar with OAuth I put nil there.

The answer to the above question doesn't use the following lines from my code:

(def request-token (oauth/request-token consumer nil))

(oauth/user-approval-uri consumer 
                         (:oauth_token request-token))

(def access-token-response (oauth/access-token consumer 
                                               request-token
                                               nil))

And subsequently doesn't use the "http://www.goodreads.com/oauth/request_token" "http://www.goodreads.com/oauth/access_token" "http://www.goodreads.com/oauth/authorize" addresses in the consumer nor does it use (:oauth_token access-token-response) (:oauth_token_secret access-token-response) in test-get, but instead replaces those values with nil, but since it didn't work I tried to combine it with the example mentioned on clj-oauth github page mentioned above, but it still doesn't work.

I am simply trying to get a XML response of a member's list of friends from the Goodreads API and any help configuring this would be much appreciated.


回答1:


so my project.clj looks like this:

:dependencies [[org.clojure/clojure "1.6.0"]
                 [clj-oauth "1.5.2"]
                 [clj-http "1.1.2"]]

Sample code:

(ns scratch.core
  (:require [oauth.client :as oauth]
            [clj-http.client :as http]))

(def consumer-key "your_key")
(def consumer-secret "your_secret")

;Step 1: Create an oath consumer object
(def consumer (oauth/make-consumer consumer-key
                                   consumer-secret
                                   "https://www.goodreads.com/oauth/request_token"
                                   "https://www.goodreads.com/oauth/access_token"
                                   "https://www.goodreads.com/oauth/authorize"
                                   :hmac-sha1))
;Step 2: Create a request token.  These can only be used once.  They usually expire as well.
(def request-token (oauth/request-token consumer nil))

;Step 3:  Have the goodreads user approve your application.  They can approve your application by visting the url
; produced by the call below.
(oauth/user-approval-uri consumer
                         (:oauth_token request-token))

;Step 4:  Once the goodreads user has approved your application, you can exchange the request token for an access token.
;An access token is per-user.  Goodreads in particular will only issue 1 per user, so don not lose this access token.
(def access-token-response (oauth/access-token consumer
                                               request-token
                                               nil))

;Step 5: Get the user id of the user who approved your application.
;you can parse the user id out from this.  I used clojure.zip, clojure.data.zip.xml, and clojure.data.xml to parse this out.
(defn get-user-id []
  (let [url "https://www.goodreads.com/api/auth_user"
        credentials (oauth/credentials consumer
                                       (:oauth_token access-token-response)
                                       (:oauth_token_secret access-token-response)
                                       :GET
                                       url)]
    (http/get url {:query-params credentials})))

(get-user-id)

;Step 6: Get the friends of the user.
(defn get-friends [user-id]
  (let [url (str "https://www.goodreads.com/friend/user/" user-id)
        params {:format "xml"}
        credentials (oauth/credentials consumer
                                       (:oauth_token access-token-response)
                                       (:oauth_token_secret access-token-response)
                                       :GET
                                       url
                                       params)]
    (http/get url {:query-params (merge credentials params)})))

(get-friends <a user id>)

EDIT:

Ok I reran the exact code above (redacted api keys and user id) and am 100% sure it works. I would highly recommend creating a throwaway Goodreads account to test with.

Here is a screenshot of a successful request



来源:https://stackoverflow.com/questions/32920728/how-to-configure-oauth-with-goodreads-in-clojure

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!