8

I'm not really understanding https://github.com/clojure-liberator/liberator and the list of decision points that it provides to the developer. How would one implement a basic auth/auth service using/alongside/on-top-of the library?

2 Answers 2

14

The idiomatic way is to implement the :authorized? decision point. However there is currently no support for the handling of basic or digest authentication. A practical approach is to use ring-basic-authentication for authentication and handle only authorization in the resource. The following example uses ring-basic-authentication and sets the token to a users's role. This role is then checked by liberator in authorized?

(defresource admin-only
  :handle-ok "secrect"
  :handle-unauthorized "for admins only"
  :authorized? (fn [{{token :token} :request}]
                 (= "admin" token)))

;; token returned encodes role
(defn authenticated? [name pass] 
  (cond (and (= name "scott") 
             (= pass "tiger")) "admin")
        (and (= name "jack")
             (= pass "jill"))  "user)))

(def app (wrap-basic-authentication admin-only authenticated?))
Sign up to request clarification or add additional context in comments.

4 Comments

cone should be cond in this (very good) example, but we aren't allowed to fix typos
Typo is fixed. Thanks for the hint
I was able to manage the authentication, but not the authorization. If I pass "admin-only" to wrap-basic-authentication I get the following error "clojure.lang.ArityException: Wrong number of args (2) passed to: controller/admin-only". My route declaration is as follows: (GET "/test" request (admin-only request ). How the token gets to the resource? Thanks.
In the latest version of wrap-basic-authentication authenticated? return is filled in request :basic-authentication. So to get it's necessary to do the following :authorized? #(get-in % [:request :basic-authentication])):
6

from the readme"

Resources are compatible with Ring and can be wrapped in Ring middleware. When evaluated, a resource returns a function which takes a Ring request and returns a Ring response.

so you can then wrap it in ring-basic-authentication

(use 'ring.middleware.basic-authentication)
(defn authenticated? [name pass] (and (= name "foo") (= pass "bar")))
(def app (-> routes .. (wrap-basic-authentication authenticated?))

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.