[ANN] Authorization Plugin for Rails

I’ve posted a lengthy description of an authorization plugin for Rails
on my
blog:
http://www.billkatz.com/authorization

It describes a proposed DSL for authorization, a pattern for use that
describes conventions, and a reference implementation that lets you test
the
some of the ideas. I hope that some subset of Rails programmers
gravitate
toward a common DSL for authorization, which would ease sharing of
plugins
that require authorization.

Hope you like it.
-Bill

On Tue, 21 Feb 2006 01:31:29 -0500, Bill K. wrote:

I’ve posted a lengthy description of an authorization plugin for Rails on my
blog:
http://www.billkatz.com/authorization

I’m really glad you’ve taken this on - with three active role-based
plugin
projects, it’s a good time to settle on compatible syntax.

Initial musings:

  • “permit” might too short a phrase for a plugin/engine that will gain
    widespread use. What’s the likelihood of conflict? Would permit_access
    be
    better, or is that redundant? Then again, if rails can take “render”
    and
    “find” for itself, maybe “permit” is fine.

  • It looks like you can grant a whole action permission at the top of
    the
    class, not just wrapped in a block, right? As in
    permit “registered”, :except => public

I assume multiple permit statements would be additive - if one of them
grants you access, you have access? It might be nice to declare that
they’re processed in order, and to create an equivalent “deny”
statement.
Otherwise, there are things you can’t do. F’rinstance, I want to take
new
users (who have role User) through a registration screen, but not allow
them back once they’ve been granted the Registered role. Since the User
and Registered roles are additive in UserEngine, I have to create a
temporary Registering role, instead of
deny “registered”, :only => :reg_action
permit “user”, :only => :reg_action

  • Thinking along those lines, :action might better than :only, since
    :only
    isn’t actually exclusive.

  • As someone who hasn’t done Ruby outside Rails - and who’s watched as
    Rails’ reliance on instance variables has decreased since 0.8 - I find
    it
    confusing that “:meeting” can refer to substition by an options hash (a
    la
    printf(“%s”)) or a previously-defined instance variable.

If it’s an instance variable, I’d like to explicitly declare that:
permit “moderator of @meeting

If, otoh, it’s an options hash, well, I’m not sure, but maybe
permit “moderator of #meeting

Using “:meeting” implies (to my brain) that it’s a real symbol already
defined elsewhere. I’m trying to think of other Rails-isms that do such
substitution, but I haven’t had enough coffee yet.

I had a few other confusions about meeting vs. Meeting vs. :meeting vs
@meeting.id, but I think I cleared them up as I wrote this.

Again, I feel like the syntax is disambiguous enough for a parser, but
not
necessarily for a programmer… but I don’t have enough Rails/Ruby
experience to necessarily suggest something better.

Jay L.

On 2/21/06, Jay L. [email protected] wrote:

  • It looks like you can grant a whole action permission at the top of the
    class, not just wrapped in a block, right? As in
    permit “registered”, :except => public

Yes. A class method “permit” inserts authorization checks via the
before_filter, and I pass along the :only and :except hashes. In real
life,
this makes for succinct class-level authorization. A few of my
controllers
are restricted to registered members, which only requires: permit
“member”

I assume multiple permit statements would be additive - if one of them

grants you access, you have access?

They are processed in order and use redirection by default, unless you
use
the permit? form. The idea was to use it like scope: to execute a method
you
have to satisfy the class-level authorization as well as any preceding
method-level permits. Unfortunately, I haven’t been able to work out
short-circuiting with the redirection. That’s why the block form of
permit (
i.e., permit “foo” do…end) is used frequently in my code.

It might be nice to declare that

they’re processed in order, and to create an equivalent “deny” statement.
Otherwise, there are things you can’t do. F’rinstance, I want to take new
users (who have role User) through a registration screen, but not allow
them back once they’ve been granted the Registered role. Since the User
and Registered roles are additive in UserEngine, I have to create a
temporary Registering role, instead of
deny “registered”, :only => :reg_action
permit “user”, :only => :reg_action

I think this is what you want:
permit “user and not registered” do

end
If you use that in #reg_action, it will redirect unless whatever
user-like
model you are using has role “user” and is not “registered.”

  • Thinking along those lines, :action might better than :only, since
    :only

isn’t actually exclusive.

The :only, :except syntax is used for compatability with before_filter

  • As someone who hasn’t done Ruby outside Rails - and who’s watched as

Rails’ reliance on instance variables has decreased since 0.8 - I find it
confusing that “:meeting” can refer to substition by an options hash (a la
printf(“%s”)) or a previously-defined instance variable.

I thought about it, and I’m amenable to changes that make things less
confusing. The symbol-like nomenclature for the model is consistent with
ActiveRecord associations, e.g., belongs_to :meeting.

Thanks for the comments.
-Bill