As part of a personal project, I have been working on an OpenID Provider written in Sinatra.
The idea is to make it ridiculously easy to set up an openid provider within a rack middleware stack.
It’s just a single sinatra app without any tests using code I cribbed from the example rails implementation in ruby-openid. But, I intend on rewriting it once I get a better feel for how it should go.
The problem I face is a matter of interface, specifically application programming interface. I want it to be simple to use. But that is alittle complicated underneath.
Today I read The Little Manual of API Design(pdf), which made me think about my approach to building things in, I think, a good way. It talks about the goals of building a good API and boils it down to five things.
- Easy to learn and memorize
- Leads to readable code
- Hard to misuse
- Easy to extend
For my app, complete is pretty easy. I’ve boiled the interface down to two main things:
- OpenID Store
First, for an openid app, you need an openid store to put all the associations, nonces etc.
Then, the meaty bit, the users and their identities. The stuff we are serving up. My current thought is to have one of the app’s parameters be a lambda or Proc that returns the current user, or nil when called with the request.env. So that using it would look somewhat like this.
It’s kind of ugly, but I like it better than some of my other options. One other way I could get the user to the app would be to use rack request hash. I could have users put the user object in the request env before the OpenID provider gets it and tell the provider where to look. But the problem with that is that I would need to add another middleware layer that added the user to the environment. That would look something like this:
Maybe that would be better.
Ultimately I just need to pick something and run with it.
The thing I wonder about though, is what is the most idomatic way of doing this. Using the most rubyish, most Rack like interface would make it easier to learn and memorize.