repoze.who + Authority

20 views
Skip to first unread message

Chris McDonough

unread,
Mar 19, 2008, 3:02:59 PM3/19/08
to authori...@googlegroups.com, Mark Ramm, Ian Bicking, whit
Hi folks,

I just got back from PyCon (where many folks still are, sprinting away), and I
wanted to report on what we've done so far as it might relate to authentication,
TG2, and Authority.

The software formerly known as repoze.pam is now named repoze.who (people were
getting confused between UNIX-style PAM and repoze.pam).

repoze.who (http://svn.repoze.org/repoze.who/trunk/) has the following description:

repoze.who's middleware has one major function on ingress: it
conditionally places identification and authentication information
(including a REMOTE_USER value) into the WSGI environment and allows
the request to continue to a downstream WSGI application.

repoze.who's middleware has one major function on egress: it
examines the headers set by the downstream application, the WSGI
environment, or headers supplied by other plugins and conditionally
challenges for credentials.

So basically it's just about identification, authentication, and "challenge"
(asking for login info).

You configure repoze.who by supplying plugin implementations for various
interfaces. These interfaces include:

IIdentifier -- retrieve credentials from the WSGI environment (form, cookies,
basic auth etc)
IAuthenticator -- check credentials against user data store.
IMetadataProvider -- attach arbitrary metadata to an authenticated identity
(user properties, roles, groups, etc).
IChallenger -- return a WSGI application implying some sort of
challenge (a form, basic auth dialog, etc).

We got Bill Rivet using repoze.who in front of TG2 yesterday, and it seems to
function pretty well.

repoze.who currently has a fairly anemic set of plugins: cookie identification,
form indentification, sql authentication, htpasswd authentication, form
challenge. We just got a RADIUS identification plugin working at the sprint.
But we lack win32 stuff, LDAP authentication, OpenID authentication, etc.

Note that repoze.who plugins do not need to live *inside* of repoze.who, they
can live in a package named e.g. "Authority", along with, maybe, authorization
code, which I know is within the scope of Authority (but not in the scope of
repoze.who).

In any case, I'm hoping we can work together on this stuff, and I don't want to
over-push the repoze.who stuff, as I realize you've put a lot of work into
Authority-as-a-framework. There's a lot of overlap. But I'm hoping that we
(the repoze.who folks) can begin to use some of the applicable existing
Authority *implementation* code by turning it into repoze.who plugins. That
would be ideal. If anybody has other suggestions about how we could share
implementation, please let me know.

What I'd like to do is take a use case that Authority handles now and turn some
of the existing code that does that into a repoze.who plugin, just to
demonstrate how this might be done. One useful thing might be a plugin that
consults a data source for group (permission?) information and adds it to the
identity of the downstream user so that TG2 authorization code can use it to
determine whether a user can do something or not. Is there some code I can look
at in Authority that does this now?

Regardless, I plan to write at least one plugin that will be useful for TG2
folks: a challenger plugin which redirects to an existing login form which lives
at a URL (this could be a TG view) to collect login info. This is generically
useful for non-TG systems too.

- C


mark.mch...@gmail.com

unread,
Mar 22, 2008, 8:48:56 PM3/22/08
to Authority
I for one am interested in seeing if some providers could be moved out
of Authority into repoze.who, and exploring the possibility of
delegating authentication responsibility to who and focusing authority
on the authorization layer, and on providing an identity like auth
API.

What do you think Kevin? It seems that there's been some requests to
separate these two things into separate packages in the past, and it
seems like a reasonable oportuity to go that route at the moment.

percious

unread,
Mar 24, 2008, 8:05:18 PM3/24/08
to Authority
How close did we get during the sprints to a TG2 implementation? Is
there a @requires now?

I have a customer who is trying to decide between TG2 and Pylons, and
I really want to have Authority/who in my arsenal.

cheers.
-chris

On Mar 22, 6:48 pm, "mark.mchristen...@gmail.com"

Chris McDonough

unread,
Mar 24, 2008, 9:42:59 PM3/24/08
to authori...@googlegroups.com
On Mar 24, 2008, at 8:05 PM, percious wrote:
>
> How close did we get during the sprints to a TG2 implementation? Is
> there a @requires now?

FTR, I offered today to rough out a set of repoze.who plugins that
would set user and group information from TG1-style user and group
tables for downstream applications (such as a @requires decorator,
which I personally don't know the status of and don't plan to
implement) to consume. I plan to have this done by Thursday. The
plugins I produce will only be a rough cut that will use dbapi and raw
SQL; I hope to rely on more experienced TG folks to massage the rough-
cut plugins to do the right thing with respect to SQLAlchemy and
idiomatic TG2 stuff.

I suspect that doing this is presumptuous, but the very worst that can
happen is that the work I do won't get used (which would be fine) so
I'll forge ahead. ;-)

- C

Mark Ramm

unread,
Mar 24, 2008, 11:29:51 PM3/24/08
to authori...@googlegroups.com
I suspect that doing this is presumptuous, but the very worst that can
happen is that the work I do won't get used (which would be fine) so
I'll forge ahead. ;-)

Thanks for doing the work ;)  And I think there's a very good chance that even if it didn't turn out to be the "default" authorization method in TG2 it will be a common recipe that lots of people use, so the work won't be totally in vain.

