Gert, There is no declarative way to satisfy that requirement at the moment. Fine-grained authorization often falls out to imperative checks, though there are mostly-declarative approaches in other libraries/frameworks that I have yet to grok enough to have a feel for what Friend should do in this area. (As an aside, I think something like trammel will prove to be very useful for fine-grained authorization.)
There is a function `cemerick.friend/throw-unauthorized` that will raise an unauthorized exception that the top level `authenticate` middleware will catch, and either redirect to your :login-uri if the user isn't logged in, or pass along to the :unauthorized-handler you provide if the user is logged in (the default simply returns an HTTP 401 with a plain text message). So, assuming the user's :id is in the authentication map your credential fn is returning, you can do something like: (POST "/user/:id" [id & params :as req] (let [identity (friend/identity req)] (if-not (or (friend/authorized? #{"admin"} identity) (and (friend/authorized? #{"user"} identity) (= id (:id (friend/current-authentication identity))))) (friend/throw-unauthorized identity) ;; actual implementation of POST /user/:id... ))) Of course, you can factor the above out into a function to apply generally to any route/function that has similar authorization requirements (and maybe applied as a hook, depending on personal taste). Does that help? FWIW, there's no reason for solutions to problems like these to come exclusively from Friend itself. I'd love to have contributions addressing general-interest requirements (of which fine-grained, declarative authorization is an example), but especially for more esoteric security requirements, I hope I've made it possible for enterprising and informed hackers to independently build extensions and addons. Cheers, - Chas -- http://cemerick.com [Clojure Programming from O'Reilly](http://www.clojurebook.com) On Apr 18, 2012, at 7:38 PM, Gert Verhoog wrote: > That looks promising, good work! > > I read through the docs and browsed the sources, and (admittedly without > trying to code an example myself) it's not immediately obvious to me how > Friend would handle the following use case: > > Given: > - three users: alice, bob, and admin. Alice and Bob have a "user" role, and > admin is "admin" > - "edit user account" routes, such as > (GET "/user/:id/edit" [id] (show-edit-form)) > (POST "/user/:id" [id & params] (update-user)) > > How would I use Friend to ensure that these resources can only be accessed if: > - you have the "admin" role, OR > - you are a user AND your id matches the id in the url? > > > cheers, > gert > > > > > On 12/04/2012, at 2:34 AM, Chas Emerick wrote: > >> For your consideration, a new library: >> >> I’m hoping this can eventually be a warden/spring-security/everyauth >> /omniauth for Clojure; that is, a common abstraction for authentication and >> authorization mechanisms. Clojure has been around long enough that adding >> pedestrian things like form and HTTP Basic and $AUTH_METHOD_HERE to a Ring >> application should be easy. Right now, it’s not: either you’re pasting >> together a bunch of different libraries that don’t necessarily compose well >> together, or you get drawn into shaving the authentication and authorization >> yaks for the fifth time in your life so you can sleep well at night. >> >> Hopefully Friend will make this a solved problem, or at least push things in >> that direction. >> >> Read more here: http://wp.me/p10OJi-d6 >> >> Cheers, >> >> - Chas >> >> -- >> http://cemerick.com >> [Clojure Programming from O'Reilly](http://www.clojurebook.com) >> >> -- >> You received this message because you are subscribed to the Google >> Groups "Clojure" group. >> To post to this group, send email to clojure@googlegroups.com >> Note that posts from new members are moderated - please be patient with your >> first post. >> To unsubscribe from this group, send email to >> clojure+unsubscr...@googlegroups.com >> For more options, visit this group at >> http://groups.google.com/group/clojure?hl=en > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with your > first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en