In this screencast, we’ll improve the code introduced in the previous post OAuth Scopes with UMA Action URLs with the help of our friends Artifice and Cucumber.
Calls to Net::HTTP can be intercepted by Artifice and sent to your rack application instead of the network. If you are developing an OAuth provider, Artifice makes testing the api a lot easier. Since the OAuth ruby gem uses Net::HTTP, we can wrap Artifice blocks around our client calls in tests and Artifice will intercept the calls and route them to our Rails app.
Before jumping headfirst into the screencast, it might be worth reviewing some fundamentals.
An OAuth mantra that seems to have emerged is “Get a token. Use a token.” The cucumber tests we’ll be seeing in this screencast are concerned with using the access token. If you are familiar with OAuth, you know that possession of an access token allows a machine to impersonate a person on another site but with limited capabilities authorized by the person. OAuth calls a capability a scope. Without the use of OAuth scopes, OAuth’s vision of being the “valet key for the web” cannot be realized.
Unfortunately, the term scope seems unnecessarily general. If a provider is just using so-called scopes to restrict a token for a particular type of service (e.g. YouTube vs. Google Photos), then the term scope makes sense in that passive context. But, if we’re talking about different actions a token can perform, capability seems to be a better term. In the screencast, I’ll use the word capability for the purpose of thinking about the problems we’re trying to address.
As the risk of unauthorized use of an action increases, many customers will require more control over these capabilities, especially if the trustworthiness of the third party receiving an access token is questionable. We have already seen this with Twitter’s response to customers wanting finer control over delegated access to private messages.
It is instructive to consider how Twitter patiently allowed the scopes demanded by their customers to emerge. We can imagine a hypothesis was constructed: “There are no customers who care about finer grained control of access to their account.” Then, a number of data points were collected that refuted that hypothesis. This data allowed a business case to be made for adding a little complexity to the user interface to support new Twitter OAuth capabilities.
This is a desirable process to follow as long as the data points don’t sting. Testing the hypothesis “No bees will sting me if I reach my hand over here” is not recommended. We shouldn’t be surprised if we receive similar results by testing the hypothesis “No banking customers care about finer grained control of access to their account.”
This doesn’t mean we should start defining capabilities willy-nilly. It just means we probably shouldn’t unleash a financial service provider without considering how customers might be blindsided by unnecessary third-party access. Does a third-party doing a withdrawal need access to a customer’s payment history? Of course not. So, already we know there should be at least two scopes, one for making withdrawals and one for viewing transaction history (which might be used by an account aggregator like Yodlee).
What about a single payment? Are there cases where a customer would want to give a token for a one-time payment. Of course. Banking sites are compromised much more frequently than they disclose. Sometimes, compromises are obvious like the recent hack of the Bitcoin exchange site Mt. Gox. Why give sites carte-blanche over your account when you just want to authorize a single payment?
A useful abstraction we’ve been discussing on the OpenTransact mailing list is the wallet. This is a list of the asset classes an account holder is keeping and the balance for each. Much like viewing a transaction history, viewing an account holder’s wallet deserves its own capability.