If there's anything I can do to help, feel free to let me know.

--
Mark Ramm-Christensen
email: mark at compoundthinking dot com
blog: www.compoundthinking.com/blog

Kevin Horn

unread,
Mar 25, 2008, 1:21:07 AM3/25/08
to authori...@googlegroups.com
On Sat, Mar 22, 2008 at 7:48 PM, mark.mch...@gmail.com <mark.mch...@gmail.com> wrote:

I for one am interested in seeing if some providers could be moved out
of Authority into repoze.who, and exploring the possibility of
delegating authentication responsibility to who and focusing authority
on the authorization layer, and on providing an identity like auth
API.

What do you think Kevin?   It seems that there's been some requests to
separate these two things into separate packages in the past, and it
seems like a reasonable oportuity to go that route at the moment.


I'm still ambivalent about this.  I think that eventually there's a lot of potential for cross-development between Authority and repoze.who, but I've just not been able to put a lot of effort into figuring out how to combine the two.  My meager amounts of free software dev time have gone into Authority for the last couple of weeks, and I'm really trying to concentrate on getting something fully fleshed out, so that we really have something to compare.

As for splitting things into 2 separate packages, I really haven't ever understood why people want to do this.  What does it really buy over a clean separation of concerns within one package?  I'm not dismissing the idea, but I need some convincing I guess.  I just don't see much advantage.

Kevin Horn

Kevin Horn

unread,
Mar 25, 2008, 1:29:03 AM3/25/08
to authori...@googlegroups.com
On Mon, Mar 24, 2008 at 7:05 PM, percious <ch...@percious.com> wrote:

How close did we get during the sprints to a TG2 implementation?  Is
there a @requires now?

I have a customer who is trying to decide between TG2 and Pylons, and
I really want to have Authority/who in my arsenal.

cheers.
-chris


There's been a working require decorator for a long time now, along with most of the "conditions" that TG1 provides (a few are still missing).  Actually there are 2 decorators "require" and "require2" as I was experimenting with different approaches.

There is also now a working (but fragile, and not-yet-very-configurable) "AppForm" authmethod, which can get a form from your application and use that to have the user log in.

In addition there's an htpasswd-style file-based checker that should be working.  I have some patches from Felix I still need to apply and some other improvements to make, but it works.

The only thing really missing at this point is a database-based password checker, some more flexibility in the AppForm method, and a database-based authprovider.

That and a bunch of tests (!) will see about 90% of the TG1 identity API working in TG2.

I'd also like to eventually see if I can't remove some of the Pylons dependencies or at least factor them out into a "framework adapter" similar to what AUthKit did to make Authority play nice with non-Pylons apps.

Kevin Horn

Kevin Horn

unread,
Mar 25, 2008, 1:31:49 AM3/25/08
to authori...@googlegroups.com

Presume away!  You won't bother me. :)

Kevin Horn

Chris McDonough

unread,
Mar 25, 2008, 2:54:21 AM3/25/08
to authori...@googlegroups.com

On Mar 25, 2008, at 1:21 AM, Kevin Horn wrote:
> On Sat, Mar 22, 2008 at 7:48 PM, mark.mch...@gmail.com <mark.mch...@gmail.com
> > wrote:
>
> I for one am interested in seeing if some providers could be moved out
> of Authority into repoze.who, and exploring the possibility of
> delegating authentication responsibility to who and focusing authority
> on the authorization layer, and on providing an identity like auth
> API.
>
> What do you think Kevin? It seems that there's been some requests to
> separate these two things into separate packages in the past, and it
> seems like a reasonable oportuity to go that route at the moment.
>
>
> I'm still ambivalent about this. I think that eventually there's a
> lot of potential for cross-development between Authority and
> repoze.who, but I've just not been able to put a lot of effort into
> figuring out how to combine the two. My meager amounts of free
> software dev time have gone into Authority for the last couple of
> weeks, and I'm really trying to concentrate on getting something
> fully fleshed out, so that we really have something to compare.

