Skip to content

Commit

Permalink
support for plain text
Browse files Browse the repository at this point in the history
linked request_token into app.
One error failing todo with encoding/decoding of hmac-sha1 signatures
  • Loading branch information
pelle committed Mar 17, 2010
1 parent 5d4db94 commit 295f633
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 33 deletions.
6 changes: 3 additions & 3 deletions src/oauth/client.clj
Expand Up @@ -42,7 +42,7 @@
"Fetch request token for the consumer."
[consumer]
(let [unsigned-params (sig/oauth-params consumer)
params (assoc unsigned-params :oauth_signature (sig/sign consumer
params (assoc unsigned-params :oauth_signature (sig/sign (consumer :digest-method) consumer
(sig/base-string "POST"
(:request-uri consumer)
unsigned-params)))]
Expand Down Expand Up @@ -78,7 +78,7 @@ to approve the Consumer's access to their account."
([consumer request-token verifier]
(let [unsigned-params (sig/oauth-params consumer request-token verifier)
params (assoc unsigned-params
:oauth_signature (sig/sign consumer
:oauth_signature (sig/sign (consumer :digest-method) consumer
(sig/base-string "POST"
(:access-uri consumer)
unsigned-params)))]
Expand All @@ -96,7 +96,7 @@ Authorization HTTP header or added as query parameters to the request."
(let [unsigned-oauth-params (sig/oauth-params consumer token)
unsigned-params (merge request-params
unsigned-oauth-params)]
(assoc unsigned-oauth-params :oauth_signature (sig/sign consumer
(assoc unsigned-oauth-params :oauth_signature (sig/sign (consumer :digest-method) consumer
(sig/base-string (-> request-method
as-str
upper-case)
Expand Down
20 changes: 13 additions & 7 deletions src/oauth/server.clj
Expand Up @@ -61,17 +61,23 @@
[handler store]
(fn [request]
(let
[op (oauth-params request)]
[op (oauth-params request)
;; _ (println op)
]
(if (not (empty? op))
(let
[oauth-consumer (store/get-consumer store (op :oauth_consumer_key))
oauth-token (store/get-access-token store (op :oauth_token))]
(if (sig/verify
(op :oauth_signature)
{:secret (and oauth-consumer (oauth-consumer :secret)) :signature-method :hmac-sha1}
(sig/url-decode (op :oauth_signature))
(keyword (.toLowerCase (op :oauth_signature_method)))
oauth-consumer
(request-base-string request)
(and oauth-token (oauth-token :secret)))
(handler (assoc request :oauth-consumer oauth-consumer :oauth-token oauth-token :oauth-params op))
(if (nil? oauth-token)
(handler (assoc request :oauth-consumer oauth-consumer :oauth-params op))
(handler (assoc request :oauth-consumer oauth-consumer :oauth-token oauth-token :oauth-params op))
)
(handler request)
)
)
Expand Down Expand Up @@ -127,12 +133,12 @@
/oauth/access_token
/oauth/authorize
"
[handler]
[handler store]
(fn [request]
(condp = (:uri request)
"/oauth/request_token"
(request-token request)
(request-token store request)
"/oauth/access_token"
(access-token request)
(access-token store request)
(handler request)))
)
23 changes: 15 additions & 8 deletions src/oauth/signature.clj
Expand Up @@ -20,7 +20,8 @@
[length]
(. (new BigInteger (* 5 length) secure-random) toString 32))

(def signature-methods {:hmac-sha1 "HMAC-SHA1"})
(def signature-methods {:hmac-sha1 "HMAC-SHA1"
:plaintext "PLAINTEXT"})

(defn url-form-encode [params]
(str-join "&" (map (fn [[k v]]
Expand All @@ -30,7 +31,7 @@
([method base-url c t params]
(base-string method base-url (assoc params :oauth_consumer_key (:key c)
:oauth_token (:token t)
:oauth_signature_method (signature-methods (:signature-method c))
:oauth_signature_method (or (params :oauth_signature_method) (signature-methods (:signature-method c)))
:oauth_version "1.0"
))
)
Expand All @@ -41,22 +42,28 @@

(defmulti sign
"Sign a base string for authentication."
(fn [c & r] (:signature-method c)))
(fn [c & r] c))

(defmethod sign :hmac-sha1
[c base-string & [token-secret]]
(let [key (str (:secret c) "&" (or token-secret ""))]
[ _ c base-string & [token-secret]]
(let [key (str (url-encode (:secret c)) "&" (url-encode (or token-secret "")))]
(digest/hmac key base-string)))

(defn verify [sig c base-string & [token-secret]]
(= sig (sign c base-string token-secret))
(defmethod sign :plaintext
[ _ c base-string & [token-secret]]
(str (url-encode (c :secret)) "&" (url-encode token-secret)))

(defn verify [sig digest-method c base-string & [token-secret]]
(do
(println sig (sign digest-method c base-string token-secret))
(= sig (sign digest-method c base-string token-secret)))
)

(defn url-encode
"The java.net.URLEncoder class encodes for application/x-www-form-urlencoded, but OAuth
requires RFC 3986 encoding."
[s]
(-> (java.net.URLEncoder/encode s "UTF-8")
(-> (java.net.URLEncoder/encode (str s) "UTF-8")
(.replace "+" "%20")
(.replace "*" "%2A")
(.replace "%7E" "~")))
Expand Down
2 changes: 1 addition & 1 deletion test/oauth/client_test.clj
Expand Up @@ -12,7 +12,7 @@
nil
nil
:hmac-sha1)]
(is (= (sig/sign c (sig/base-string "GET"
(is (= (sig/sign :hmac-sha1 c (sig/base-string "GET"
"http://photos.example.net/photos"
{:oauth_consumer_key "dpf43f3p2l4k3l03"
:oauth_token "nnch734d00sl2jdk"
Expand Down
69 changes: 59 additions & 10 deletions test/oauth/server_test.clj
Expand Up @@ -81,7 +81,7 @@
)))

(defn app [req]
(if (req :oauth-token)
(if (or (req :oauth-token)(req :oauth-consumer))
{
:status 200
:request req
Expand All @@ -93,15 +93,7 @@
:body ""
}))

(defn token-finder [consumer token]
["kd94hf93k423kf44" "pfkkdhi9sl3r4s00"])
;; (if (and (= consumer "0685bd9184jfhq22") (= token "ad180jjd733klru7"))
;; ["kd94hf93k423kf44" "pfkkdhi9sl3r4s00"] nil
;; ))
(defn store-token-finder [store]
(fn [consumer token]
)
)

(deftest
#^{:doc "wrap oauth"}
wrap-oauth
Expand All @@ -112,13 +104,33 @@
(is (= 401 ((oauth-app {:headers { :authorize "Basic realm=\"Secure Area\""}}) :status)))
(is (= 401 ((oauth-app {:headers { :authorize "OAuth realm=\"http://sp.example.com/\", oauth_consumer_key=\"0685bd9184jfhq22\", oauth_token=\"ad180jjd733klru7\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"fake\", oauth_timestamp=\"137131200\", oauth_nonce=\"4572616e48616d6d65724c61686176\",oauth_version=\"1.0\""}}) :status)))

;; 3 legged HMAC-SHA1
(is (= 200 ((oauth-app {
:request-method :get
:server-name "photos.example.net"
:uri "/photos"
:scheme :http
:params {:file "vacation.jpg" :size "original"}
:headers { :authorize "OAuth realm=\"http://sp.example.com/\", oauth_consumer_key=\"dpf43f3p2l4k3l03\", oauth_token=\"nnch734d00sl2jdk\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"tR3%2BTy81lMeYAr%2FFid0kMTYa%2FWM%3D\", oauth_timestamp=\"1191242096\", oauth_nonce=\"kllo9940pd9333jh\",oauth_version=\"1.0\""}}) :status)))

;; 3 legged PLAINTEXT
(is (= 200 ((oauth-app {
:request-method :get
:server-name "photos.example.net"
:uri "/photos"
:scheme :http
:params {:file "vacation.jpg" :size "original"}
:headers { :authorize "OAuth realm=\"http://sp.example.com/\", oauth_consumer_key=\"dpf43f3p2l4k3l03\", oauth_token=\"nnch734d00sl2jdk\", oauth_signature_method=\"PLAINTEXT\", oauth_signature=\"kd94hf93k423kf44%26pfkkdhi9sl3r4s00\", oauth_timestamp=\"1191242096\", oauth_nonce=\"kllo9940pd9333jh\",oauth_version=\"1.0\""}}) :status)))

;; 2 legged PLAINTEXT
(is (= 200 ((oauth-app {
:request-method :get
:server-name "photos.example.net"
:uri "/photos"
:scheme :http
:params {:file "vacation.jpg" :size "original"}
:headers { :authorize "OAuth realm=\"http://sp.example.com/\", oauth_consumer_key=\"dpf43f3p2l4k3l03\", oauth_signature_method=\"PLAINTEXT\", oauth_signature=\"kd94hf93k423kf44%26\", oauth_timestamp=\"1191242096\", oauth_nonce=\"kllo9940pd9333jh\",oauth_version=\"1.0\""}}) :status)))

))

(deftest
Expand Down Expand Up @@ -147,6 +159,43 @@
)
))
)

;;
(deftest
#^{:doc "integrated token request in app using example from http://oauth.net/core/1.0a/#anchor43"}
integrated-token-request
(let [oauth-app (os/wrap-oauth (os/oauth-token-manager app :memory ) :memory)
_ (store/store-consumer :memory {:key "dpf43f3p2l4k3l03" :secret "kd94hf93k423kf44"})]
(is (= 401 ((oauth-app {}) :status)))
(is (= 401 ((oauth-app {:headers { :authorize "Basic realm=\"Secure Area\""}}) :status)))
(is (= 401 ((oauth-app {:headers { :authorize "OAuth realm=\"https://photos.example.net/\", oauth_consumer_key=\"dpf43f3p2l4k3l03\", oauth_signature_method=\"HMAC-SHA1\", oauth_signature=\"fake\", oauth_timestamp=\"1191242090\", oauth_nonce=\"hsu94j3884jdopsl\", oauth_version=\"1.0\", oauth_callback=\"http%3A%2F%2Fprinter.example.com%2Frequest_token_ready\""}}) :status)))

(let [ response (oauth-app {
:request-method :post
:server-name "photos.example.net"
:uri "/oauth/request_token"
:scheme :https
:headers { :authorize "OAuth realm=\"https://photos.example.net/\", oauth_consumer_key=\"dpf43f3p2l4k3l03\", oauth_signature_method=\"PLAINTEXT\", oauth_signature=\"kd94hf93k423kf44%26\", oauth_timestamp=\"1191242090\", oauth_nonce=\"hsu94j3884jdopsl\", oauth_callback=\"http://printer.example.com/request_token_ready\" oauth_version=\"1.0\""}})
token-body (response :body)
_ (println token-body)
token-params (os/parse-form-encoded (response :body))]
(is(= 200 (response :status)))
(is (not (nil? token-body)))
(is (not (nil? token-params)))
(is (not (nil? (token-params :oauth_token))))
(is (not (nil? (token-params :oauth_secret))))
(is (= (token-params :oauth_callback_confirmed) "true"))
(is (nil? (token-params :oauth_verifier)))
(let [token (store/get-request-token :memory (token-params :oauth_token))]
(is (not (nil? token)))
(is (= (token :token) (token-params :oauth_token)))
(is (= (token :secret) (token-params :oauth_secret)))
(is (= (token :consumer) (store/get-consumer :memory "dpf43f3p2l4k3l03")))
(is (not (nil? (token :verifier))))
))

))


(deftest
#^{:doc "access token request"}
Expand Down
44 changes: 40 additions & 4 deletions test/oauth/signature_test.clj
Expand Up @@ -43,13 +43,13 @@
))

(deftest
#^{:doc "Test signing of a request."}
signature
#^{:doc "Test hmac-sha1 signing of a request."}
hmac-sha1-signature
(let [c { :key "dpf43f3p2l4k3l03"
:secret "kd94hf93k423kf44"
:signature-method :hmac-sha1}]

(is (= (sig/sign c (sig/base-string "GET"
(is (= (sig/sign :hmac-sha1 c (sig/base-string "GET"
"http://photos.example.net/photos"
{:oauth_consumer_key "dpf43f3p2l4k3l03"
:oauth_token "nnch734d00sl2jdk"
Expand All @@ -62,14 +62,42 @@
"pfkkdhi9sl3r4s00")
"tR3+Ty81lMeYAr/Fid0kMTYa/WM="))))

(deftest
#^{:doc "test plaintext signatures"}
plaintext-signature
(let [c { :key "dpf43f3p2l4k3l03"
:secret "kd94hf93k423kf44"
:signature-method :hmac-sha1}] ; I'm intentionally testing with this as sha1

(is (= "kd94hf93k423kf44&" (sig/sign :plaintext c (sig/base-string "POST"
"https://photos.example.net/request_token"
{:oauth_consumer_key "dpf43f3p2l4k3l03"
:oauth_signature_method "PLAINTEXT"
:oauth_timestamp "1191242090"
:oauth_nonce "hsu94j3884jdopsl"
:oauth_version "1.0"}))
))
(is (= "kd94hf93k423kf44&hdhd0244k9j7ao03" (sig/sign :plaintext c (sig/base-string "POST"
"https://photos.example.net/access_token"
{:oauth_consumer_key "dpf43f3p2l4k3l03"
:oauth_signature_method "PLAINTEXT"
:oauth_timestamp "1191242090"
:oauth_token "hh5s93j4hdidpola"
:oauth_nonce "hsu94j3884jdopsl"
:oauth_verifier "hfdp7dh39dks9884"
:oauth_version "1.0"})
"hdhd0244k9j7ao03")
))

))
(deftest
#^{:doc "Test verification of signed request."}
verify
(let [c { :key "dpf43f3p2l4k3l03"
:secret "kd94hf93k423kf44"
:signature-method :hmac-sha1}]

(is (sig/verify "tR3+Ty81lMeYAr/Fid0kMTYa/WM=" c (sig/base-string "GET"
(is (sig/verify "tR3+Ty81lMeYAr/Fid0kMTYa/WM=" :hmac-sha1 c (sig/base-string "GET"
"http://photos.example.net/photos"
{:oauth_consumer_key "dpf43f3p2l4k3l03"
:oauth_token "nnch734d00sl2jdk"
Expand All @@ -81,6 +109,14 @@
:size "original"})
"pfkkdhi9sl3r4s00")
)
(is (sig/verify "kd94hf93k423kf44&" :plaintext c (sig/base-string "POST"
"https://photos.example.net/request_token"
{:oauth_consumer_key "dpf43f3p2l4k3l03"
:oauth_signature_method "PLAINTEXT"
:oauth_timestamp "1191242090"
:oauth_nonce "hsu94j3884jdopsl"
:oauth_version "1.0"}))
)
))


Expand Down

0 comments on commit 295f633

Please sign in to comment.