Neustar April 15th, 2009

Walkthrough of a typical XRD/OpenID/OAuth use case

There is currently no provisioning mechanism for a service to insert itself in a user's XRD file.

Is it possible for a Consumer to find another service? Yes but only in a public way, because it's in the XRDS.

  1. The user visits a site he's never been before and gives his OpenID
  2. The site discovers where the user's OP is. To do so, it sends GET on the OpenID ID with accept:app/xrds+xml. There are 3 variants of this discovery step:
    1. HTTP header that tells the location of the XRDS document
    2. Returning the XRDS document itself
    3. Get HTML that is to be parse the head for looking for the tag that tells where the XRDS document is.
  3. The site parse the document to find the OP. The TYPE element defines whether the service supports OpenID2 or if it supports AX etc.This dicovery process is chainable so that a service can then retrieve the XRDS of a service that will describe things like the fact that it supports OAuth etc. This chaining needs to be trusted (need to sign etc.).There are 2 modes of thinking with respect to an XRD:
    1. My XRDS has all the endpoints in there for all my services
    2. All supported extensions are pointers at the service- those pointers are where the real OAuth pointer (for instance) can be requested.
  4. Do an XRD discovery on, say, twitter.com. The result will contain, for instance, links to the OAuth endpoints (request token, authorize etc.)

Some privacy concerns with the XRD model:

  • When the site I visit needs to access another service (e.g. my calendar service), it retrieves my XRDS and as a result gets information on all the services I use
  • Multiple identities: I want to find your calendar to put in an entry and, doing so, I can see all your services.
  • I want to show some services I use to a set of people only

How do you protect this? We should enable identity-restricted metadata discovery. This amounts to changing the result of the XRD request based on identity and sign it on the fly (if needed).

Another issue: all those operations are front channel so that this becomes very painful for the user as soon as we get passed the 1-site interaction level.

Potential areas of investigation

  1. Having a way for the OP to generate an OAuth access token for all the sites that do accept that OP (e.g. Yahoo! would generate an OAuth token, about the user, for Hiking.com to present it to another site like Twitter)?
  2. Using the interaction service to get consent to generate the token.
  3. Having a DS co-located with the OP that can generate tokens, we have an opportunity to apply policies there.
  4. Federation might be a contributing factor in the authorization decision too (e.g. “''anyone I federated with can use my twitter service''” or “''because I federated Hiking.com with my Yahoo! Account, it gets some visibility into my services''”)

Since OAuth has no federation (no identifier mapping – the token carries the map) and there is no standardized structure for the token we currently cannot support use cases as above.

Dealing with multi-party identities is about 2 things:

  • How do I express multiple identities in a message
  • How do I get those identities in a privacy-preserving way

Although ID-WSF addresses both, will the OAuth/OpenID community be interested in the latter?

Oauth Extension: Supporting Identity Tokens

Use case

Alice is planning a hike and wants to check the availability of her hiking friends.

Assumptions

  1. Alice uses Friends.com as a social network.
  2. Alice uses Hike.com to plan her hikes.
  3. Alice's friends use different calendar services. Bob uses Event.com as well as a Portable Contact site (PoCo)
  4. Alice's friends have specified access control rules (e.g. anyone in my hiking friends group etc.) over their calendars in terms of their own (different) social networks

The illustration gives an overview of the flow of messages. The steps are as follows:

  1. Alice visits Hike.com to check whether her friends are available for a hike
  2. Hike.com retrieves Alice's list of friends at her PoCo (Bob's identifier is in there)
  3. Hike.com obtains an identity token for Alice that can be presented at Bob's site. The obtained token is not targeted at any site. It identifies the OP, the party it was issued for (Hike.com) and has some identifier of the user (Alice). This identifier might be opaque/encrypted
  4. Hike.com can now perform an OAuth call to Event.com, carrying the identity token. This is a 2-legged call.
  5. Event.com resolve (i.e. exchanges) the identity token at Alice's OP and obtains an appropriate identifier of Alice (OpenID ID or email address etc.) that it can then use in its PoCo check for Bob.


This identity token is to carry the invocation identity (in Liberty ID-WSF's parlance). How is Bob's identity expressed in the call from Hike.com to Event.com? In a RESTful way, the URI would point to Bob, in a more traditional approach (e.g. Yahoo! Or Google) the URI only points to a generic endpoint and Bob's identity is added as a query parameter.

Although the OP knows whom the token is issued to, it doesn't know what the audience for this identity token might be. We need a mechanism to let Event.com know that the presented token was issued to Hike.com (i.e. Hike.com is authorized to present it).

Question: how does this applies to protecting XRD?

Looking into the identity token itself and how to secure it

There are cases where Hike.com does not know until later on that it needs the token for Event.com; in some other use cases, it is known in advance.

Core of the identity token:

IdP:Consumer:UserIdentifier
OP~A~:hike.com:A <nowiki>= </nowiki>secret

Information returned to Hike.com:
HMAC_SHA(secret, IDtoken string)
base64(OP~A~:Hike.com:A, hash1)

Hike.com uses the hash it receives as a secret and adds a nonce, creates the hash:
hash2 = HMAC_SHA(OP~A~:Hike.com:A:nonce, hash1)

Hike.com then sends the following to Event.com
OP~A~:Hike.com:A:nonce, hash2

Event.com should only receive this nonce once.

Hike.com should be able to generate multiple identity tokens (using different nonces) to multiple Service Providers.

Event.com can send the above data to OP~A~ which can verify it and get the identity A.

Note that this is not complete since it does not map A to a real user in Event.com (assuming there is one) nor does it give us the mapping to an identifier that maps to Bob's PoCo service.

Question: is there a way to reuse the consumer secret Hike.com has with Event.com to protect the token that OP~A~ will create? If so, does Hike.com need to communicate any data to OP~A~?

Next step:

  • Writing a document that shows how current technology (OpenID, OAuth etc.) fails in covering this use case.

OAuth extension #2 - Service Provisioning

Enabling the provisioning of your services (aka. Discovery part of ID-WSF) is another working item for us (note that this is more of a provisioning protocol rather than an OAuth extension per say).

Should we define a query interface on XRDS, or querying the host site for the XRDS?

Note: forcing the requesting service to parse the XRDS document (to find one service) could be a problem if the site handles millions of users.

Provisioning some reference (or piece) of service metadata into a user's XRD: no work on this so far.

The default expectation is that when I log in to a service, that service looks up my XRD file, detects it is not listed as one of the service providers there and proposes to add itself in it. This flow is similar to the one in the RESTful ID-WSF work.


The above swim lane describes an OAuth-based service provisioning. In this approach, we separate the registered services from its registered users, very much like the model adopted in ID-WSF (and for the same motivations). The numbered steps correpond to the following operations:

  1. Post XML (an XRD link element) to the OP. We want the OP to be able to verify that this is the SP that sent this request. We also want the OP to validate the SP reference in the XML data. This is why we use 2-legged OAuth. The data sent is not the service's XRD but a pointer to it.Step 1 is optional. That is, it will be executed the very first time the SP contacts the OP (and when updating the metadata).
  2. A service identifier that corresponds to this registration is returned
  3. The service providerast executes a 3-legged OAuth flow (i.e. with user authentication)
  4. The service provider can now associate the user with its registration at the OP. The OP can immediately update the user's XRDS document (unless it opted to dynamically generate those)

Step 4 aims at creating an association between the user and the SP. Similar flow should be created to delete or update such association.