[Twisted-web] [Nevow] new chapter about authentication

glyph at divmod.com glyph at divmod.com
Fri Aug 4 02:16:56 CDT 2006

On Thu, 03 Aug 2006 19:58:58 -0500, "L. Daniel Burr" <ldanielburr at mac.com> wrote:
>On Thu, 03 Aug 2006 17:54:54 -0500, Valentino Volonghi aka Dialtone 
><dialtone at divmod.com> wrote:
>I think this whole discussion is based on a misunderstanding.

I agree.

>To me, the bottom line is this: If all you are ever going to do is build
>web applications, then you will *never* see any real point in jumping
>through all of cred's hoops (portal, avatar, mind, WTF?

Guard _should_ support single-sign-on systems like OpenID or Active Directory, to minimize the number of passwords that users have to remember when interacting with Twisted sites.

If it did, it would be a lot easier to sell some of the learning required to use it well.  But I think that we could do a lot to make the learning seem easier: once over the initial hump, guard is not hard to use and the conceptual design is very simple.

>I just want a freaking username/password combo, secured by SSL, like almost 
>every other web app on Earth!).

Until we can address the prevelance of username/password systems, Guard should pretty do what it does and get out of your way.  I don't think that it should present any additional difficulty due to the fact that it's trying to do more than usernames and passwords: in fact, guard _ONLY_ supports usernames and passwords right now.  I think that interacting with it through a slightly higher-level system like Mantissa is pretty easy, so some focus on a bit of boilerplate to hide some of the more advanced details would be good.

Where people tend to get tripped up is the fact that Guard treats resources as objects or capabilities, whereas the typical web mentality is to treat them as files or functions.  Despite the fact that it's a very common mentality, it leads to atrocious, insecure code.  I think we should be doing everything possible to make the advantages of the guard model clear, and not providing a bug-prone and flaky way to do authentication simply because it seems comfortable and familiar.

I strongly believe that the capability-style authentication that guard provides is significantly more secure than the typical crap that ends up in most web applications.  This has nothing to do with other protocols, except for the fact that programmers writing code to speak other protocols don't have the baggage of thinking of every chat room as a file on disk, or every email as a stateless, universally accessible object which customizes itself on demand.  In a guard-style application, your resources look like this:

  class NormalResource(...):
    def __init__(self, userObj):
      self.userObj = userObj
    def child_lala(self):
      return HarmlessResource(self.userObj.harmlessStuff)

  class AdminResource(NormalResource):
    def child_rootme(self):
      return DestroyEverythingResource(self.userObj.stuffAllowedToDestroy)
    def child_lala(self):
      return NotQuiteHarmlessResource(self.userObj.harmlessStuff)

Whereas what most web developers, only recently dragged in from PHP, _want_ to do is this:

  ADMIN_USERNAMES = ['bob', 'jim', 'me']
  class IDontKnowAnythingAboutEncapsulationResource(...):
    def child_lala(self):
      global PAGE_MODE
      global HARMLESS_STUFF
      global USERNAME
      PAGE_MODE = 'harmless'
      HARMLESS_STUFF = getHarmlessStuff(USERNAME)
      if USERNAME.lower() in ADMIN_USERNAMES:
        PAGE_MODE = 'not_quite_harmless'
      return self

    def child_rootme(self):
      global PAGE_MODE
      global ALLOW_DESTROY
      PAGE_MODE = 'rootme'
      global USERNAME
      if USERNAME.lower() in ADMIN_USERNAMES:
        ALLOW_DESTROY = getAllowedToDestroyStuff(USERNAME)
        PAGE_MODE = '404'
      return self

Obviously I'm exaggerating somewhat for effect here, but this really is a common style, especially once you realize that the database, the request, the session, and the context are all just different forms of global variables.

Due to the resources-are-files mentality, it has become conventional wisdom that passing arguments to the constructors of objects is a hardship, if those objects happen to be resources.  This should stop.  Just about every other kind of programming seems to be on board with the whole "global variables are bad" thing.

Also, did you spot the hidden security bug in the second example?  '.lower()' is locale dependent, so the security check in child_rootme may be wrong depending on the locale the server is run in.  For example, on a turkish server, 'JİM' would be able to access administrative functions, but 'JIM' would not.

Even without weird trivia like that, it's a lot easier to forget an 'if' check for authentication on a sensitive operation than to accidentally implement it in the wrong class, or accidentally implement it twice.

More information about the Twisted-web mailing list