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!
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:Adam Bard has recently written a blog post on Easy custom auth in Clojure with Friend, I guess this might help clarify.