I'm trying to use Friend with Luminus (basically lib-noir), and I've found that my :credential-fn
isn't being called at all. At first I thought maybe I added the middleware wrong, but I tried setting a custom :login-failure-handler
to see if at least that worked and it did.
Here's how my app looks like:
(defroutes my-routes
(GET "/login" [login_failed username]
(login-page login_failed username)) ;; login-page just renders HTML form
(GET "/logout" req
(friend/logout* (resp/redirect (str (:context req) "/")))))
(defn login-failure-handler [req]
(println "Failed") ;; <-- get's printed and redirects no problem
(redirect "/login?failed=Y"))
(defn credential-fn [creds-map]
(println creds-map) ;; <-- doesn't get printed at all
{:identity "test" :roles [::user]})
;; define custom wrapping middleware as noir's middleware/app-handler does
;; its own thing with routes + middleware
(defn authenticate [handler]
(friend/authenticate
handler
{:workflows [(workflows/interactive-form
:credential-fn credential-fn
:login-failure-handler login-failure-handler)]}))
(defn debugger [handler]
(fn [req]
(println req)
(handler req)))
(def app (middleware/app-handler
;; add your application routes here
[my-routes]
;; add custom middleware here
:middleware [debugger authenticate]
;; add access rules here
:access-rules []
;; serialize/deserialize the following data formats
;; available formats:
;; :json :json-kw :yaml :yaml-kw :edn :yaml-in-html
:formats [:json-kw :edn]))
I also added a debugger
middleware, that just prints out the request map, and I've noticed that it doesn't print anything at all when I click on my login form's submit button (i.e. no POST request is happening). It just immediately prints out the GET to the login-failure-handler
.
What did I miss?
Turns out my login form was incorrect. Friend specifically expects 2 form params from the POST request, username
and password
. So the login form needs to have those two fields. There doesn't seem to be a way to customise those fields on Friend's side, which I think is a flaw.