You gotta do what you gotta do, but repoze.who is curently "done" for
some definition of "done", and only specific plugins to it need be
written to form various authentication systems. I'd like to think
that if Authority was "as done" as repoze.who is, and it didn't make
too many TG-specific assumptions, I'd try to use it out of an
obligation not to reinvent that wheel. I might end up not using it if
it didn't fit my needs, but I'd make a genuine effort to make sure it
didn't before I reimplemented it.

That said, I understand that using other people's frameworky software
is *much, much* harder (and a heck of lot less fun) than writing your
own. To that end, I'm happy to try to a) make it easier, and b) make
it more fun (or at least suck less ;-) ).

I'm pretty sure there's some impedance mismatch between the
terminology of what currently exists in Authority and the terminology
used by repoze.who. As I understand the Authority code, what
Authority calls "prompts" ("methods"?) are referred to as
"challengers" in repoze.who. Authority "checkers" are
"authenticators" in repoze.who. But both Authority's authentication
code and repoze.who do largely the same thing as it relates to a)
obtaining credentials from the request b) authenticating those
credentials and c) prompting the user for credentials if the
downstream application refuses the request with a 4XX response code.
repoze.who does one additional thing which is elided in Authority
(mostly because Authority seems to conflate authentication with the
creation of user object instances): it allows you to attach arbitrary
metadata to an "identity" (groups, roles, etc). These are meant to be
consumed by downstream code, like authorization code and code which
turns the identity (which is just a dictionary) into a "user object".

I suspect the repoze.who plugins I'm writing for TG1-style tables
might help here too. There will be *lots* of room for improvements on
the plugins I write (they will almost certainly just get thrown out
and reimplemented), because I'm not familar with TG idioms or
subsystems. But I'm hoping they'll be sufficient to drive interest.

More essentially, we (the repoze folks) are trying to produce things
that are useful across many WSGI applications with the dream that one
day we'll all just be "Python web developers" instead of "TG
developers" or "Zope developers" or "Django developers". This
particular thing (repoze.who) may or may not be a fit for TG2, but I
think it's worth the effort to try to collaborate (even if we fail
miserably, it's definitely fun to get to know other folks you might
not have had the chance to work with).

> As for splitting things into 2 separate packages, I really haven't
> ever understood why people want to do this. What does it really buy
> over a clean separation of concerns within one package? I'm not
> dismissing the idea, but I need some convincing I guess. I just
> don't see much advantage.

repoze.who is strictly about authentication because it's meant to be
useful in front of arbitrary WSGI applications. Authentication-
related requirements are generally shared by most WSGI applications
(or at least it's usually not very hard to modify any particular
application to use authentication credentials provided by a trusted
upstream source), but authorization schemes vary wildly across web
applications, and so can't be as easily generalized.

There's no real reason that authentication and authorization code need
to live in separate packages, but since people who use, say, Trac
definitely don't need TurboGears authorization decorators since Trac
has a different authorization scheme, but both Trac and TurboGears
need the same sort of authentication facilities, it's mostly a
packaging separation defined by audience-appropriateness.

- C


Kevin Horn

unread,
Mar 25, 2008, 11:54:51 AM3/25/08
to authori...@googlegroups.com
 
repoze.who is definitely a lot more "done" than Authority.  In fact, if I had known about it before I started, I probably would have built on it instead. :)

That said, I understand that using other people's frameworky software
is *much, much* harder (and a heck of lot less fun) than writing your
own.  To that end, I'm happy to try to a) make it easier, and b) make
it more fun (or at least suck less ;-) ).
 
:)

I'm pretty sure there's some impedance mismatch between the
terminology of what currently exists in Authority and the terminology
used by repoze.who.  

The terminology is different, but the ideas are basically the same.
 
As I understand the Authority code, what
Authority calls "prompts" ("methods"?) are referred to as
"challengers" in repoze.who.  

Authority AuthMethods seem to me to perform the functions of both the "challenger" and the "identifier" in repoze.who.  I've just tied them together, where you've separated them out.  For the record, I like the "challenger" term better than "method".  I just couldn't think of anything better at the time.
 
