Search code examples
clojurebasic-authenticationcompojure

Exclude route from authentication in Compojure with friend?


I'm protecting a couple of HTTP routes created with compojure by basic authentication using the friend library. It looks something like this:

(defroutes my-routes
             (context "/ctx" []
                      (GET "/x" [] ...)
                      (GET "/y" [] ...)
                      (GET "/z" [] ...)))

(let [friend-auth-cfg {:allow-anon?             false
                       :unauthenticated-handler #(workflows/http-basic-deny "Unauthorized" %)
                       :workflows               [(workflows/http-basic
                                                   :credential-fn #(creds/bcrypt-credential-fn {"username" {:password (creds/hash-bcrypt "password")}} %)
                                                   :realm "My realm")]}
      my-route (-> (wrap-defaults my-routes api-defaults)
                   (friend/authenticate friend-auth-cfg))]
   (run-jetty (routes my-route)))

What I'd like to do is to exclude the "y" route (/ctx/y) from being protected by basic authentication (but x and z should still be protected). How can I achieve that?


Solution

  • I ended up splitting "my-routes" into two parts:

    (defroutes protected-routes
                 (context "/ctx" []
                          (GET "/x" [] ...)
                          (GET "/z" [] ...)))
    

    and:

    (defroutes unprotected-routes
                 (GET "/ctx/y" [] ...))
    

    And only apply the friend/authenticate middleware to the protected-routes and merging them together like this in the end:

    (run-jetty (routes my-route))