login using cookie session in cemerick/Friend

179 views Asked by At

I am trying to integrate Friend into my compojure app.

I have implemented two functions : auth/handle-authentication and auth/check-credential that I use in the following code :

(defroutes app*
  (GET "/requires-authentication" req
       (friend/authenticated (str "You have successfully authenticated as "
                                  (friend/current-authentication)))))


(defn secured-routes
  "Takes a list of unsecure (public) routes
  and returns the same routes but with an authentication middleware
  (authorization still has to be handled for each route)"
  [unsecured-routes]
  (-> unsecured-routes
      (friend/authenticate
          {:allow-anon?             true
           :unauthenticated-handler auth/handle-authentication
           :credential-fn           auth/check-credential
           :workflows [(workflows/http-basic) ; not sure what to put here
                            (workflows/interactive-form)]
})))


(def api-middleware-config
  "Configure the middlewares of the API"
  {:params    {:urlencoded true
               :multipart  true
               :nested     true
               :keywordize true}
   :responses {:not-modified-responses true
               :absolute-redirects     true
               :content-types          true
               :default-charset        "utf-8"}})


(defroutes app

   ;; public routes (they work fine)
  (-> (....)

  ;; authentication required
  (-> (secured-routes app*)
      (wrap-defaults api-middleware-config)
       ...)
  )

auth/check-credential checks the basic auth string from the request. If correct, returns {:identity username}. It works, since with postman/curl I can use the basic auth and get "You have successfully authenticated as ..." as a response.

auth/handle-authentication takes the request and checks that the cookie is correct. If it is, it then returns a map {:identity "test"}. This doesn't do anything, and regardless of the return value of my function (I tried hardcoding it). What am I missing ?

Note that my situation may be a bit specific since the login is done in another app, but the routes/endpoints are shared via nginx and I receive the cookie and have access to the sessions from a database. Checking the cookie is done in auth/handle-authentication.

How can I get "You have successfully authenticated as ..." from a browser with a valid cookie ? Right now I get a 200OK with application/octet stream headers and an empty body (which triggers an empty file download in the browser). I don't really get the :workflow, or what alow-anon? does yet.

Thanks!

1

There are 1 answers

3
schaueho On BEST ANSWER

Your approach looks somewhat strange to me. You assign auth/handle-authentication to :unauthorized, but the handler function assigned to :unauthorized is called when an incoming request could not be authorized.

If I understand you correctly, you want either basic auth or authentication by a third-party supplied cookie where this should be checked by your auth/handle-authentication method. If so, you need to ensure that this method is called as part of what you assign as a :workflow (cf. Friend documentation on workflows). Basically, I think that you're looking for:

:workflows [(auth/handle-authentication) (workflows/http-basic)]

Adam Bard has recently written a blog post on Easy custom auth in Clojure with Friend, I guess this might help clarify.