In a previous article I talked about adding a profile to OAuth WRAP that would enable users to ask for or grant permissions to each other. In this article I show that an OAuth WRAP profile to handle granting permissions only needs two request/response pairs. I then show that an OAuth WRAP profile to handle asking for permissions only needs one additional exchange.
1.1 How did Joe know to tell Yahoo that Mike keeps his calendar at Live?
1.2 What if Mike has multiple calendar services?
1.3 How did Live know the requests came from Yahoo?
1.4 How did Live know what permission Yahoo was asking for?
1.5 How did Live know that email@example.com was the one who asked Yahoo to make the request?
1.6 How does Joe remove permission for Mike to see his free/busy time?
2 Asking for permission - extending the free/busy time example
2.1 How does Live know that the notification in 7 is a response to the request in 4?
In this example the user firstname.lastname@example.org, who uses the Yahoo Calendar service, wants to give permission to email@example.com, who uses the Live calendar service, to see Joe’s free/busy time. Mike will then login to Live calendar service, accept Joe’s permission grant and then schedule a meeting with Joe where Joe’s free/busy time will be displayed to Mike.
In looking at the sequence diagram it’s worth noting that the entire proposal comes down to creating a profile for OAuth WRAP that introduces request/response pairs 2/2R and 3/3R. That’s it.
7/7R are already defined by OAuth WRAP, 8/8R are defined by other protocols like CalDAV and everything else occurs outside of any standard context. So while a lot is going on the amount we have to add to enable interoperability is quite small. The sequence diagram does, however, bring up some interesting issues that I explore below.
One can imagine that Joe went into his Yahoo address book and clicked on a button saying "Give Mike permission to see my free/busy time". Yahoo knows that Mike’s e-mail address is firstname.lastname@example.org but how does Yahoo figure out where Mike keeps his calendar? I don’t think it will ever make sense to ask a customer where their friend’s calendar is because the customer might either not know or have the wrong answer. For privacy reasons Yahoo in many cases can’t tell the customer if their choice is right or wrong. So my suspicion is that Yahoo will need to find out for itself where the calendar is for the associated e-mail address.
In the long term there will exist discovery services that given an identifier like an e-mail address can return information such as where the owner’s calendar(s) is(are). I hope to discuss my ideas around that problem in another article. But in the short term my guess is that services will just have to ask their partners. In some cases, where there is very deep trust (or very long legal agreements and enough money to sue if things go bad) services will just bulk upload lists of who they host calendars for to their partners and update those lists on a regular basis. In other cases a service will have to send a protocol request to their partners asking "Do you host X’s calendar?" This request/response pair is shown in 2/2R in the diagram.
This means that a service like Yahoo who is probably partnered with a large number of other services will either have to check its local database of bulk uploads and/or make queries to partner services in order to figure out where a user’s calendar is. This won’t scale but it’s probably o.k. in the short term until the discovery service infrastructure is up and running.
We can easily imagine that Mike has a personal calendar that he keeps at Live and a work calendar that is run from his business. One can also imagine that both Live and Mike’s business are federated with Yahoo. So when Yahoo goes out looking for where Mike’s calendar is they are likely to find not one, but two calendars. In fact it could be even more complicated. Let’s say that before deciding that Live was his primary personal calendar service Mike created accounts with a few other calendar services. He has since abandoned those calendars but he used the same e-mail address, email@example.com, to create all the calendar accounts. If Yahoo is federated/registered with those calendaring services then Yahoo could find itself having numerous potential calendaring services who all say they represent firstname.lastname@example.org and at least two of them are even right!
One suspects that the only sane way to handle this for now is for Yahoo to just find all the calendar services who have an entry for Mike and send the permission request to all of them. Most likely Mike will probably accept Joe’s request for his Live calendar and reject Joe’s request for his work calendar. But just as likely Joe might accept both requests and that’s probably a good thing. In the end Joe needs to know when Mike is busy, if Mike hasn’t federated his two calendars together then the only way to have an accurate picture of Mike’s activities is to get free/busy time from both calendars. Yahoo would then pull the data from both and show Joe a unified free/busy time view for Mike.
In the sequence diagram Yahoo sends two requests to Live, one to find out if Live has Mike’s calendar (2/2R) and another to notify Live that Joe has granted Mike permission to see Joe’s free/busy time (3/3R). In the short run my guess is that services like Live will require services that want to talk to it to register and as part of that registration the requesting service, in this case Yahoo, will get what OAuth WRAP calls a client id and a client secret. Yahoo will include those values in its requests and so authenticate itself to Live.
In the long run I’d actually like to see an ad-hoc system that lets two services exchange requests without a previous relationship. In a future blog post I hope to explain how this could be made to work.
My guess is that requests 2/2R and 3/3R will use the OAuth WRAP request/response format which is just HTML Forms. So we would expect that request 3 will include some indicator of what permission or permissions are being asked for. This is nothing new in and of itself, OAuth handles this all the time today. What’s unfortunate is that the way OAuth typically handles this is that every service posts its own unique list of permissions it handles and anyone wanting to work with that service has to work with that service’s permissions. This makes economies of scale hard to come by. Also the permissioning part of the game is the easy part, all things considered. The hard work comes in request/response pair 8/8R where the free/busy time is retrieved.
My hope is that folks in communities like calendaring, document sharing, etc. will get together and create packages of both claims for use with OAuth WRAP as well as details on what protocols to use along with those permissions. But one step at a time.
The real question is probably more subtle - how did Yahoo know its user was the legitimate owner of email@example.com? It turns out that there are a non-trivial number of ways that Yahoo could have validated Joe’s identify. But the two typical approaches are:
- E-mail Validation
- Joe could have created an account with Yahoo using the e-mail address ’firstname.lastname@example.org’ and Yahoo e-mailed a confirmation message to that address that Joe then had to click on and then log in again. This provides reasonable proof that the user owns the e-mail address ’email@example.com’.
- WS-Federation, SAML-P or OpenID
- Yahoo could have a trusted federation with Google and so accept Google’s attestations of Joe’s identity.
My guess is that initially Live will require that Yahoo disclose the mechanism used to authenticate the user’s identity. Live will then decide how to proceed based on context and the authentication mechanism. Yahoo’s disclosure could be as simple as a field in the permission notification request that says "auth_type = EmailValidation" or what have you. Live would then trust that Yahoo was being honest about the value it put in the auth_type claim.
There are some edge case scenarios where a service that is giving permission might not know the public identity of the person granting the permission. I have some ideas on how to solve that problem but they are fairly complex so I’ll save them for another day.
In message 1R Yahoo let Joe know that it was able to deliver the notification request, although Yahoo won’t tell Joe where the request was sent. But Joe won’t ever know if Mike actually accepted the request since, to be blunt, it’s none of Joe’s business. Joe can offer the permission but that’s it. But what is Joe’s business is if Joe changes his mind and wants to withdraw permission he needs a way to do that.
Thankfully removing permissions can be handled completely outside of the protocol. Joe needs to let Yahoo know that he no longer wants Mike to be able to see his free/busy time and at that point Yahoo will remove Mike’s permission from its permission store. It’s worth remembering that the way OAuth WRAP works every time a particular user gives a particular permission to another particular user a refresh token is issued. That token is unique to the combination of Source User/Source Service/Destination User/Destination Service/Permission. In our case that is firstname.lastname@example.org/Yahoo Calendaring Serviceemail@example.com/Live Calendaring Service/See Free Busy time. So the next time that Live comes with the refresh token (request 7) to get a new access token (7R) the request will be denied since Joe had Yahoo remove the permission.
In this version of the example Mike asks for permission to see Joe’s free busy time. By way of reference, in the previous example Joe pre-emptively granted Mike permission, Mike hadn’t asked. The scenario is that Mike creates a meeting in the Live calendar service and invites Joe. Live sees that Mike doesn’t have Joe’s free/busy time and prompts Mike if he would like to ask Joe to see his free/busy time. Mike responds in the affirmative. Yahoo queries the services it knows to see if anyone owns Joe’s calendar and gets a positive response from Yahoo. So Live asks Yahoo to forward a free/busy time view request to Joe from Mike. Mike logs in, sees the request and approves it. At that point the rest of the flow is essentially identical to the previous example. Yahoo notifies Live that Joe has granted the permission and Live uses that permission to show Joe’s free/busy time to Mike.
In comparing this example to the previous example only one new request/response pair is added, 4/4R. All the other request/response pairs that deal with anything that needs to be standardized are already defined in the previous example. And even 4/4R is a variant on 7/7R.
A variant on this scenario would be to have Mike both request Joe’s free/busy time while simultaneously granting Joe the right to see Mike’s free/busy time. But I suspect these should be modeled as two separate interactions.
Strictly speaking correlation isn’t necessary since Live should be able to recognize that it asked for specific permission from Yahoo for a specific user and if it later gets that permission then matching the request with the response shouldn’t be a big deal. One can imagine Live keeping a table where the index is on a set of columns that specify what service the request went to, what user at the server it was targeted at, what permission was asked for and what local user made the request. Correlating 7 with 4 then becomes a simple task of looking up the appropriate entry in the table. If there is an entry then this is a response to a previous permission request and if there isn’t an entry then this is the previous example.
But if we really want we can just include a correlation ID from Live in request 4 that Yahoo is expected to include in 7 because 7 was generated in response to 4. If 7 was generated on its own (e.g. the previous example) then no correlation ID would be present.