Diff: tgext.authorization vs tg.ext.repoze.who

1 view
Skip to first unread message

Gustavo Narea

unread,
Sep 10, 2008, 9:43:13 AM9/10/08
to turbogea...@googlegroups.com, Florent Aide
Hello, everybody.

[Get a coffee, it's a long email!]

After checking the code for tg.ext.repoze.who, now I have an idea on what
would need to be changed for its successor (tgext.authorization) to support
authorization only. So, these are the changes I propose for the replacement of
tg.ext.repoze.who:

I think we should create a module for authentication and authorization related
stuff in the TG template (at {package}.lib.auth, for example). And I think we
should move the 'middleware' module of tg.ext.repoze.who to this new module,
excluding the SQLMetadataProviderPlugin class (see below to learn why).

On the other hand, I could not find anything on authorize.py that needs to be
changed.

This way, the extension will be made up of the following modules:
- authorize: It *may* need some slight modifications.
- adapters: This module will contain plugins for fetching groups and
permission data for the authenticated user from different backends. They will
*not* be repoze.who's metadata providers: tg.ext.authorization will provide
the only required metadata provider (possibly called 'AuthorizationMetadata'),
which will fetch groups and permissions metadata from one or more adapters;
this way, developers will be able to store groups in one place and permissions
in another (e.g., re-using LDAP groups and storing permissions in an *.ini
file).

Or in a visual way:

+ tgext.authorization
|
`---+ __init__
| |
| `---+ AuthorizationMetadata (class)
|
`---+ authorize
|
`---+ adapters
|
`---+ __init__
| |
| `---+ BaseGroupsAdapter (abstract class or interface)
| |
| `---+ BasePermissionsAdapter (abstract class or interface)
|
`---+ sql
| |
| `---+ class SQLGroups(BaseGroupsAdapter)
| |
| `---+ class SQLPermissions(BasePermissionsAdapter)
|
`---+ htgroup
| |
| `---+ class Htgroups(BaseGroupsAdapter)
|
`---+ ldap
| |
| `---+ class LDAPGroups(BaseGroupsAdapter)
|
`---+ ini
| |
| `---+ class IniGroups(BaseGroupsAdapter)
| |
| `---+ class IniPermissions(BasePermissionsAdapter)
|
:


Silverplate and tgext.authorization
===================================

One of the main reasons to use so-called adapters is not to break Silverplate,
which I think is tied to the only adapter supported by tg.ext.repoze.who, the
SQL one.

With adapters, Silverplate may work in a adapter-agnostic fashion, as long as
the adapter supports not only retrieving, but also adding, modifying and
deleting entries.

How would adaptors would look like
==================================

Roughly, like this:

class BaseGroupsAdapter(object):
# Abstract
def get_all_groups(self):
# Return a tuple for all the groups found in the backend.
# Abstract
def get_groups(self, identity):
# Return a tuple for the groups the user belongs to.
# Abstract
def add_group(self, group_name, group_data):
# Add the group to the backend
# Abstract
def edit_group(self, group_name, group_data):
# Modify the group data
# Abstract
def delete_group(self, group_name):
# Delete the group from the backend

class BasePermissionsAdapter(object):
# Abstract
def get_all_permissions(self):
# Return a tuple for all the permissions found in the backend.
# Abstract
def get_permissions(self, group):
# Return a tuple for the permissions granted to `group`.
# Abstract
def get_groups(self, permission):
# Return a tuple for the groups granted the `permission`.
# Abstract
def grant_permission(self, permission, groups):
# Grant `groups` the `permission` permission
# Abstract
def deny_permission(self, permission, groups):
# Deny `groups` the `permission` permission
# Abstract
def delete_permission(self, permission):
# Delete the `permission` permission from the backend

Then AuthorizationMetadata would look like this:

class AuthorizationMetadata(object):
implements(IMetadataProvider)
def __init__(self, group_fetchers, permission_fetchers):
self.group_fetchers = group_fetchers
self.permission_fetchers = permission_fetchers
def add_metadata(self, environ, identity):
groups = set()
permissions = set()
for grp_fetcher in self.group_fetchers:
groups |= grp_fetcher.get_groups(identity)
for group in groups:
for perm_fetcher in self.permission_fetchers:
permissions |= perm_fetcher.get_permissions(group)
identity['groups'] = groups
identity['permissions'] = permissions


How would it be setup in TG2 applications
=========================================

It would be _extremely_ easy to setup tgext.authorization: The developer
simply has to add the AuthorizationMetadata to the metadata providers of their
repoze.who setup. That's it.

For example, if I store my groups in an Htgroup file and their permissions in
an INI file, I would use a code similar to:

groups_fetcher = Htgroups('/path/to/groups.htgroup')
permissions_fetcher = IniPermissions('/path/to/permissions.ini')
authorization = AuthorizationMetadata([groups_fetcher],
[permissions_fetcher])
mdproviders = [authorization]
app_with_auth = PluggableAuthenticationMiddleware(
app,
identifiers,
authenticators,
challengers,
mdproviders,
default_request_classifier,
default_challenge_decider
)

Please notice that only the first four lines are specific to the setup of
tgext.authorization; the others are specific to repoze.who itself. So the
extension will require at least three lines to be configured!

Using its authorization mechanism
=================================
Its API will be just like that of tg.ext.repoze.who, so we will use it the
same way.

Let's get started!
==================

Please let me know what if think about my proposal.

If we're going to make it, I'll need commit rights in the tgtools repository.
My Google account is the same as the email address I'm currently using.

Cheers!
--
Gustavo Narea.
http://gustavonarea.net/

Get rid of unethical constraints! Switch to Freedomware:
http://softwareliberty.com/


signature.asc

Mark Ramm

unread,
Sep 10, 2008, 12:47:01 PM9/10/08
to turbogea...@googlegroups.com, Florent Aide
> I think we should create a module for authentication and authorization related
> stuff in the TG template (at {package}.lib.auth, for example). And I think we
> should move the 'middleware' module of tg.ext.repoze.who to this new module,
> excluding the SQLMetadataProviderPlugin class (see below to learn why).

So what exactly goes in lib.auth?

My concern here is that there is already too much code generation
going on in the quickstart template, so I'm concerned about the size
of any additions there.

Lee McFadden

unread,
Sep 10, 2008, 1:32:25 PM9/10/08
to turbogea...@googlegroups.com
On Wed, Sep 10, 2008 at 5:47 PM, Mark Ramm <mark.mch...@gmail.com> wrote:
>
> So what exactly goes in lib.auth?
>

From what I can see it will be boilerplate for the most part other
than using the project name here and there so I don't see much of a
problem with it in terms of code generation per se.

I like the idea of this as it will give a lot of customization options
in terms of authentication for advanced users while remaining tucked
away for 90% of use cases.

--
Lee McFadden

blog: http://www.splee.co.uk
rejaw: http://rejaw.com/splee
twitter: http://twitter.com/splee

Gustavo Narea

unread,
Sep 10, 2008, 1:41:20 PM9/10/08
to turbogea...@googlegroups.com, Mark Ramm, Florent Aide
Hello,

On Wednesday September 10, 2008 18:47:01 Mark Ramm wrote:
> So what exactly goes in lib.auth?

Code to setup authentication and authorization in the application.
Specifically, the SQLAuthenticatorPlugin class and the make_who_middleware()
function found here:
http://code.google.com/p/tgtools/source/browse/projects/tg.ext.repoze.who/trunk/tg/ext/repoze/who/middleware.py?r=60

make_who_middleware() should be in the TG2-powered project, because this
extension won't deal with authentication anymore. This function is the one
that setups repoze.who.

And we should include SQLAuthenticatorPlugin in the project, if and only if we
want to keep the current identity structure (user, groups and permissions in a
database) by default in quickstarted projects.

> My concern here is that there is already too much code generation
> going on in the quickstart template, so I'm concerned about the size
> of any additions there.

Yes, I understand. But if we're going to make this extension only deal with
authorization, we'll have to move its authentication bits into the template.

Although option B would be to move tg.ext.repoze.who.middleware to
tgext.authorization.quickstart (for example). I think this is the best
solution if we don't want to make the template more complex: The template
wouldn't be modified (except that
tg.ext.repoze.who.middleware.make_who_middleware() will be replaced by
tgext.authorization.quickstart.make_who_middleware()).

Cheers.

Gustavo Narea

unread,
Sep 10, 2008, 1:48:52 PM9/10/08
to turbogea...@googlegroups.com
On Wednesday September 10, 2008 19:32:25 Lee McFadden wrote:
> I like the idea of this as it will give a lot of customization options
> in terms of authentication for advanced users while remaining tucked
> away for 90% of use cases.

Exactly. It would only be modified by those who need something more advanced.

I also agree that it should not be a problem for those who don't need to
modify it. Actually, it'd make it easier for those who want something
different (not necessarily more advanced; the developer may want to use plain
Htpasswd for authentication, and Htgroup with permissions being stored in INI
files for authorization, which I consider less complex than using a database
for everything).

Mark Ramm

unread,
Sep 10, 2008, 3:05:37 PM9/10/08
to turbogea...@googlegroups.com
So, I think the middleware should live in some library somewhere, not
in the template itself (what if there's a security fix, do we require
all users to update their generated middleware code?) and I'm fine
with putting it in tgext.authorization.quickstart or
tgext.authorization.helpers or whatever we want to call it.
Alternatively if you feel really strongly that id does not belong in
tgext.authorization we can put it in tg itself
tg.authhelpers.make_who_middleware.

The key thing is that it should be easy to extend, but that those who
don't want to extend it should not have to understand and maintain it.

--Mark Ramm

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

Gustavo Narea

unread,
Sep 10, 2008, 3:26:14 PM9/10/08
to turbogea...@googlegroups.com
On Wednesday September 10, 2008 21:05:37 Mark Ramm wrote:
> So, I think the middleware should live in some library somewhere, not
> in the template itself (what if there's a security fix, do we require
> all users to update their generated middleware code?) and I'm fine
> with putting it in tgext.authorization.quickstart or
> tgext.authorization.helpers or whatever we want to call it.
> Alternatively if you feel really strongly that id does not belong in
> tgext.authorization we can put it in tg itself
> tg.authhelpers.make_who_middleware.

That sounds good. Then I think we should do it that way.

> The key thing is that it should be easy to extend, but that those who
> don't want to extend it should not have to understand and maintain it.

+1.

Cheers.

percious

unread,
Sep 13, 2008, 12:25:18 AM9/13/08
to TurboGears Trunk
+1
Reply all
Reply to author
Forward
0 new messages