Friday, August 26, 2011
OpenTransact: Testing OAuth Scopes with Artifice and Cucumber
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.
Labels:
artifice,
cucumber,
oauth,
opentransact
Friday, May 20, 2011
OAuth Scopes with UMA Action URLs
In a recent South Park episode, Kyle is kidnapped and subjected to product prototyping (made of people) by employees of a large, cult-like tech company who explain that it is all justified: Kyle failed to read the complex terms and conditions he agreed to. Unfortunately, the risks of consenting to the agreement were not clear to Kyle.
There is a new hope. Earlier this week, Twitter announced more precise controls over permissions granted to third parties. Twitter wants to make the risks of consent more clear. Access to your direct messages should be on a need-to-know basis. Twitter says that by mid-June, when you grant a third-party permission to your twitter account, it will no longer be able to access your direct messages unless you have explicitly granted that particular type of access.
At IIW12, in the session New UMA solutions for scoped access and centralized AUTHZ, Eve Maler explained that part of the motivation is that we don't end up like rats at the feeder bar. One of the elements of User-Managed Access (UMA) that I found immediately useful was the requested scope format. For instance, here is one of three scopes I made for a financial service provider.
We have an identifier to reference the type of access requested, some text to display so that it is clear what type of access is being requested and an icon image for visual aid. For a simple one-time payment, we also need two dynamic values "asset" and "amount" which can be added as query parameters to the requested scope url.
Suppose an OAuth consumer (related to a merchant) wanted a customer to authorize a withdrawal of 3 bernal bucks from his financial service provider (FSP). We supply the requested scope url in the body.
It's not crazy to assume that the FSP will want to host its own scope definitions and that is the assumption made in the create_request_token method.
Regardless of the scope specified, the request token is not issued if the asset isn't specified or isn't supported by the FSP or if the json scope file doesn't exist on the FSP.

Here, we see that after receiving a request token associated with the requested scope, the merchant has redirected the customer to the authorization page where the scope definition is used to display what the customer is being asked to authorize. The name of the type of scope is displayed with a light yellow background.
In RSpec and Cancan Authorization for Intentional Economics, a process of using RSpec examples to drive the rules for authorizing a payment in the Cancan Ability class was described. Using the same process, we create 4 new specs that produce two new lines of code in the ruleset: if it is an OAuth payment, we pass the payment amount to authorized_for? on the access token. These are the two lines added to the Ability class in the checkin.
Here is authorized_for?
Although this seems like progress, there's plenty of room for improvement and plenty more that needs to be done. I have only implemented the single payment scope. How will recurring payment scope work? What if multiple scopes are specified? If this is interesting to you, let's collaborate. One place to do this is on the OpenTransact mailing list. Another way is to work on it at the next Internet Identity Workshop (IIW). At the most recent one, I facilitated a session called Beautiful Payment Systems w/OAuth.

Finally, if you're in Austin on June 1st, come to the EFF-Austin meeting where we'll be talking about What's up with the Internet Identity Movement?.
There is a new hope. Earlier this week, Twitter announced more precise controls over permissions granted to third parties. Twitter wants to make the risks of consent more clear. Access to your direct messages should be on a need-to-know basis. Twitter says that by mid-June, when you grant a third-party permission to your twitter account, it will no longer be able to access your direct messages unless you have explicitly granted that particular type of access.
At IIW12, in the session New UMA solutions for scoped access and centralized AUTHZ, Eve Maler explained that part of the motivation is that we don't end up like rats at the feeder bar. One of the elements of User-Managed Access (UMA) that I found immediately useful was the requested scope format. For instance, here is one of three scopes I made for a financial service provider.
We have an identifier to reference the type of access requested, some text to display so that it is clear what type of access is being requested and an icon image for visual aid. For a simple one-time payment, we also need two dynamic values "asset" and "amount" which can be added as query parameters to the requested scope url.
Suppose an OAuth consumer (related to a merchant) wanted a customer to authorize a withdrawal of 3 bernal bucks from his financial service provider (FSP). We supply the requested scope url in the body.
It's not crazy to assume that the FSP will want to host its own scope definitions and that is the assumption made in the create_request_token method.
Regardless of the scope specified, the request token is not issued if the asset isn't specified or isn't supported by the FSP or if the json scope file doesn't exist on the FSP.

Here, we see that after receiving a request token associated with the requested scope, the merchant has redirected the customer to the authorization page where the scope definition is used to display what the customer is being asked to authorize. The name of the type of scope is displayed with a light yellow background.
In RSpec and Cancan Authorization for Intentional Economics, a process of using RSpec examples to drive the rules for authorizing a payment in the Cancan Ability class was described. Using the same process, we create 4 new specs that produce two new lines of code in the ruleset: if it is an OAuth payment, we pass the payment amount to authorized_for? on the access token. These are the two lines added to the Ability class in the checkin.
Here is authorized_for?
Although this seems like progress, there's plenty of room for improvement and plenty more that needs to be done. I have only implemented the single payment scope. How will recurring payment scope work? What if multiple scopes are specified? If this is interesting to you, let's collaborate. One place to do this is on the OpenTransact mailing list. Another way is to work on it at the next Internet Identity Workshop (IIW). At the most recent one, I facilitated a session called Beautiful Payment Systems w/OAuth.

