weavejester / ring-oauth2

OAuth 2.0 client middleware for Ring
146 stars 38 forks source link

400 "No authorization code" on callback, even though I can see code in URL string #43

Closed njerig closed 4 months ago

njerig commented 3 years ago

I can see both code and state attached to my callback url as query params, and (when make-redirect is called) get-authorization-code returns nil. I'm not sure why this would happen, as I can see both code and state as query params in my /callback's URL string.

weavejester commented 3 years ago

Do you have wrap-params in your middleware? As the README says:

you must make sure that ring.middleware.params/wrap-params is enabled and runs before this middleware, as this library depends on the :query-params key to be present in the request.

whatacold commented 3 years ago

Hi, I am playing ring-oauth2 with compojure, all works well except the last step resulting in "No authorization code".

Here is handler.clj:

(ns hello-compojure.handler
  (:require [compojure.core :refer :all]
            [compojure.route :as route]
            [ring.middleware.defaults :refer [wrap-defaults site-defaults]]
            [ring.middleware.params :refer [wrap-params]]
            [ring.middleware.oauth2 :refer [wrap-oauth2]]
            [selmer.parser :refer [render render-file]]
            [selmer.util :refer [resource-path]]))

(defroutes app-routes
  (GET "/login/" [] "<a href=\"/login/github\">github</a>")
  (GET "/user/profile" request (str "whole request map:" request))
  (route/not-found "Not Found"))

;; print the request
(defn- wrap-print-request [handler]
  (fn
    ([request]
     (println "print request sync:" (:uri request) (str request))
     (handler request))
    ([request respond raise]
     (println "print request async:" (:uri request) (str request))
     (handler request respond raise))))

(def app
  (let [profiles {:github
                 {:authorize-uri    "https://github.com/login/oauth/authorize"
                  :access-token-uri "https://github.com/login/oauth/access_token"
                  :client-id        conf-client-id
                  :client-secret    conf-client-secret
                  :scopes           ["user:email"]
                  :launch-uri       "/login/github"
                  :redirect-uri     "/login/github-callback"
                  :no-auth-code-handler (fn [request] {:status 401, :headers {}, :body (str "debug no code request:" request)})
                  :landing-uri      "/user/profile"}}]
    (-> app-routes
        (wrap-defaults (assoc-in site-defaults [:session :cookie-attrs :same-site] :lax))
        wrap-params
        wrap-print-request
        (wrap-oauth2 profiles)
        )))

I have two questions:

  1. What's wrong with the above wrap-params? I can confirm with a debugging :no-auth-code-handler that the request doesn't have :query-params.
  2. The debugging-purpose wrap-print-request doesn't work with URIs /login/github and /login/github-callback, but it works with "normal" URIs like "/user/profile", why is that?

Thanks.

whatacold commented 3 years ago

Oops, it turns out that I place the middle-wares in wrong order, adjusting it to the below order fixes it:

    (-> app-routes
        wrap-print-request
        (wrap-oauth2 profiles)
        (wrap-defaults (assoc-in site-defaults [:session :cookie-attrs :same-site] :lax))
        wrap-params)

P.S. @njerig did it due to the exact problem for you?

zikajk commented 3 years ago

@whatacold Thank you, I have been struggling with this for an hours!