Authority "checkers" are
"authenticators" in repoze.who.  

Yup.
 
But both Authority's authentication
code and repoze.who do largely the same thing as it relates to a)
obtaining credentials from the request b) authenticating those
credentials and c) prompting the user for credentials if the
downstream application refuses the request with a 4XX response code.
repoze.who does one additional thing which is elided in Authority
(mostly because Authority seems to conflate authentication with the
creation of user object instances): it allows you to attach arbitrary
metadata to an "identity" (groups, roles, etc).  These are meant to be
consumed by downstream code, like authorization code and code which
turns the identity (which is just a dictionary) into a "user object".
 
Actually not so different.  Authority passes around a "credentials" object (just a dictionary), which the "provider" can later turn into a user object (which is a _very_ simple object).  This is probably hard to see from Authority's code, since I haven't really written any (useful) providers yet.

I suspect the repoze.who plugins I'm writing for TG1-style tables
might help here too.  There will be *lots* of room for improvements on
the plugins I write (they will almost certainly just get thrown out
and reimplemented), because I'm not familar with TG idioms or
subsystems.  But I'm hoping they'll be sufficient to drive interest.

I think they will be very helpful.  I'm looking forward to it. 
 
More essentially, we (the repoze folks) are trying to produce things
that are useful across many WSGI applications with the dream that one
day we'll all just be "Python web developers" instead of "TG
developers" or "Zope developers" or "Django developers".  This
particular thing (repoze.who) may or may not be a fit for TG2, but I
think it's worth the effort to try to collaborate (even if we fail
miserably, it's definitely fun to get to know other folks you might
not have had the chance to work with).

The idea behind Authority is to eventually  get it working with  POWA (Plain Old  WSGI Apps), but since my motivation was to get a workable auth framework for TG2, I've skirted around total WSGI-compatibility for the moment.  If I ever get the time to go through the repoze.who code properly (sigh) I expect I'll find a few things that will help with that goal.

I certainly think there's the potential for a huge win in collaboration between the two projects, but my main limiting factor right now is time.  There just never seems to be enough of it, and I stuill haven't had time to wrap my head around repoze.who to the point where I can see how exactly we can share knowledge/code/etc.

> As for splitting things into 2 separate packages, I really haven't
> ever understood why people want to do this.  What does it really buy
> over a clean separation of concerns within one package?  I'm not
> dismissing the idea, but I need some convincing I guess.  I just
> don't see much advantage.

repoze.who is strictly about authentication because it's meant to be
useful in front of arbitrary WSGI applications.  Authentication-
related requirements are generally shared by most WSGI applications
(or at least it's usually not very hard to modify any particular
application to use authentication credentials provided by a trusted
upstream source), but authorization schemes vary wildly across web
applications, and so can't be as easily generalized.

There's no real reason that authentication and authorization code need
to live in separate packages, but since people who use, say, Trac
definitely don't need TurboGears authorization decorators since Trac
has a different authorization scheme, but both Trac and TurboGears
need the same sort of authentication facilities, it's mostly a
packaging separation defined by audience-appropriateness.

Sure they have different schemes, but they both need authorization of some kind, and pretty much all applications I've ever seen have their authorization requirements fall into one of the following categories:

- the user IS a specific user (username)
- the user IS ONE OF a set of users (groups)
- the user IS ALLOWED to perform a specific function (permissions)

You can fit the word "roles" in there someplace, but some put it in the groups category, and some in the permissions category, so I just ducked the problem by avoiding it altogether.

At any rate, that's why I've focused on a generic interface for Authorization.  The plan is for Authority users to easily be able to create their own "providers", or even their own "conditions" to make whatever Authorization scheme they want.

I think the key thing is to be able to separate authorization and authentication, so that you can
a) use authentication only
b) use different storage mechanisms for authentication and authorization

But at the same time, I think it is desirable to at least be _able_ to share resources (db connections, files, whatever) between the two pieces.
 
As far a "authorization decorators", Authority only really has one decorator (actually there are two, but it _will_ only have one), which takes a "condition" for authorization purposes, and if there's no condition, it just authenticates the user with no further authorization.  This should allow for "public" vs. "private" urls.


- C



Kevin Horn

Chris McDonough

unread,
Mar 26, 2008, 1:53:12 PM3/26/08
to authori...@googlegroups.com
Kevin Horn wrote:
> Authority AuthMethods seem to me to perform the functions of both the
> "challenger" and the "identifier" in repoze.who. I've just tied them
> together, where you've separated them out. For the record, I like the
> "challenger" term better than "method". I just couldn't think of anything
> better at the time.

