Skip to main content

Spyce will not waste your time: authentication

If you work in the web development area, or even dabble in it as a hobbyist, sooner or later you're going to write code for a project that needs authentication. Probably sooner than later.

For a feature that gets used so frequently, it's remarkable to me that nobody has really done this right. Here are some basic principles for a good solution:

  1. A minimum of customization to work out-of-the-box
  2. Gentle complexity slope when more sophisticated behavior is needed
  3. Play nice with others
  4. Don't try to solve world hunger

The first two are, I hope, no-brainers. The second two bear more explanation.

Play nice with others: not everyone wants to authenticate against a Users table in a relational database. (Fairly common alternatives are LDAP or Unix logins.) If you bake in assumptions like this too deep, it causes problems. It might be worth the problems if it were impossible to provide both generality and ease of use, but such is not the case.

Don't try to solve world hunger. By this I mean, don't invent a Grand Unified Authorization/Permissions scheme with Groups and Subgroups and Roles and ACLs that supposedly can handle any needed authorization requirements, but requires a week of studying your system to make it work. There have been several attempts by very smart people to make this work and it hasn't, yet. So unless you are a grad student or in some other position that leaves you with too much time on your hands, don't go there. Instead, make it easy for the application developer to implement whatever he needs on top of your authentication code.

With that introduction, here's what you need to do to enable authentication for your Spyce app:

  1. Invoke the spy:login (or spy:login_required) tag in the pages you wish to restrict to authenticated users
  2. Write a function that, given a username / password combination, returns a pickle-able identifier, or None; make this function the login_defaultvalidator in your Spyce config file. Like this one, used in the pyweboff demo (which does, as it happens, store user information in a database):
    def validator(login, password):
       user = db.users.selectone_by(name=login, password=password)
       if user:
           return user.id
       return None
    login_defaultvalidator = validator
    

That's it! Out of the box, Spyce handles the cookies, the login forms and handlers, all of the details you shouldn't have to worry about! The form rendering is done by active tags, which we talked about yesterday, so it's easy to customize when you get to that point. And if you want to restrict some pages to a subset of all users, you'd just write a validation function expressing those constraints, and pass that function to spy:login on those pages.

Here's a live example. (Login as spyce/spyce.)

If you'd like to compare this approach with other frameworks, here are some relevant links:

  • Ruby on Rails: "Don't start here until you 'get' it. Most of the authentication guides are broken or poorly documented." Good luck! Or maybe you'd like to buy our book!
  • Turbogears: (updated link) there is a lot to read here but Karl assures me that only a couple steps are actually necessary, besides the database setup.
  • Django: you have to do a lot of reading to find out what the real minimum work to do is, but I count 5 steps in 3 files.
  • I'll throw in ASP.NET for good measure: it's actually not too bad, but you're still on your own writing the login form and handler.

Tomorrow I'll talk about the Spyce db module, shown briefly above in the sample validation function. (And also mentioned in passing when I talked about Spyce handlers.)

Comments

Anonymous said…
Ouch. I resemble that "solve world hunger" remark. ;-)

http://www.plope.com/Members/chrism/decsec_proposal/view
Anonymous said…
"Spyce handles the cookies, the login forms and handlers, all of the details you shouldn't have to worry about!"

Smells like Rails scaffolding. Nice for a demo, impractical in production settings. I suspect that by the time your authentication in Spyce looks and acts the way you need it to, you've written as much code as you would have in Rails (which is still probably not very much).
Anonymous said…
Note that the TG page you linked to is a year old. The current steps to the same thing are:

1. Create a quickstart project, answer 'yes' to the identity prompt
2. stick '@identity.require(identity.in_group("admin"))' in front of a method
3. tg-admin sql create
4. There is no default user/passwd or groups, so you still have to create those.
Jonathan Ellis said…
zach: the value of sensible defaults is not necessarily that you end up writing less code for production -- although much of the Spyce auth defaults are a lot more likely to be useful in production than scaffolding -- but that it lowers the learning curve. Time wasted flailing around trying to understand the steps needed to get started is still time wasted.

karl: thanks for the update; if there is a good doc page for this I would be glad to update my link. (That was the best I could google.)
Anonymous said…
How does spyce authentication compare with zope?
Tim Lesher said…
karl: thanks for the update; if there is a good doc page for this I would be glad to update my link.

By sheer coincidence, I just updated the TG identity docs yesterday:

http://trac.turbogears.org/turbogears/wiki/IdentityManagement
Jonathan Ellis said…
Thanks, I updated the TG link.
Anonymous said…
The link posted regarding ASP.NET refers to ASP.NET 1.1; in ASP.NET 2.0, pre-built login controls are available which require no additional code. This is built on top of the provider model which allows different authentication backends

Popular posts from this blog

The Missing Piece in AI Coding: Automated Context Discovery

I recently switched tasks from writing the ColBERT Live! library and related benchmarking tools to authoring BM25 search for Cassandra . I was able to implement the former almost entirely with "coding in English" via Aider . That is: I gave the LLM tasks, in English, and it generated diffs for me that Aider applied to my source files. This made me easily 5x more productive vs writing code by hand, even with AI autocomplete like Copilot. It felt amazing! (Take a minute to check out this short thread on a real-life session with Aider , if you've never tried it.) Coming back to Cassandra, by contrast, felt like swimming through molasses. Doing everything by hand is tedious when you know that an LLM could do it faster if you could just structure the problem correctly for it. It felt like writing assembly without a compiler -- a useful skill in narrow situations, but mostly not a good use of human intelligence today. The key difference in these two sce...

Why PHP sucks

(July 8 2005) Apparently I got linked by some PHP sites, and while there were a few well-reasoned comments here I mostly just got people who only knew PHP reacting like I told them their firstborn was ugly. These people tended to give variants on one or more themes: All environments have warts, so PHP is no worse than anything else in this respect I can work around PHP's problems, ergo they are not really problems You aren't experienced enough in PHP to judge it yet As to the first, it is true that PHP is not alone in having warts. However, the lack of qualitative difference does not mean that the quantitative difference is insignificant. Similarly, problems can be worked around, but languages/environments designed by people with more foresight and, to put it bluntly, clue, simply don't make the kind of really boneheaded architecture mistakes that you can't help but run into on a daily baisis in PHP. Finally, as I noted in my original introduction, with PHP, ...

A week of Windows Subsystem for Linux

I first experimented with WSL2 as a daily development environment two years ago. Things were still pretty rough around the edges, especially with JetBrains' IDEs, and I ended up buying a dedicated Linux workstation so I wouldn't have to deal with the pain.  Unfortunately, the Linux box developed a heat management problem, and simultaneously I found myself needing a beefier GPU than it had for working on multi-vector encoding , so I decided to give WSL2 another try. Here's some of the highlights and lowlights. TLDR, it's working well enough that I'm probably going to continue using it as my primary development machine going forward. The Good NVIDIA CUDA drivers just work. I was blown away that I ran conda install cuda -c nvidia and it worked the first try. No farting around with Linux kernel header versions or arcane errors from nvidia-smi. It just worked, including with PyTorch. JetBrains products work a lot better now in remote development mod...