Finally, if you're in Austin on June 1st, come to the EFF-Austin meeting where we'll be talking about What's up with the Internet Identity Movement?.
Labels:
iiw,
oauth,
opentransact,
payments,
uma
Friday, February 25, 2011
What's new with oscurrency
See this video on blip.tv.
This is a 10 minute explanation of the feature changes in the groupy branch. The motivation and design was discussed in RSpec And CanCan Authorization for Intentional Economics three months ago.
Labels:
complementarycurrency,
insoshi,
oscurrency,
screencast
Monday, January 31, 2011
Thursday, November 25, 2010
RSpec and CanCan Authorization for Intentional Economics
Not long after moving the Austin Time Exchange to Ruby on Rails, we started receiving requests for a groups feature since some local groups were interested in having their own currency but did not want to run their own instance of the software and their members were already on the existing system.
Since we're a fork of insoshi, merging the groups feature from another fork is easy. Add some code to make simple payments per-group...Boom! Done.
As you might imagine, that half-baked effort didn't work out.
The right answer is functional equivalency with the original currency: every currency has the same user interface as the original one. This means every currency can be associated with requests and offers. It means every currency has the same level of administrative support, graphs and even OpenTransact support. Also, each group wants to define its own rules for its currency with different roles.
That sounds like it could be complicated. Fortunately, Ryan Bates has created a simple authorization gem called CanCan which for our purposes can help us create and maintain rules for a number of currencies. However, before we start adding rules whilly-nilly, who and what process is responsible for managing the rules?
The right answer is not the software developer. Of course, the rules should be designed by the people organizing the currency. And, in the spirit of agile programming and/or agile banking, it helps if we start out with the bare minimum amount of rules. As participation increases, new contingencies will arise and the system will need to accommodate them with new rules or protocols agreed upon by the interested parties.
To accommodate these new contingencies, non-programmers might like to describe new rules or behavior scenarios in plain English with Cucumber. These plain English scenarios can be easily translated into Ruby RSpec code examples. For instance, a simple Cucumber scenario was demonstrated in "Using Insoshi to Support Community Currencies" at LSRC 2009 to show how trivial it is to design a payment system without charging heavy handed overdraft fees since banks were collecting $38 billion in overdraft fees that year. Cucumber is very useful but it is not essential.
What seems to be essential is for the programmer to write RSpec examples to simulate the new contingencies identified by the interested parties. An RSpec example ends with an expectation which will fail until we adapt the CanCan authorization rules to accommodate it.
Suppose we started a community currency without credit limits. This works for some period of time until an account holder makes one or more payments of a substantial amount without reciprocating in a reasonable amount of time.
Now we have a new contingency to address and we will simulate it with RSpec and it will fail because there are no rules in place to make the software behave as expected when the newly identified contingency occurs. Thankfully, the programmer is lazy and doesn't prematurely write any RSpec code. Instead, the programmer grabs one or more jelly-filled doughnuts while the interested parties agree on the rules to accommodate the contingency.
They decide a configurable per-member credit limit would be a simple general solution and would avoid hard-coded limits in the code. So, how would we simulate this contingency in an RSpec example? Let's focus on the most relevant details of the spec.
First, we say the amount of the exchange object @e is 1.0 units and the payer is the person object @p2. All activity related to exchanges now occur in the context of a group. Therefore, the roles (and rights associated therewith) are assigned to the @membership object rather than directly to the person. In this case, "individual" is the only role the payer is assigned. Another meaningful membership role is "admin" and there can be several admins per group.
Finally, we fetch the account, give it a balance of 0 and a credit limit of 0.5 for this example. Therefore, we should expect the payment to fail because the magnitude of the payment exceeds the sum of the balance and the credit limit. However, if there are no rules defined, the payment will succeed and this example will fail. To fix it, we add the following rule to the Ability class.
The authorized? method is called on the payer's account to see if the payment is allowed. If the credit limit is nil, the payment is allowed. Otherwise, it is allowed if the magnitude of the payment is less than or equal to the sum of the payer's account balance and credit limit as shown in the Account class.
Now, the RSpec example passes and the programmer can tell the interested parties that their policy is now implemented until the next time a new contingency arises.
Since we're a fork of insoshi, merging the groups feature from another fork is easy. Add some code to make simple payments per-group...Boom! Done.
As you might imagine, that half-baked effort didn't work out.
The right answer is functional equivalency with the original currency: every currency has the same user interface as the original one. This means every currency can be associated with requests and offers. It means every currency has the same level of administrative support, graphs and even OpenTransact support. Also, each group wants to define its own rules for its currency with different roles.
That sounds like it could be complicated. Fortunately, Ryan Bates has created a simple authorization gem called CanCan which for our purposes can help us create and maintain rules for a number of currencies. However, before we start adding rules whilly-nilly, who and what process is responsible for managing the rules?
The right answer is not the software developer. Of course, the rules should be designed by the people organizing the currency. And, in the spirit of agile programming and/or agile banking, it helps if we start out with the bare minimum amount of rules. As participation increases, new contingencies will arise and the system will need to accommodate them with new rules or protocols agreed upon by the interested parties.
To accommodate these new contingencies, non-programmers might like to describe new rules or behavior scenarios in plain English with Cucumber. These plain English scenarios can be easily translated into Ruby RSpec code examples. For instance, a simple Cucumber scenario was demonstrated in "Using Insoshi to Support Community Currencies" at LSRC 2009 to show how trivial it is to design a payment system without charging heavy handed overdraft fees since banks were collecting $38 billion in overdraft fees that year. Cucumber is very useful but it is not essential.
What seems to be essential is for the programmer to write RSpec examples to simulate the new contingencies identified by the interested parties. An RSpec example ends with an expectation which will fail until we adapt the CanCan authorization rules to accommodate it.
Suppose we started a community currency without credit limits. This works for some period of time until an account holder makes one or more payments of a substantial amount without reciprocating in a reasonable amount of time.
Now we have a new contingency to address and we will simulate it with RSpec and it will fail because there are no rules in place to make the software behave as expected when the newly identified contingency occurs. Thankfully, the programmer is lazy and doesn't prematurely write any RSpec code. Instead, the programmer grabs one or more jelly-filled doughnuts while the interested parties agree on the rules to accommodate the contingency.
They decide a configurable per-member credit limit would be a simple general solution and would avoid hard-coded limits in the code. So, how would we simulate this contingency in an RSpec example? Let's focus on the most relevant details of the spec.
First, we say the amount of the exchange object @e is 1.0 units and the payer is the person object @p2. All activity related to exchanges now occur in the context of a group. Therefore, the roles (and rights associated therewith) are assigned to the @membership object rather than directly to the person. In this case, "individual" is the only role the payer is assigned. Another meaningful membership role is "admin" and there can be several admins per group.
Finally, we fetch the account, give it a balance of 0 and a credit limit of 0.5 for this example. Therefore, we should expect the payment to fail because the magnitude of the payment exceeds the sum of the balance and the credit limit. However, if there are no rules defined, the payment will succeed and this example will fail. To fix it, we add the following rule to the Ability class.
The authorized? method is called on the payer's account to see if the payment is allowed. If the credit limit is nil, the payment is allowed. Otherwise, it is allowed if the magnitude of the payment is less than or equal to the sum of the payer's account balance and credit limit as shown in the Account class.
Now, the RSpec example passes and the programmer can tell the interested parties that their policy is now implemented until the next time a new contingency arises.
Labels:
agilebanking,
cancan,
insoshi,
intentionaleconomics,
rspec
Tuesday, June 22, 2010
Wednesday, June 16, 2010
A simpler alternative to rel-payment
The previous screencast may have tried to use too much technology to enable user-centric simple web payments.
After looking around some, it occurred to me that the rel-payment microformat is not sweeping the world wide web. Using the Internet Archives, I found a blog post from July 2005 that announced support for rel-payment on blip.tv. I'm guessing not many people used this before it was abandoned.
An alternative to rel-payment is to simply use a convention. For instance, the path /blog is a convention to quickly find the blog for a site. On Twitter, this would normally represent the person with the Twitter handle "blog" but Twitter follows the convention and redirects to blog.twitter.com.
Similarly, url paths that began with /transacts (or something similar) would be a lot more user friendly than using a microformat. Now we can use a simpler bookmarklet and achieve the same flexibility as rel-payment. A convention like this would be compatible with OpenTransact.
After looking around some, it occurred to me that the rel-payment microformat is not sweeping the world wide web. Using the Internet Archives, I found a blog post from July 2005 that announced support for rel-payment on blip.tv. I'm guessing not many people used this before it was abandoned.
An alternative to rel-payment is to simply use a convention. For instance, the path /blog is a convention to quickly find the blog for a site. On Twitter, this would normally represent the person with the Twitter handle "blog" but Twitter follows the convention and redirects to blog.twitter.com.
Similarly, url paths that began with /transacts (or something similar) would be a lot more user friendly than using a microformat. Now we can use a simpler bookmarklet and achieve the same flexibility as rel-payment. A convention like this would be compatible with OpenTransact.
Labels:
microformats,
opentransact,
payments,
rel-payment
Subscribe to:
Posts (Atom)