From 08d5180fe18002670e5317426cc0282ed7352391 Mon Sep 17 00:00:00 2001 From: Sam Bauch Date: Wed, 10 Feb 2021 15:05:19 -0500 Subject: [PATCH 1/5] Pass params submitted to launch-uri to authorization-uri Some OAuth providers support extra query params that aren't appropriate for hardcoding. One example is Google OAuth, which accepts an `hd` param to the authorization URL that can restrict logins to users with the provided email domain. This commit allows a developer to submit a request to the launch-uri with parameters. These parameters will now be passed along to the authorization URI as the user is sent to the OAuth provider to authenticate. Also adds a test for this functionality. https://github.com/weavejester/ring-oauth2/issues/41 --- src/ring/middleware/oauth2.clj | 22 +++++++++++++--------- test/ring/middleware/oauth2_test.clj | 9 +++++++++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/ring/middleware/oauth2.clj b/src/ring/middleware/oauth2.clj index 1cfe870..ba4060c 100644 --- a/src/ring/middleware/oauth2.clj +++ b/src/ring/middleware/oauth2.clj @@ -3,6 +3,7 @@ [clj-time.core :as time] [clojure.string :as str] [crypto.random :as random] + [ring.middleware.params :refer [wrap-params]] [ring.util.codec :as codec] [ring.util.request :as req] [ring.util.response :as resp])) @@ -19,20 +20,23 @@ (defn- authorize-uri [profile request state] (str (:authorize-uri profile) (if (.contains ^String (:authorize-uri profile) "?") "&" "?") - (codec/form-encode {:response_type "code" - :client_id (:client-id profile) - :redirect_uri (redirect-uri profile request) - :scope (scopes profile) - :state state}))) + (codec/form-encode + (merge (:query-params request) + {:response_type "code" + :client_id (:client-id profile) + :redirect_uri (redirect-uri profile request) + :scope (scopes profile) + :state state })))) (defn- random-state [] (-> (random/base64 9) (str/replace "+" "-") (str/replace "/" "_"))) (defn- make-launch-handler [profile] - (fn [{:keys [session] :or {session {}} :as request}] - (let [state (random-state)] - (-> (resp/redirect (authorize-uri profile request state)) - (assoc :session (assoc session ::state state)))))) + (wrap-params + (fn [{:keys [session] :or {session {}} :as request}] + (let [state (random-state)] + (-> (resp/redirect (authorize-uri profile request state)) + (assoc :session (assoc session ::state state))))))) (defn- state-matches? [request] (= (get-in request [:session ::state]) diff --git a/test/ring/middleware/oauth2_test.clj b/test/ring/middleware/oauth2_test.clj index 033cb87..d228d02 100644 --- a/test/ring/middleware/oauth2_test.clj +++ b/test/ring/middleware/oauth2_test.clj @@ -56,6 +56,15 @@ location (get-in response [:headers "Location"])] (is (.startsWith ^String location "https://example.com/oauth2/authorize?business_partner_id=XXXX&")))) +(deftest test-location-uri-with-dynamic-query + (let [profile test-profile + handler (wrap-oauth2 token-handler {:test profile}) + response (handler (-> (mock/request :post "/oauth2/test?hd=tenant.com" {:hd "tenant.com"}) + (mock/content-type "application/x-www-form-urlencoded"))) + location (get-in response [:headers "Location"])] + (print ^String location) + (is (.startsWith ^String location "https://example.com/oauth2/authorize?hd=tenant.com&")))) + (def token-response {:status 200 :headers {"Content-Type" "application/json"} From c7379b401e7bf97d794152ddb865c8cb92390bad Mon Sep 17 00:00:00 2001 From: Sam Bauch Date: Wed, 10 Feb 2021 15:34:35 -0500 Subject: [PATCH 2/5] test cleanup from self review --- test/ring/middleware/oauth2_test.clj | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/ring/middleware/oauth2_test.clj b/test/ring/middleware/oauth2_test.clj index d228d02..db50782 100644 --- a/test/ring/middleware/oauth2_test.clj +++ b/test/ring/middleware/oauth2_test.clj @@ -59,11 +59,9 @@ (deftest test-location-uri-with-dynamic-query (let [profile test-profile handler (wrap-oauth2 token-handler {:test profile}) - response (handler (-> (mock/request :post "/oauth2/test?hd=tenant.com" {:hd "tenant.com"}) - (mock/content-type "application/x-www-form-urlencoded"))) + response (handler (mock/request :post "/oauth2/test?hd=tenant.com")) location (get-in response [:headers "Location"])] - (print ^String location) - (is (.startsWith ^String location "https://example.com/oauth2/authorize?hd=tenant.com&")))) + (is (.contains ^String location "hd=tenant.com")))) (def token-response {:status 200 From 93daf8e58ba1c991d7dba60ae0881f257205a664 Mon Sep 17 00:00:00 2001 From: Sam Bauch Date: Wed, 17 Feb 2021 18:13:14 -0500 Subject: [PATCH 3/5] concat query string instead of reading out params --- src/ring/middleware/oauth2.clj | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/ring/middleware/oauth2.clj b/src/ring/middleware/oauth2.clj index ba4060c..92459bf 100644 --- a/src/ring/middleware/oauth2.clj +++ b/src/ring/middleware/oauth2.clj @@ -3,7 +3,6 @@ [clj-time.core :as time] [clojure.string :as str] [crypto.random :as random] - [ring.middleware.params :refer [wrap-params]] [ring.util.codec :as codec] [ring.util.request :as req] [ring.util.response :as resp])) @@ -20,23 +19,21 @@ (defn- authorize-uri [profile request state] (str (:authorize-uri profile) (if (.contains ^String (:authorize-uri profile) "?") "&" "?") - (codec/form-encode - (merge (:query-params request) - {:response_type "code" - :client_id (:client-id profile) - :redirect_uri (redirect-uri profile request) - :scope (scopes profile) - :state state })))) + (request :query-string) + (codec/form-encode {:response_type "code" + :client_id (:client-id profile) + :redirect_uri (redirect-uri profile request) + :scope (scopes profile) + :state state}))) (defn- random-state [] (-> (random/base64 9) (str/replace "+" "-") (str/replace "/" "_"))) (defn- make-launch-handler [profile] - (wrap-params - (fn [{:keys [session] :or {session {}} :as request}] - (let [state (random-state)] - (-> (resp/redirect (authorize-uri profile request state)) - (assoc :session (assoc session ::state state))))))) + (fn [{:keys [session] :or {session {}} :as request}] + (let [state (random-state)] + (-> (resp/redirect (authorize-uri profile request state)) + (assoc :session (assoc session ::state state)))))) (defn- state-matches? [request] (= (get-in request [:session ::state]) From 6c3b4053a3ca54f209c6355d890eb7d4f243123f Mon Sep 17 00:00:00 2001 From: Sam Bauch Date: Thu, 18 Feb 2021 09:32:40 -0500 Subject: [PATCH 4/5] Update src/ring/middleware/oauth2.clj --- src/ring/middleware/oauth2.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ring/middleware/oauth2.clj b/src/ring/middleware/oauth2.clj index 92459bf..ebe9d05 100644 --- a/src/ring/middleware/oauth2.clj +++ b/src/ring/middleware/oauth2.clj @@ -19,7 +19,7 @@ (defn- authorize-uri [profile request state] (str (:authorize-uri profile) (if (.contains ^String (:authorize-uri profile) "?") "&" "?") - (request :query-string) + (:query-string request) (codec/form-encode {:response_type "code" :client_id (:client-id profile) :redirect_uri (redirect-uri profile request) From 4e4d67a14cc7e687139a178c378876a3d8a068f5 Mon Sep 17 00:00:00 2001 From: Sam Bauch Date: Wed, 24 Feb 2021 15:20:38 -0500 Subject: [PATCH 5/5] improve test to ensure ampersand between query string and form encoded params --- src/ring/middleware/oauth2.clj | 2 +- test/ring/middleware/oauth2_test.clj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ring/middleware/oauth2.clj b/src/ring/middleware/oauth2.clj index 92459bf..761a5a7 100644 --- a/src/ring/middleware/oauth2.clj +++ b/src/ring/middleware/oauth2.clj @@ -19,7 +19,7 @@ (defn- authorize-uri [profile request state] (str (:authorize-uri profile) (if (.contains ^String (:authorize-uri profile) "?") "&" "?") - (request :query-string) + (if (request :query-string) (str (request :query-string) "&")) (codec/form-encode {:response_type "code" :client_id (:client-id profile) :redirect_uri (redirect-uri profile request) diff --git a/test/ring/middleware/oauth2_test.clj b/test/ring/middleware/oauth2_test.clj index db50782..3fb4332 100644 --- a/test/ring/middleware/oauth2_test.clj +++ b/test/ring/middleware/oauth2_test.clj @@ -61,7 +61,7 @@ handler (wrap-oauth2 token-handler {:test profile}) response (handler (mock/request :post "/oauth2/test?hd=tenant.com")) location (get-in response [:headers "Location"])] - (is (.contains ^String location "hd=tenant.com")))) + (is (.contains ^String location "?hd=tenant.com&")))) (def token-response {:status 200