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 [email protected]
>> Note that posts from new members are moderated - please be patient with your
>> first post.
>> To unsubscribe from this group, send email to
>> [email protected]
>> 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 [email protected]
> Note that posts from new members are moderated - please be patient with your
> first post.
> To unsubscribe from this group, send email to
> [email protected]
> 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 [email protected]
Note that posts from new members are moderated - please be patient with your
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en