Smart programming isn’t always about the hard stuff. Sometimes, it’s just doing the simple, but clever, things. Here’s a tiny example.
I spent a few hours this weekend implementing the Basecamp API into BugSpray, our home-grown, web-based bug tracking tool. This lets Basecamp users import a project, companies, and users from Basecamp over to BugSpray.
To access any call to the API, four things must be known:
- The URL domain to someone’s Basecamp project.
- A valid Basecamp user name.
- A valid Basecamp password.
- Whether the project is running under SSL (http v. https).
From an interface perspective, this seems pretty straightforward. Three text fields, one set of “http/https” radio buttons, and off-you-go! But, that user experience is rather odd.
The obnoxious bit is, you need to know whether you are indeed running Basecamp under SSL. I’d imagine most users don’t know. The instructions “Login to your Basecamp account and see if the URL in your browser has http:// or https:// in front of it” sounds kinda-like-not-a-great-time.
Instead, I simplified the UI to this:
When a user passes BugSpray the info, the code makes two calls. First, it tries calling the URL with login credentials under
httphttps. If it gets through, yippee. If it fails, it tries calling the URL with login credentials under httpshttp. If it gets through, yippee. If it fails, then it notifies the user that the login credentials are probably wrong. *(see addendum)
The SSL issue is still there, it’s just a business logic issue rather than a user experience issue. Instead of asking the user, “Is your Basecamp site under SSL?” it just tries both. The slight performance hit of the potential extra call is certainly worth the user experience gain of not having to think about whether you’re Aych-Tee-Tee-Pee-Essin’ it. And, once the code successfully connects to the API the first time, we already know the answer to the https question for that user. Subsequent calls to the API don’t have to run through the double try-catch block.
Before you go filing this post under the “ho hum” programming tip of the day, just remember all the tiny little clever things you can do under the covers to make less interface.
* An addendum regarding authentication security
In my original post, I stated that I first test the Basecamp call using http, and if it fails, I use https. A commenter correctly pointed out this is a horrible idea since those who have SSL on will have their credentials initially sent over http under clear text (technically base64-encoded because the authorization happens over basic authentication).
Here’s how I’ve fixed this issue.
Now, I call https first, and if it fails, I call http. Now, a Basecamp account under SSL will successfully login without worry of sending credentials over clear text since the https call attempt happens first.
But, there’s still a loophole. Suppose the credentials were typed incorrectly. Then, the https call will fail and the http call will be attempted. But, if the Basecamp account is, indeed, under SSL, we’re sending credentials (albeit the incorrect ones) over http. That’s not good enough security.
To stymie the loophole, I now check the error response on the initial https attempt. If the error is an unauthorized error (401), I know that the credentials themselves are wrong (regardless of whether https or http is the correct protocol since the server authorization occurs before the page is requested). In this case, I don’t attempt the http call at all since the credentials are wrong.
Otherwise, I check if the error is a protocol violation exception. This means that the credentials are correct, but the protocol is wrong. Only then do I attempt the call under http.
A bit more thinking then initially anticipated, but now we still get to keep it out of the UI without the security issue.