Search code examples
clojurering

Clojure friend causes redirect loop with basic auth


I am using ring with compojure and friend to realize basic password authentication in a toy app. Now I was trying to implement an example and my ring server causes a redirect loop in every browser.

This is my code:

(ns kassenclo.handlers
  (:use [ring.util.response]
        [ring.middleware.resource]
        [ring.middleware.params])
  (:require [compojure.core :refer :all]
            [compojure.route :as route]
            [ring.middleware.session :refer [wrap-session]]
            [ring.middleware.keyword-params :refer [wrap-keyword-params]]
            [kassenclo.views :as views]
            [cemerick.friend :as friend]
            [cemerick.friend.workflows :refer [make-auth]]))

(defroutes app
  (GET "/" [] views/tally-view)
  (GET "/inventory" [] (friend/authorize #{::user} views/inventory-view))
  (route/not-found (html [:h1 "This page could not be found, please go back."])))

(defn auth-workflow [request]
  (let [speak (get-in request [:params :speak])
        credential-fn (get-in request [::friend/auth-config :credential-fn])]
    (make-auth (credential-fn speak))))

(defn auth-credential [password]
  (if (= password "pass")
    {:identity password :roles #{::user}}))

(def handler
  (-> app
      (friend/authenticate {:workflows [auth-workflow]
                            :credential-fn auth-credential})
      (wrap-keyword-params)
      (wrap-params)
      (wrap-session)
      (wrap-resource "public")))

Simple debugging shows me that the server is alternating between auth-workflow and auth-credential a few times before it is stopped. Can anybody point out to me what I am missing?

// Edit: The curious thing is that this redirect-loop happens on every route, even on / where friend is not used in the defroutes command.


Solution

  • I found out that the make-auth function, which wraps the authentication-map so it has the correct form has to be applied on the return value of the auth-credential before returning it. If it happens afterwards like in my original post friend rejects it and we get a authentication loop.