iiw / oauth / opentransact / payments / uma

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.

"name":"single payment",

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.

def create_request_token(params={})
if params[:scope]
scope_uri = URI.parse(params[:scope])
# XXX ignoring host:port and assuming it's our host:port
filepath = RAILS_ROOT + '/public' + scope_uri.path
if File.exist?(filepath)
# valid asset is required
asset = CGI::parse(scope_uri.query)['asset'][0]
unless asset.blank?
group = Group.find_by_asset(asset)
RequestToken.create(:client_application => self,
:scope => params[:scope],
:group_id => group.id,
:callback_url=>self.token_callback_url) unless group.nil?
logger.info "XXX create_request_token - file not found: #{scope_uri.path}"

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.

<%= check_box_tag 'authorize' %> authorize <span id="scope-action"><%= @token.action_name %></span> <img src="<%= @token.action_icon_uri %>"> of <%= @token.amount %> <%= @token.asset %>

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.

unless (access_token.nil? || access_token.authorized_for?(exchange.amount))
view raw ability.rb hosted with ❤ by GitHub

Here is authorized_for?

def authorized_for?(requested_amount)
['single_payment','recurring_payment'].include?(action_id) && requested_amount <= amount.to_f && !invalidated?
view raw OauthToken.rb hosted with ❤ by GitHub

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.

beautiful payments with 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?.


3 thoughts on “OAuth Scopes with UMA Action URLs

  1. Hi, so what exactly does the scope string look like? Is this the first time it's being used as a URI? I'm working at Twilio trying to develop structured/configurable scopes for OAuth.

  2. hi jeff,

    the 2nd gist included the scope string:


    i've noticed a number of folks, including google, assign the scope to a url like this. usually, there's no need for query string parameters, but i'm using them to specify amount and asset since those are dynamic.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s