The notional reason that identifiers and challengers are distinct in repoze.who
is that while usually all challenger implementations need to also be (or at
least defer to another) an identifier implementation, all identifier
implementations need not be challengers.

For instance, you can write a cookie identifier that isn't tied to any
particular challenge type and reuse it across slightly different form
challengers (e.g. a form challenger that redirects, one that doesnt).

An example of this pattern is
http://svn.repoze.org/repoze.who/trunk/repoze/who/plugins/form.py which is both
a challenger and an identifier implementation, but the "identification" methods
(remember/forget) actually delegate to another identifier plugin (which could be
an arbitrary identification plugin, but will most commonly be some cookie
identification plugin).

> Actually not so different. Authority passes around a "credentials" object
> (just a dictionary), which the "provider" can later turn into a user object
> (which is a _very_ simple object). This is probably hard to see from
> Authority's code, since I haven't really written any (useful) providers yet.

Got it, thanks.

> The idea behind Authority is to eventually get it working with POWA (Plain
> Old WSGI Apps), but since my motivation was to get a workable auth
> framework for TG2, I've skirted around total WSGI-compatibility for the
> moment. If I ever get the time to go through the repoze.who code properly
> (sigh) I expect I'll find a few things that will help with that goal.
>
> I certainly think there's the potential for a huge win in collaboration
> between the two projects, but my main limiting factor right now is time.
> There just never seems to be enough of it, and I stuill haven't had time to
> wrap my head around repoze.who to the point where I can see how exactly we
> can share knowledge/code/etc.

Understood. Hopefully the plugins I write will help.

> Sure they have different schemes, but they both need authorization of some
> kind, and pretty much all applications I've ever seen have their
> authorization requirements fall into one of the following categories:
>
> - the user IS a specific user (username)
> - the user IS ONE OF a set of users (groups)
> - the user IS ALLOWED to perform a specific function (permissions)
>
> You can fit the word "roles" in there someplace, but some put it in the
> groups category, and some in the permissions category, so I just ducked the
> problem by avoiding it altogether.

Yup In Zope, there is an additional level of abstraction in the form of roles
(which can be provided to groups or users globally, or in a "place").
"permissions" in Zope are attached to particular methods. Some number of roles
are given some number of permissions in a "place". A Zope user's roles are also
determined by a "place". There is no facility for roles or place in the
primitives you describe above, so Zope just couldn't use a system based on those
primitives.

> At any rate, that's why I've focused on a generic interface for
> Authorization. The plan is for Authority users to easily be able to create
> their own "providers", or even their own "conditions" to make whatever
> Authorization scheme they want.

I've tilted at that windmill for a while too:
http://www.plope.com/Members/chrism/decsec_revisited

That's a framework I wrote to do declarative security in a WSGI stack. I was
never quite happy with the amount of work someone would have to do to implement
their own authorization callbacks. The frameworky bits don't seem to do enough
to make it worth someone's while to use rather than just embedding the
authorization stuff in their application.

I'm not saying it's impossible, I'm just saying it's pretty hard, and tackling
both authentication and authorization in the same package if the package is
meant to be useful across arbitrary WSGI apps is a pretty huge committment.

> I think the key thing is to be able to separate authorization and
> authentication, so that you can
> a) use authentication only
> b) use different storage mechanisms for authentication and authorization
>
> But at the same time, I think it is desirable to at least be _able_ to share
> resources (db connections, files, whatever) between the two pieces.

Yes. That's currently tricky. This feels like it should be handled by a
library of some kind.

> As far a "authorization decorators", Authority only really has one decorator
> (actually there are two, but it _will_ only have one), which takes a
> "condition" for authorization purposes, and if there's no condition, it just
> authenticates the user with no further authorization. This should allow for
> "public" vs. "private" urls.

repoze.who just assumes that if a 401 is returned by the application, the user
needs to be challenged (and the "best" challenge plugin then fires).

So in a notional repoze.who-aware decorator, all the authorization decorator
would need to do is check the repoze.who identity in the environ
(environ['repoze.who.identity'],) which will include user, group, and permission
info, and allow the request to proceed if the identity satisfies the condition
or (in Pylons terms) abort(401) if it doesn't. Maybe the decorator would also
be responsible for turning the identity into a more useful user object at that
point too. This I'm not sure about.

- C

Reply all
Reply to author
Forward
0 new messages