Usernames & Passwords
As I chronicled in a previous post, I recently wrote an application in Ruby that took advantage of OmniAuth for all of it’s user authentication. As I worked on the application, I decided that I would no longer write an application that did not use OAuth or OpenId to sign-up & log in.
The fact that LinkedIn (as well as others) lost their passwords this summer, combined with Jeff Atwood’s blog post about not needing another username and password made me realize that I really didn’t want to be in the username & password management game. I’m a single developer working on toy sites for fun. I don’t really want to worry that I might not have secured my login table well enough. Instead, I want to write the app that I’m writing.
A Couple Spikes
I really wanted to play with OpenAuth because I still write most of my code in .NET, so I can’t use OmniAuth for a majority of my work. As I sat down I noticed that there was a NuGet, so I installed that. As I looked around for how to get started, the first thing I found was some code on DNOA’s page. I tried messing with it for a bit but quickly realized that this was just a general guide. What I really wanted was to hook up Faebook and Twitter. I figure most people use one of those two services. As a result I looked around and found a blog that looked pretty helpful. Still it was a good chunk of code, and it only solved the problem for a single provider.
In contrast to DNOA, OmniAuth is stupidly simple. In fact, in 18 lines of code, I was able to use Facebook and Twitter, and additionally store the user’s name in my database.
Maybe the problem is that OmniAuth is a Ruby Gem and DNOA is .NET. Perhaps it’s not possible to write concise code in .NET.
Except that it is. Simple.Data is a ORM that is similar to ActiveRecord in Ruby. I installed the NuGet package, added a connection string to my Web.Config file and issued the following lines. And with this code snippet I was able to display records out to a View.
Now one thing to note here, the class Media is not needed to pull the data from the database. Simple.Data uses dynamic objects, and by simply specifying the name Media it knows what table to use.
All told, I spent about 5-10 minutes total getting up and running with Simple.Data and that includes creating a new project etc.
The contrast between these projects is startling to me. One thing I don’t want to do when I bring down a package is spend a lot of time configuring it. To me, it’s like having this interface:
This interface expects the consumer to make each call, and to do so in the right order and at the right time.
However this interface simply expects you to tell the car to start and let the implementation handle the details.
What I Want to Do
I want to write code. I enjoy code. I enjoy it enough that I just spent the past hour on a Saturday afternoon playing with these packages and writing spikes and working on this blog.
But what I hate is reinventing the wheel.
Why does my project need to use dependencies that I have to spend time configuring? The longer I spend time configuring the more likely I figure a different way around the problem. For example, if I have to have a bunch of code for each authentication provider I want to use, I’m more likely to just write my own Users table with a salted & hashed password, and make my users remember one more username & password combination.
In the end, I lose because I spend more time writing database tables, queries and code to make sure I lock your password after so many failed tries, that I have a way to reset your password, and make sure I don’t have a way to see your plaintext password etc.
But I’m not the only one. My end users (if I ever have any) will lose as well. They’ll go through the dread of password management. They’ll miss out on the joy of being to use your Google account to sign-in to another site. They’ll miss the added security that a company like Google can provide, and a single, shade-tree developer can’t. They’ll lose because ultimately they’ll probably pick the same password for my site as they do for every other site on the web (and it’s probably their email password.) Which means if some other site gets hacked, there’s a very strong chance that my users’ passwords are all owned, and if they want to change them, they’ll have to visit 50 or 100 different sites and go through that flow. Simply put, that’s too much work, so they won’t change their passwords.
Finally, the community loses. Every time someone installs a package that takes time to configure, they’re spending time configuring a package and not shipping code. I’m not coming to your site for it’s data access layer, or for it’s user management. I’m coming to your site for the unique service that it provides. But you’ve spent too much time writing boilerplate code and you ran out of steam before you shipped your site. Now the community doesn’t have the next great idea.
Solve the Right Problem
The goal of new software should be to solve a problem in as few lines of code as possible, and with as little attention to the periphery as possible. When you sit down to write a new script, website, or application you have a problem you want to solve. Wouldn’t it be great if you could focus all your attention on that problem?