OAuth for social sites

10 views
Skip to first unread message

Brian Eaton

unread,
Aug 5, 2008, 11:55:26 AM8/5/08
to opensocial-an...@googlegroups.com
OpenSocial 0.8 included support for OAuth authenticated access to data
via an OAuth proxy service. That support has been tested and found
suitable for private containers such as igoogle. Social containers
have sniffed at the OAuth proxy, and then walked away. Instead of
using OAuth, gadget authors are being forced to roll their own
solutions on top of signed fetch. This works, but we shouldn't force
people to reinvent the wheel. I'd like to propose some changes to the
OAuth proxy to make it suitable for social networks.

For those of you in a hurry, skip down to the section of this note
marked "Spec Proposal". If you're interested in why private
containers are happy with the OAuth proxy and social containers are
not, read on.

Almost no one aside from those implementing social containers
understands the special implications for OAuth in gadgets on social
sites. In particular, gadget authors and OAuth service providers are
unaware of some of the special considerations. For example, consider
the following scenario:
User X on an SNS installs an OAuth enabled gadget on their profile page.
User X grants approval for the OAuth gadget to access their
calendar from a third-party calendar site.
The third-party calendar site issues an OAuth token that gives
read/write access to the user's calendar.
When a friend visits the profile page, they see the calendar for the user.

This all looks fine, but there is a subtle security problem. The
calendar site can't tell the difference between someone viewing their
own calendar and a friend viewing their calendar. Both requests
arrive with the same OAuth token. If the friend is actually a
malicious user, the OAuth token could be used to modify or delete
entries, which is probably not what the owner intended when they added
the calendar to their page. The key insight here is that someone
viewing the gadget is not limited to the capabilities the gadget
intended to provide: they have the ability to send near-arbitrary
requests through the OAuth proxy, and the OAuth proxy will use the
OAuth token to sign those requests.

The chain of trust works as follows: the container page gives the
viewer a gadget security token authenticating the owner and the
viewer. The viewer gives the gadget security token to the gadget
rendering server, along with a request to sign. The gadget rendering
server authenticates the owner of the page based on the gadget
security token. Once the gadget rendering server knows who the owner
of the page is, the rendering server will use the OAuth token for the
owner to sign and proxy requests.

There are a few possibilities to fix this. One option is for the
OAuth token to carry very limited access rights. For example, the
token could provide read-only access to the calendar instead of
read/write access. That would give the viewer of the page permission
to see the calendar, which is probably what the owner intended in the
first place. The gadget could have a link back to the calendar site
that the owner would click when they wished to update their calendar.
The calendar site would then authenticate the owner with a more
standard mechanism (such as a password or a cookie), and thus would be
able to grant appropriate permissions to the owner.

Unfortunately, the notion of an OAuth token carrying limited access
rights requires great care on the part of the calendar site, the
gadget author, and the owner of the profile page. The calendar site
needs to provide a mechanism for OAuth tokens to carry limited access
rights. The gadget author needs to request a limited access token.
The owner of the calendar, in order to guarantee their own security,
needs to carefully consider what access they are approving before they
add the gadget to their page. If anyone fails to exercise due
diligence, the security vulnerability still exists. This model is
fine in theory, but is too fragile for wide spread use. We need
something more robust.

Another approach is to restrict the use of normal OAuth to the case
when the viewer of the page and the owner are the same person. This
is simple, and it fixes the security problem. Private containers are
happy with this solution, because for them the owner and the viewer
are always the same person. The only downside to this approach is
that it makes it impossible to build OAuth enabled gadgets that run on
social pages. We can address that limitation by using something
similar to signed fetch to pass information about the owner and the
viewer instead of signing the request with the OAuth token.

To build an OAuth gadget for a private container, no special work is
needed on the part of the gadget author or the OAuth service provider:
vanilla OAuth keeps working.

To build an OAuth gadget for a social container, the gadget author and
the OAuth service provider both need to be aware of the social nature
of the page. The OAuth data requests will include owner and viewer
information, so the service provider can map OAuth access tokens to
ids on the social network. Later on, if a request arrives without an
access token but with owner and viewer information, the service
provider can map the owner and viewer ids to their local user
identifiers and extract appropriate information for the users. The
service provider could even use the owner and viewer ids to call back
in to the social network to retrieve the social graph and return a
response customized to the user's network.

------- Spec Proposal -------

The gadgets.io.makeRequest function will be extended to take two
additional, optional parameters:
sign_owner: if enabled, the request should include opensocial owner
information. The default value of this parameter is false.
sign_viewer: if enabled, the request should include opensocial
viewer information. The default value of this parameter is false.

When gadgets.io.makeRequest is used with an authentication type of
OAuth, the OAuth proxy in the gadget rendering server will use the
following procedure to sign the request:

1) Any opensocial, oauth, or xoauth parameters sent by the client will
be removed. (Those parameters are completely controlled by the client
and so cannot be trusted to authenticate anything. The rendering
server must not sign them.)

2) If the client enabled either the "sign_owner" or "sign_viewer"
parameters, the rendering server will insert the opensocial_ signed
fetch parameters (such as the app id) into the OAuth request token,
access token, and data requests. If sign_owner is true, the
opensocial owner will be included in the request. If sign_viewer is
true, the opensocial viewer will be included in the request.

3) If the owner and the viewer are the same person, the OAuth access
token will be used to sign the request. Otherwise, only the consumer
key will be used to sign the request.

Examples #1: a gadget on a private page (owner == viewer), not using
the new parameters:
gadgets.io.makeRequest(url, callback, { AUTHORIZATION: "OAUTH" });

The request will follow the normal OAuth flow, either signing the
request with the user's access token or requesting that the user
approve access for the gadget. Any opensocial, oauth, or xoauth
parameters inserted by the client will be removed, but no new ones
will be inserted.

Example #2: a gadget on a private page (owner == viewer), using the
new parameters:
gadgets.io.makeRequest(url, callback, { AUTHORIZATION: "OAUTH",
SIGN_OWNER: true, SIGN_VIEWER: true });

The request will follow the normal OAuth flow, using the user's
access token to sign the request, but some additional parameters will
be inserted and signed by the rendering server:
GET /url?oauth_consumer_key=<consumer>&oauth_token=<token>&opensocial_owner_id=<owner>&opensocial_viewer_id=<owner>&opensocial_app_url=<gadget-url>...

Example #3: a gadget on a social page (owner != viewer), using the new
parameters:
gadgets.io.makeRequest(url, callback, { AUTHORIZATION: "OAUTH",
SIGN_OWNER: true, SIGN_VIEWER: true });

No access token will be used to sign the request. Instead, the
request will be signed as for signed fetch, using the consumer key
instead of the access token. Both owner and viewer id will be
included in the request:
GET /url?oauth_consumer_key=<consumer>&opensocial_owner_id=<owner>&opensocial_viewer_id=<owner>&opensocial_app_url=<gadget-url>...

Example #4: a gadget on a social page (owner != viewer), requesting
that only the owner id be used:
gadgets.io.makeRequest(url, callback, { AUTHORIZATION: "OAUTH",
SIGN_OWNER: true, SIGN_VIEWER: false });

No access token will be used to sign the request. Instead, the
request will be signed as for signed fetch, using the consumer key
instead of the access token. Only the owner id will be included in
the request
GET /url?oauth_consumer_key=<consumer>&opensocial_owner_id=<owner>&opensocial_app_url=<gadget-url>...

David Primmer

unread,
Aug 5, 2008, 2:54:08 PM8/5/08
to opensocial-an...@googlegroups.com
Hey Brian, thanks for the explanation of this complicated problem and
what seems like a good solution.

One problem I have is, from a high level, the AUTHORIZATION: "OAUTH",
now seems much more like AUTHORIZATION: "SIGNED", and it might be a
little confusing to end users. AUTHORIZATION: "OAUTH" would have a
fail-over design if you add the either SIGN_= true that allows it to
add identity attributes to the URL in the same manner as the current
AUTHORIZATION: "SIGNED", "signed fetch".

here's makeRequest spec for reference
http://code.google.com/apis/opensocial/docs/0.8/reference/gadgets/#gadgets.io.makeRequest

If I understood it before, you could request AUTHORIZATION: "OAUTH",
instead of AUTHORIZATION: "SIGNED", and you were assured that you
would not get a "identity attribute enhanced signed fetch" if you
requested OAUTH, but would get a bare consumer key signed fetch or
possibly the full OAuth dance. So with this change, since both types
of signed fetch can have these identity attributes, the main
difference between these two, from my perspective, is that if you use
AUTHORIZATION: "SIGNED", you can prevent the full OAuth dance from
happening if the runtime environment is not social.

The examples help a lot and one thing they had me wondering about was
'fallback' scenarios. It might help, if this becomes part of the spec,
to make quick notes about how a fetch changes as the deployment/user
environment changes but the actual gadget code does not. There are a
lot of combinations here, but they're very instructive as well. For
each permutation of the makeRequest call, the request that comes out
the other side changes depending on how it's deployed and rendered. It
is rather complicated, as your email shows, and it is important for
gadget developers to know how their code performs. A little web form
that allows you to experiment with these scenarios and dumps the
request they generate might be a useful tool.

davep

Krishna Sankar (ksankar)

unread,
Aug 6, 2008, 2:22:35 PM8/6/08
to opensocial-an...@googlegroups.com
Brian,
Good write-up; good points. Few thoughts:
a) You are right - some form of rbac is the right approach.
And I think we can make a robust set of APIs - for example have task
based tokens and APIs like friend access token (which is Read-only) and
owner token (which is RW) and making friend access token default
b) The idea of inferring access, based on a second order
inference is fine and probably a good first step
c) But it is binary and not granular and hence not
extensible - which again is fine. If it solves a current problem, so be
it
d) You are right "If anyone fails to exercise due
diligence, the security vulnerability still exists." It doesn't go away
even with the current proposal. A container can still ignore the
artifacts and allow RW access to a friend (Pl correct me if I am missing
something i.e. the proposed mechanism will make it impossible for a
calendar server to allow RW access with viewer != owner and SIGN_OWNER:
true, SIGN_VIEWER: true)
e) What I am leading upto is to see if we can add some well
known permissions RO,RW,WO as first order attributes than derive RW/RO
as second order attributes.
f) There might be cases where owner != viewer and still
need RW access (for example family members or admin assistants)
g) There might be cases where we need to do RW when owner
and viewer are in the same group and RO when they are in different
group.
h) OTOH, I do not want to add more "shine" when a simpler
solution would solve a current pain point. May be we just add two more
optional parameters role and permission.
Cheers
<k/>

Brian Eaton

unread,
Aug 6, 2008, 3:50:26 PM8/6/08
to opensocial-an...@googlegroups.com
On Wed, Aug 6, 2008 at 11:22 AM, Krishna Sankar (ksankar)
<ksa...@cisco.com> wrote:
> a) You are right - some form of rbac is the right approach.
> And I think we can make a robust set of APIs - for example have task
> based tokens and APIs like friend access token (which is Read-only) and
> owner token (which is RW) and making friend access token default

This sounds both complicated and brittle. Complicated because it
involves significant non-backwards compatible wire-format changes that
flow all the way to the APIs provided at both client and server.
Brittle because it forces complex business logic to be enforced far
away from where the business application is developed and where user
information is available.

> d) You are right "If anyone fails to exercise due
> diligence, the security vulnerability still exists." It doesn't go away
> even with the current proposal. A container can still ignore the
> artifacts and allow RW access to a friend (Pl correct me if I am missing
> something i.e. the proposed mechanism will make it impossible for a
> calendar server to allow RW access with viewer != owner and SIGN_OWNER:
> true, SIGN_VIEWER: true)

The security problem should go away with the current proposal, I
think. The OAuth access token will only be used if viewer == owner,
so the calendar app is not exposed by default. If the calendar app
chooses to be social, to recognize the viewer and owner parameters
instead of the access token, then and only then are they dealing with
the special risks associated with sharing data.

I'm comfortable with that because the calendar application developers
are aware of the social nature of the problem and can design their
code appropriately. With the old scheme we were suddenly ripping
their data out of a nice simple environment and into a much more
complex world, and the calendar app didn't get much say in the matter.


> e) What I am leading upto is to see if we can add some well
> known permissions RO,RW,WO as first order attributes than derive RW/RO
> as second order attributes.
> f) There might be cases where owner != viewer and still
> need RW access (for example family members or admin assistants)
> g) There might be cases where we need to do RW when owner
> and viewer are in the same group and RO when they are in different
> group.

This is terrifying, but maybe if you provide details on how this could
be implemented I'll stop shaking in fear. =)

A couple of the scarier bits: where are "family members" and "admin
assistants" defined, at the social site or at the calendar site? How
do we handle distribution of tokens? Where is the business logic of
each application enforced? How do we translate the business logic
from the application server into access control decisions at the
gadget server?

> h) OTOH, I do not want to add more "shine" when a simpler
> solution would solve a current pain point. May be we just add two more
> optional parameters role and permission.

My take on this is that we could add lots of complexity at the client
side of the communication, but we'd still end up with a solution that
was unable to account for all of the details of the business logic.
The only thing the client side can do really well is authenticate
users and provide metadata about those users via the REST-ful APIs.
We should expose that information to the server side, and let it
implement the business logic itself.

Cheers,
Brian

Louis Ryan

unread,
Aug 6, 2008, 4:55:18 PM8/6/08
to opensocial-an...@googlegroups.com
So basically you're saying that the use of Access token signing should be used by service providers to infer that viewer == owner. I dont see why the pattern used for example #2 above cannot just be used for example #3. In each case the provider has reliably been given the information to determine if the viewer is the owner but they must decide which signing scheme to validate which seems like unnecessary overhead. If the expect providers to implement permissioning schemes based on whether or not viewer == owner regardless of the authorization scheme then it seems like we should just always include that information in the request. I dont think caching is much of a concern here as we wouldnt allow for signing requests with the OAuth token when SIGN_VIEWER=true & SIGN_OWNER=false.

On Tue, Aug 5, 2008 at 8:55 AM, Brian Eaton <bea...@google.com> wrote:

Brian Eaton

unread,
Aug 7, 2008, 11:17:57 AM8/7/08
to opensocial-an...@googlegroups.com
[full disclosure: I don't totally understand your note. I'm replying
to individual sentences that I did understand, and you're probably
going to have to explain the rest to me again.]

On Wed, Aug 6, 2008 at 1:55 PM, Louis Ryan <lr...@google.com> wrote:
> So basically you're saying that the use of Access token signing should be
> used by service providers to infer that viewer == owner.

Not just that. Access token signing should be used for two reasons:

1) It's backwards compatible with non-social OAuth services, e.g. I
can still write a fireeagle gadget or a calendar gadget that works on
non-social pages, without any special work on the part of the SP.

2) For correlating access tokens with opensocial ids, so that I know
when opensocial id 12...@orkut.com shows up, it maps to user xyz in my
system.

> I dont see why the pattern used for example #2 above cannot just be used for example #3.

If we use access token signing in example #3 (owner != viewer) then we
create a security problem for non-social OAuth providers whose data is
suddenly exposed in a social context. Not using access token signing
when owner != viewer is a fundamental goal of this proposal.

> if the viewer is the owner but they must decide which signing scheme to
> validate which seems like unnecessary overhead.

It's not much overhead, because the same consumer key is used to sign
the request regardless. If you see an access token in a request, you
have to do some extra work, but people are already doing that work for
OAuth today because it is necessary for the id correlation.

> If the expect providers to
> implement permissioning schemes based on whether or not viewer == owner
> regardless of the authorization scheme then it seems like we should just
> always include that information in the request. I dont think caching is much
> of a concern here as we wouldnt allow for signing requests with the OAuth
> token when SIGN_VIEWER=true & SIGN_OWNER=false.

Totally confused on this one.

Brian Eaton

unread,
Aug 7, 2008, 11:25:35 AM8/7/08
to opensocial-an...@googlegroups.com
On Tue, Aug 5, 2008 at 11:54 AM, David Primmer <david....@gmail.com> wrote:
> One problem I have is, from a high level, the AUTHORIZATION: "OAUTH",
> now seems much more like AUTHORIZATION: "SIGNED", and it might be a
> little confusing to end users.

I assume by "end user" you mean "gadget developer"?

> If I understood it before, you could request AUTHORIZATION: "OAUTH",
> instead of AUTHORIZATION: "SIGNED", and you were assured that you
> would not get a "identity attribute enhanced signed fetch" if you
> requested OAUTH, but would get a bare consumer key signed fetch or
> possibly the full OAuth dance. So with this change, since both types
> of signed fetch can have these identity attributes, the main
> difference between these two, from my perspective, is that if you use
> AUTHORIZATION: "SIGNED", you can prevent the full OAuth dance from
> happening if the runtime environment is not social.

You would want to use "authorization = oauth" if and only if the
service provider supports full OAuth on their end. Gadget developers
should make the choice as follows:

Does the SP support full OAuth, or just signed fetch?
-- if they don't support OAuth, you're stuck with the signed fetch
option. This is a totally reasonable place to be, by the way. OAuth
is overkill unless you've got multiple identity silos.

Does the SP support the social extensions to OAuth?
-- if they don't, the gadget will only work on private pages. If the
SP does support the social extensions, however, they you can use the
sign_owner and sign_viewer parameters to display OAuth data on social
pages.

How should SPs decide what to support?

If the only notion of identity they need is the opensocial id and
container id, then they should use signed fetch.

If they need to correlate the opensocial ids with their own ids, they
should use OAuth.

If they want to allow users to expose their data on social pages, they
should use OAuth + the social extensions proposed here.

Did that explanation clear things up, or am I just muddying the waters
further? If it helps, let's add it to the spec proposal.

Louis Ryan

unread,
Aug 7, 2008, 12:03:55 PM8/7/08
to opensocial-an...@googlegroups.com
Ok you've largely convinced me so +1.

 My general point was about providers relying on the existence of both viewer and owner params in OAuth requests would more closely match what they would do for signed requests and so always including them might simplify code for some folks. I accept though that the existence or otherwise of the access token provides the same information and in many ways is more useful and we dont want to disrupt general OAuth providers with extraneous OpenSocial cruft when they dont want it.

Krishna Sankar (ksankar)

unread,
Aug 7, 2008, 2:23:32 PM8/7/08
to opensocial-an...@googlegroups.com
|This is terrifying, but maybe if you provide details on how this could
|be implemented I'll stop shaking in fear. =)
|
|A couple of the scarier bits: where are "family members" and "admin
|assistants" defined, at the social site or at the calendar site? How
|do we handle distribution of tokens? Where is the business logic of
|each application enforced? How do we translate the business logic
|from the application server into access control decisions at the
|gadget server?
<KS>
DON'T PANIK ;o)
Actually I was not implying that we immediately implement the
different roles, but pointing out that owner = viewer is not the only
case for RW access. IMHO we need to allow extensibility and
remixability. Let us add one more optional ACCESS_TYPE parameter. That
way if systems want to implement types of access based on other
inferences, they can.

BTW, agreed on your idea of leaving business logic at the server
side rather than complex client protocols. Simpler state machines (on
both sides) as well as a single place for business logic. Good thought.

</KS>
Cheers
<k/>

|-----Original Message-----
|From: opensocial-an...@googlegroups.com [mailto:opensocial-
|and-gadg...@googlegroups.com] On Behalf Of Brian Eaton

Brian Eaton

unread,
Aug 7, 2008, 2:31:42 PM8/7/08
to opensocial-an...@googlegroups.com
On Thu, Aug 7, 2008 at 11:23 AM, Krishna Sankar (ksankar)
<ksa...@cisco.com> wrote:
> DON'T PANIK ;o)

OK, I'm chill.

> Actually I was not implying that we immediately implement the
> different roles, but pointing out that owner = viewer is not the only
> case for RW access. IMHO we need to allow extensibility and
> remixability. Let us add one more optional ACCESS_TYPE parameter. That
> way if systems want to implement types of access based on other
> inferences, they can.

Can you give more detail on this, preferably at the level of the
javascript API exposed and the semantics the gadget server needs to
implement for that API?

Krishna Sankar (ksankar)

unread,
Aug 7, 2008, 5:14:32 PM8/7/08
to opensocial-an...@googlegroups.com
This is what I am thinking:

The gadgets.io.makeRequest function will be extended to take three
additional, optional parameters:
sign_owner: if enabled, the request should include opensocial owner
information. The default value of this parameter is false.
sign_viewer: if enabled, the request should include opensocial viewer
information. The default value of this parameter is false.
access_type : if present, will have the role or access type

Without breaking the flow, along with other parameters, this will end up
as opensocial_access_type=<access_tpe>

The rendered and downstream servers can act based on the element, if the
understand it. If not, they will ignore it - same processing model as
the signed_viewer et al.

What we are providing is an extensibility mechanism for rbac-like
control for applications and services that need extended capabilities.
BTW, some server along the chain can collapse the sign_owner =
sign_viewer to access_type = RW (or sign_owner != sign_viewer to
access_type = RO) it can. Or a social app which understands the
relationship between users and infers that while sign_owner !=
sign_viewer but still access_type should be RW, it can do so.

Cheers
<k/>

|-----Original Message-----
|From: opensocial-an...@googlegroups.com [mailto:opensocial-
|and-gadg...@googlegroups.com] On Behalf Of Brian Eaton
|Sent: Thursday, August 07, 2008 11:32 AM
|To: opensocial-an...@googlegroups.com
|Subject: Re: OAuth for social sites
|
|

Brian Eaton

unread,
Aug 7, 2008, 6:00:05 PM8/7/08
to opensocial-an...@googlegroups.com
On Thu, Aug 7, 2008 at 2:14 PM, Krishna Sankar (ksankar)
<ksa...@cisco.com> wrote:
> The gadgets.io.makeRequest function will be extended to take three
> additional, optional parameters:
> sign_owner: if enabled, the request should include opensocial owner
> information. The default value of this parameter is false.
> sign_viewer: if enabled, the request should include opensocial viewer
> information. The default value of this parameter is false.
> access_type : if present, will have the role or access type
>
> Without breaking the flow, along with other parameters, this will end up
> as opensocial_access_type=<access_tpe>

This doesn't make sense to me. If the access type value is supposed
to be inserted by the gadget javascript, then it can do so already.
Just add a parameter to the URL saying "access_type=foo". There is no
need to modify the opensocial spec to support that use case.

Krishna Sankar (ksankar)

unread,
Aug 7, 2008, 8:37:46 PM8/7/08
to opensocial-an...@googlegroups.com
Two reasons:
a) The access type would be part of signed OAuth artifacts (across
multiple servers, if need be)
b) Provides us with a namespace (opensocial\access_Type) and
associated common semantic bindings (RO,RW,WO,reader,...) for rbac.

And finally, if this is too divergent for the current discussions, we
can revisit the extensibility, authZ and rbac at the appropriate time.
Cheers
<k/>

|-----Original Message-----
|From: opensocial-an...@googlegroups.com [mailto:opensocial-
|and-gadg...@googlegroups.com] On Behalf Of Brian Eaton
|Sent: Thursday, August 07, 2008 3:00 PM
|To: opensocial-an...@googlegroups.com
|Subject: Re: OAuth for social sites
|
|
|On Thu, Aug 7, 2008 at 2:14 PM, Krishna Sankar (ksankar)
|<ksa...@cisco.com> wrote:
|> The gadgets.io.makeRequest function will be extended to take three
|> additional, optional parameters:
|> sign_owner: if enabled, the request should include opensocial owner
|> information. The default value of this parameter is false.
|> sign_viewer: if enabled, the request should include opensocial
|viewer
|> information. The default value of this parameter is false.
|> access_type : if present, will have the role or access type
|>
|> Without breaking the flow, along with other parameters, this will end
|up
|> as opensocial_access_type=<access_tpe>
|
|This doesn't make sense to me. If the access type value is supposed
|to be inserted by the gadget JavaScript, then it can do so already.

Brian Eaton

unread,
Aug 7, 2008, 8:44:14 PM8/7/08
to opensocial-an...@googlegroups.com
On Thu, Aug 7, 2008 at 5:37 PM, Krishna Sankar (ksankar)
<ksa...@cisco.com> wrote:
> Two reasons:
> a) The access type would be part of signed OAuth artifacts (across
> multiple servers, if need be)
> b) Provides us with a namespace (opensocial\access_Type) and
> associated common semantic bindings (RO,RW,WO,reader,...) for rbac.
>
> And finally, if this is too divergent for the current discussions, we
> can revisit the extensibility, authZ and rbac at the appropriate time.

I think that's a good idea. Right now signing is used to distinguish
between information inserted by the trusted gadget rendering server
and the untrusted browser. Until we have a good notion of where
opensocial_access_type fits into that scheme, we shouldn't worry about
it.

Brian Eaton

unread,
Aug 14, 2008, 2:19:07 AM8/14/08
to opensocial-an...@googlegroups.com
The proposal I made earlier
(http://groups.google.com/group/opensocial-and-gadgets-spec/browse_thread/thread/e51cf32cfb4a54eb)
is already complicated, and as Eric Sachs and Dirk Balfanz and I
talked it over during the past week we figured out it doesn't even
cover all of the possible use cases. During our conversations we
decided it ought to be possible to come up with something that was (a)
simpler and (b) more powerful. The proposal below is the result.

First, the uncovered use case: the previous proposal assume that when
owner == viewer, the OAuth token was always necessary. That might be
true for some situations, but there is a class of applications that
can't be built under that assumption. Consider this gadget:

- a user installs an application from an OAuth service provider. The
app begins working immediately (no need to login/approve access). The
user adds data and gradually builds up a relationship with the service
provider.
- eventually the user decides that the small screen gadget is useful
enough that they want to take greater advantage of the service
provider. They visit the SP and create an account. The data they
created from the gadget is immediately linked to their new account.

You can, in fact, build that application on top of the existing
OpenSocial APIs, but unless you've spent a lot of time thinking about
strategies it's not obvious how. Even once you figure out a system
that can work, the code is tricky. If we simplify the authentication
and authorization APIs, we can make it easy.

Spec proposal:

AUTHZ=SIGNED takes one new parameter:

use_oauth_token = [no | if_available | yes]

If use_oauth_token = no (the default), then signed fetch behaves
exactly as it does today.

If owner != viewer, use_oauth_token is always forced to "no". The
OAuth token is never used. This resolves the security risks that
started this discussion.

If use_oauth_token = yes (and owner == viewer), then the behavior is
equivalent to authz=OAUTH. If the token is not available, the gadget
server begins the OAuth dance and returns the approval URL to the
gadget.

If use_oauth_token = if_available, we get new behavior. If we already
have an access token for the user, we include it in the OAuth
signature. If we don't have an access token for the user, we make a
signed fetch instead.

AUTHZ=OAUTH is deprecated, and instead is implemented as AUTHZ=SIGNED
with use_oauth_token=yes, sign_owner=no, and sign_viewer=no. The only
functional change is that the token is never used unless owner ==
viewer. No social networks have deployed the OAuth proxy, so that's
not a major loss.

That's the sum of the spec proposal. We drop authz=OAUTH, and we add
one new parameter to signed fetch.

Above I described a gadget that lets a user start creating data before
they've created an account, and then later on the user can link the
data to a full-fledged account. Here's how it would work:

1) the gadget begins using authz=SIGNED with use_oauth_token=if_available.
2) when the user indicates they want to link an account, the gadget
makes a single request with use_oauth_token=yes. The gadget server
doesn't have an access token for the user, so it starts the OAuth
dance and returns an approval URL.
3) the user completes the OAuth dance. During this process the
service provider is able to link the user's opensocial id (user abc
from some opensocial container) to an independent ID at the service
provider site.
4) the next time the gadget makes a request to the service provider,
the gadget server swaps the OAuth request token for the approved OAuth
access token.
5) on subsequent requests, the gadget continues to use
use_oauth_token=if_available. The OAuth access token is used for
signing.

It's relatively easy for the gadget author to implement this logic.
The service provider needs some smarts, in order to be able to link up
the identity from the opensocial container to their own identity. I
hope the value proposition for service providers is high enough that
they'll be willing to do the work.

Explaining this to gadget developers is going to be challenging. How
do people know which option to use? Dirk suggested explaining it as
follows:

> - if you don't need to link accounts, just use "never"
> - if your gadget only works once accounts are linked, just use "always"
> - if your gadget should work whether or not accounts are linked, use "if
> available", and put the necessary smarts into your server to deal with both
> cases (incoming requests with/without tokens). You can force an account link
> with a single request that uses "always"

I've tried to explain this clearly and briefly. I know I failed on
the latter goal, but hopefully this explanation is readable.
Questions, suggestions, and criticism would be great.

Cheers,
Brian

David Primmer

unread,
Aug 14, 2008, 4:29:08 AM8/14/08
to opensocial-an...@googlegroups.com
bravo. this new approach is much more clear and remove some of the
complicated 'magic' in the earlier proposal.

davep

Eiji Kitamura

unread,
Aug 15, 2008, 11:19:21 AM8/15/08
to opensocial-an...@googlegroups.com
Hi Brian,


I have a question regarding how OAuth should be used.

> User X on an SNS installs an OAuth enabled gadget on their profile page.
> User X grants approval for the OAuth gadget to access their
> calendar from a third-party calendar site.
> The third-party calendar site issues an OAuth token that gives
> read/write access to the user's calendar.
> When a friend visits the profile page, they see the calendar for the user.
>
> This all looks fine, but there is a subtle security problem. The
> calendar site can't tell the difference between someone viewing their
> own calendar and a friend viewing their calendar. Both requests
> arrive with the same OAuth token.

Why is this? Assumption I had was to use one token for each user.
Access control on service provider always lives on their side. It
sounds ridiculous to use owner's token for viewer's access.

I was expecting cases like this:
1. viewer accesses owner's profile
2. the gadget indicates to give authentication.
3. viewer authenticate with service provider via OAuth.
4. consumer container requests data from service provider using OAuth token.
5. service provider judges if given token's owner have access to the
resource. returned content may have detail of the schedule, or just an
indication that calendar owner has plan for that period, depending on
owner of the token.
6. consumer container gets response from service provider.

If the service provider needs friend list for controling access to the
calendar, container can provide it via REST API. Of course, there
needs to be some kind of structure like FriendConnect or
DataAvailability and proper connection should be prepared beforehand.

This way looks simpler and compelling to me.
Why not?

Brian Eaton

unread,
Aug 15, 2008, 12:09:26 PM8/15/08
to opensocial-an...@googlegroups.com
On Fri, Aug 15, 2008 at 8:19 AM, Eiji Kitamura <age...@gmail.com> wrote:
>> Both requests
>> arrive with the same OAuth token.
>
> Why is this? Assumption I had was to use one token for each user.
> Access control on service provider always lives on their side. It
> sounds ridiculous to use owner's token for viewer's access.

Yes, I agree, that's (one of) the reasons I want to change the spec.
The old version says that the owner's token is always used, and that's
just not the right thing to do.

> I was expecting cases like this:
> 1. viewer accesses owner's profile
> 2. the gadget indicates to give authentication.
> 3. viewer authenticate with service provider via OAuth.
> 4. consumer container requests data from service provider using OAuth token.
> 5. service provider judges if given token's owner have access to the
> resource. returned content may have detail of the schedule, or just an
> indication that calendar owner has plan for that period, depending on
> owner of the token.
> 6. consumer container gets response from service provider.
>
> If the service provider needs friend list for controling access to the
> calendar, container can provide it via REST API. Of course, there
> needs to be some kind of structure like FriendConnect or
> DataAvailability and proper connection should be prepared beforehand.
>
> This way looks simpler and compelling to me.
> Why not?

This is almost exactly what I'm proposing. The only difference is
that you're suggesting that the OAuth token be sent even when owner !=
viewer. I'm reluctant to do that because it means exposing data on
social pages without the cooperation of the service provider. If we
start doing that, some service providers are going to be surprised and
unhappy.

Eiji Kitamura

unread,
Aug 15, 2008, 12:36:20 PM8/15/08
to opensocial-an...@googlegroups.com
Hi Brian,


Thanks for your reply. I'm happy to know that my basic assumption was correct.

> This is almost exactly what I'm proposing. The only difference is
> that you're suggesting that the OAuth token be sent even when owner !=
> viewer. I'm reluctant to do that because it means exposing data on
> social pages without the cooperation of the service provider. If we
> start doing that, some service providers are going to be surprised and
> unhappy.

Isn't this why OAuth asks consumer to have key and secret? I thought
service provider giving key and secret means some kind of trust to the
consumer.
Also, this sounds like being against the concept of Data Portability.
If user permits his friend to fetch data via consumer, it should be
allowed, shouldn't it?

If I'm not understanding correctly, can you please give me concrete
example when service provider being surprised and unhappy?

Brian Eaton

unread,
Aug 15, 2008, 12:55:12 PM8/15/08
to opensocial-an...@googlegroups.com
On Fri, Aug 15, 2008 at 9:36 AM, Eiji Kitamura <age...@gmail.com> wrote:
>> I'm reluctant to do that because it means exposing data on
>> social pages without the cooperation of the service provider. If we
>> start doing that, some service providers are going to be surprised and
>> unhappy.
>
> Isn't this why OAuth asks consumer to have key and secret? I thought
> service provider giving key and secret means some kind of trust to the
> consumer.

Most OAuth service providers are not going to individually review
every application someone builds on top of their APIs, and they might
not realize that the data is being exposed to people besides the user.

> Also, this sounds like being against the concept of Data Portability.
> If user permits his friend to fetch data via consumer, it should be
> allowed, shouldn't it?

I think so, but I want everyone to be comfortable with it. In
particular, we need to be careful not to create any security surprises
for users or service providers.

> If I'm not understanding correctly, can you please give me concrete
> example when service provider being surprised and unhappy?

No, because no social sites have supported OAuth yet. =)

With the current implementation, where the owner's token is always
available, there are lots of bad things that can happen very easily.
For example, someone adds an OAuth gadget to their page, intending to
provide read-access to their data, but accidentally provides
read-write because the OAuth token is not restricted to read-only
access.

If we made the viewer's token available, that seems safer, but it
still dangerous for sites that provide stronger authentication of the
owner than the viewer. For example, some sites allow the owner of the
page to insert script. That would mean that the owner could hijack
the viewer's token, and then we're back in a situation where the OAuth
service provider doesn't really know who is accessing the data.

Cheers,
Brian

Scott Seely

unread,
Aug 15, 2008, 1:04:59 PM8/15/08
to opensocial-an...@googlegroups.com
I just want to clear up a couple incorrect statements in this post:
1. MySpace does individually review every social application before it
is made available to other users.
2. MySpace is currently using OAuth for MDP. I'm pretty sure we're a
social site ;)

-----Original Message-----
From: opensocial-an...@googlegroups.com
[mailto:opensocial-an...@googlegroups.com] On Behalf Of Brian
Eaton
Sent: Friday, August 15, 2008 9:55 AM
To: opensocial-an...@googlegroups.com
Subject: Re: OAuth for social sites


Brian Eaton

unread,
Aug 15, 2008, 1:17:20 PM8/15/08
to opensocial-an...@googlegroups.com
Hi Scott -

Sorry for the confusion. My specific statements were not about OAuth
requests inbound to social sites. That's working just fine. This
spec proposal was about the reverse flow, when a gadget is importing
data from a third-party, non-social OAuth service provider to an SNS.

Cheers,
Brian

Eiji Kitamura

unread,
Aug 15, 2008, 2:05:57 PM8/15/08
to opensocial-an...@googlegroups.com
>> Isn't this why OAuth asks consumer to have key and secret? I thought
>> service provider giving key and secret means some kind of trust to the
>> consumer.
>
> Most OAuth service providers are not going to individually review
> every application someone builds on top of their APIs, and they might
> not realize that the data is being exposed to people besides the user.

I imagine a developer create a gadget which fetches user's schedule
from Google Calendar, which key/secret pair is generated using
automated process mentioned here:
http://code.google.com/apis/accounts/docs/RegistrationForWebAppsAuto.html

> No, because no social sites have supported OAuth yet. =)

Thanks for examples in spite of saying No :)

> With the current implementation, where the owner's token is always
> available, there are lots of bad things that can happen very easily.

By "current implementation", you mean Shindig v0.8 OAuth impl?

> For example, someone adds an OAuth gadget to their page, intending to
> provide read-access to their data, but accidentally provides
> read-write because the OAuth token is not restricted to read-only
> access.

Isn't this the case where you should use two-legged signed fetch?
Is this what your proposal intended to be?

> If we made the viewer's token available, that seems safer, but it
> still dangerous for sites that provide stronger authentication of the
> owner than the viewer. For example, some sites allow the owner of the
> page to insert script. That would mean that the owner could hijack
> the viewer's token, and then we're back in a situation where the OAuth
> service provider doesn't really know who is accessing the data.

Your consideration sounds like assuming use of GDATA apis with OAuth,
which key/secrets are auto-generated. If service provider can't trust
consumer, security risk always exists. It's OAuth's fundamental
problem rather than OpenSocial specific.
Consumer can do anything evil and this is unavoidable as long as using OAuth.

I would let only trusted consumers use OAuth api as a container /
service provider, which verification done by either business or
reading code like MySpace.


What do you think?

Brian Eaton

unread,
Aug 15, 2008, 2:35:32 PM8/15/08
to opensocial-an...@googlegroups.com
On Fri, Aug 15, 2008 at 11:05 AM, Eiji Kitamura <age...@gmail.com> wrote:
>> With the current implementation, where the owner's token is always
>> available, there are lots of bad things that can happen very easily.
>
> By "current implementation", you mean Shindig v0.8 OAuth impl?

Yes.

>> For example, someone adds an OAuth gadget to their page, intending to
>> provide read-access to their data, but accidentally provides
>> read-write because the OAuth token is not restricted to read-only
>> access.
>
> Isn't this the case where you should use two-legged signed fetch?
> Is this what your proposal intended to be?

Two-legged signed fetch only works if there is no independent user
identity at the remote site. This proposal tries to provide a clear
transition path from two-legged to three-legged. If a site really
doesn't need their own user identities, that's great, and they should
stick with two-legged.

> Your consideration sounds like assuming use of GDATA apis with OAuth,
> which key/secrets are auto-generated. If service provider can't trust
> consumer, security risk always exists. It's OAuth's fundamental problem
> rather than OpenSocial specific.

I disagree. We are providing APIs for gadgets to use OAuth on social
sites. Providing a well-designed API that encourages secure use of
OAuth is an important goal. As an example of why, consider the
original implementation of the OAuth proxy in Shindig: it worked fine
for private containers, but use of the owner's token meant that the
OAuth proxy was just not suitable for social containers.

A bad OpenSocial API will create a security problem for OAuth service providers.

> Consumer can do anything evil and this is unavoidable as long as using OAuth.

There is malice, and there is ignorance. I'm actually more concerned
about accidental security vulnerabilities than malicious OAuth
consumers. Dealing with a malicious OAuth consumer is relatively
easy: revoke their consumer secret. Ignorance is a harder problem.
We need to make sure that well-intentioned people can write secure
OAuth enabled gadgets, and we need to make it as simple as humanly
possible.

> I would let only trusted consumers use OAuth api as a container /
> service provider, which verification done by either business or
> reading code like MySpace.
>
> What do you think?

You seem to be making the argument that the security of OAuth enabled
gadgets is not an issue for the opensocial community, that we should
leave the matter up to the OAuth service providers. I don't think
that's a good idea. If we don't provide secure APIs for gadgets to
use OAuth on social sites, one of two things will happen:

- social sites will refuse to let gadgets use OAuth at all
OR
- OAuth service providers will refuse to issue consumer keys and
secrets to the authors of social gadgets.

Cheers,
Brian

Eiji Kitamura

unread,
Aug 18, 2008, 4:47:21 AM8/18/08
to opensocial-an...@googlegroups.com
Hi Brian,


>> Isn't this the case where you should use two-legged signed fetch?
>> Is this what your proposal intended to be?
>
> Two-legged signed fetch only works if there is no independent user
> identity at the remote site. This proposal tries to provide a clear
> transition path from two-legged to three-legged. If a site really
> doesn't need their own user identities, that's great, and they should
> stick with two-legged.

I guess I'm not really understanding the characteristics of two-legged
OAuth and how it should be used.

My assumption for two-legged OAuth was:
- two-legged OAuth is used only for data which is public, because
there's no authentication involved especially when owner != viewer.
- a gadget's developer and SP's owner which use two-legged OAuth don't
necessarily be the same.

Can you correct me if they are wrong?


>> Your consideration sounds like assuming use of GDATA apis with OAuth,
>> which key/secrets are auto-generated. If service provider can't trust
>> consumer, security risk always exists. It's OAuth's fundamental problem
>> rather than OpenSocial specific.
>
> I disagree. We are providing APIs for gadgets to use OAuth on social
> sites. Providing a well-designed API that encourages secure use of
> OAuth is an important goal. As an example of why, consider the
> original implementation of the OAuth proxy in Shindig: it worked fine
> for private containers, but use of the owner's token meant that the
> OAuth proxy was just not suitable for social containers.
>
> A bad OpenSocial API will create a security problem for OAuth service providers.

I agree. OpenSocial OAuth proxy is safer than to let developer be
OAuth consumer itself.
I forgot OAuth work as proxy when on opensocial.


>> Consumer can do anything evil and this is unavoidable as long as using OAuth.
>
> There is malice, and there is ignorance. I'm actually more concerned
> about accidental security vulnerabilities than malicious OAuth
> consumers. Dealing with a malicious OAuth consumer is relatively
> easy: revoke their consumer secret. Ignorance is a harder problem.
> We need to make sure that well-intentioned people can write secure
> OAuth enabled gadgets, and we need to make it as simple as humanly
> possible.

You are right. Even if consumer developer knows rules and has good
skill, anything could happen.
We should consider every possible case.


>> I would let only trusted consumers use OAuth api as a container /
>> service provider, which verification done by either business or
>> reading code like MySpace.
>>
>> What do you think?
>
> You seem to be making the argument that the security of OAuth enabled
> gadgets is not an issue for the opensocial community, that we should
> leave the matter up to the OAuth service providers. I don't think
> that's a good idea. If we don't provide secure APIs for gadgets to
> use OAuth on social sites, one of two things will happen:
>
> - social sites will refuse to let gadgets use OAuth at all
> OR
> - OAuth service providers will refuse to issue consumer keys and
> secrets to the authors of social gadgets.

Let me explain why I asked this.
I'm anxious about use case like following.

Condition:
- There's an SNS and a Service(S) which lets user share photos.
- S is a registered service like Flickr but you can't have friends on S itself.
- But S can import social graph from other SNS using OpenSocial
RESTful API (like FriendConnect).
- S can share user's photos to arbitorary SNS's friends / part of
friends. (ACL is stored in S's DB)
- Of course, S supports both OAuth consumer / service provider.
- To use S with an SNS, you have to register to SNS beforehand.
- Also, you have to add S as external service in the SNS.
- On adding S to SNS, SNS supports adding S's gadget at the same time.
This is ** Inbound/Outbound hybrid use case **.
- On the SNS's profile page, the user's gadget shows his latest photo addition.
- When friend of him accesses the user's page, the friend sees what's
added to the user's photo in S.

It's kinda hustle for me to explain this in English :) but could you understand?
This is the Social Web I'm dreaming of, and hopefully others too.
There'll be activity stream involved, so some bit could be slightly
different but, what I'm anxious of is the last bit.

> - When friend of him accesses the user's page, the friend sees what's added to the user's photo in S.

I believe on this case, two-legged OAuth won't work, especially when
the photo is shared only to part of his friends.
I'm asking this because my knowledge how two-legged OAuth should be
used is not enough.
Will your proposal apply for this situation?

Brian Eaton

unread,
Aug 18, 2008, 1:17:41 PM8/18/08
to opensocial-an...@googlegroups.com
On Mon, Aug 18, 2008 at 1:47 AM, Eiji Kitamura <age...@gmail.com> wrote:
> My assumption for two-legged OAuth was:
> - two-legged OAuth is used only for data which is public, because
> there's no authentication involved especially when owner != viewer.
> - a gadget's developer and SP's owner which use two-legged OAuth don't
> necessarily be the same.

For public data, you don't need OAuth at all. Just grab it. Here's a
use case for two-legged OAuth:

Service provider (SP) records ratings and reviews for music.
A gadget G runs on multiple SNS acts as a front-end to the SP.
When a user is running the gadget, the gadget contacts the SP with
information about the user's music preferences, something like this.

Signed fetch/two-legged OAuth is used for that. The SP receives a
request from the proxy at the SNS saying "user 12345 on network
example-social-network.com sent this request". The SP verifies the
signature on the request, and records music preferences in their
database:

User: 12...@example-social-network.com
Favorite artist: MC Frontalot

Multiple social networks can send requests to the SP, so user
information can come from almost anywhere. Users could be
ab...@orkut.com, wx...@myspace.com, etc...

Signed fetch includes information about both the owner and the viewer
of the page, so behavior can be customized for the context. For
example, when someone views my page, they can see the overlap between
my music taste and theirs. Using the REST-ful APIs the SP can also
customize the information based on the friend graph.

This all works, but it depends on a big assumption: there is no
independent user identity at the SP. Users never log in to the SP
directly, they always authenticate to the SP via signed fetch from the
social network.

Full OAuth, three-legged OAuth, gets around that limitation. The user
is redirected to the SP's web site, so the SP gets an opportunity to
establish an identity for the user independent of the SNS identity.
This is necessary if there is already user-specific data at the SP, as
in your photo example.

So this scenario is mostly possible with the OAuth support in
opensocial 0.8. Here's how it would work:
- User adds gadget to their page.
- User is redirected to photo site to approve access to their photos.
- The OAuth token of the owner of the page is always used to access
their photos.

So my profile page can pull photos from the photo site, and my friends
viewing my profile page will see those photos.

The downside to this is that the photo site can't tell the difference
between me accessing my photos, and my friends viewing my page. This
is a major problem.

With the new proposal, it works like this:
- User adds gadget to their page. A signed request is made with
use_oauth_token=yes and sign_owner=true.
- User is redirected to photo site to approve access to their photos.
- The service provider correlates the opensocial owner ID of the user
with their OAuth token, i.e. it stores a mapping like this:

12...@example-social-network.com -> bea...@photosite.com.

Subsequent requests from the gadget are made using signed fetch, with
use_oauth_token=optional, sign_owner=true, and sign_viewer=true. When
a friend views my page, the request to the service provider does not
include my OAuth token, but it does include the opensocial ids from
the SNS:
Owner: 12...@example-social-network.com
Viewer 67...@example-socail-network.com

The photo site can look up my photos based on the owner id, and it can
look up the friend graph by calling back to example-social-network
with the REST-ful APIs.

Does this sound like it would meet your use case?

Eiji Kitamura

unread,
Aug 20, 2008, 5:03:12 AM8/20/08
to opensocial-an...@googlegroups.com
Hi Brian,


I'm getting there but a few things still seems ambiguous to me.
I've read through this:
https://sites.google.com/site/oauthgoog/2leggedoauth/2opensocialrestapi

What are conditions for use with 2-legged oauth?
My assumption:
1. SP is under control of Consumer gadget.
2. Consumer is proxied (OAuth proxy).

Otherwise, can't consumer abuse service provider?
For example, consumer can fetch arbitrary user's information, can't it?
That's why i assumed 2-legged can fetch only public data and the
biggest riddle I have here.


> With the new proposal, it works like this:
> - User adds gadget to their page. A signed request is made with
> use_oauth_token=yes and sign_owner=true.

What is this endpoint? Resource itself? Then,
1. if use_oauth_token=no then assume this is signed fetch and return
available resource.
2. if use_oauth_token=[yes|optional] and token exists then return
available resource.
3. if use_oauth_token=yes and no token {
4a. redirect to oauth request endpoint.
4b. return 403. consumer begins oauth dance by itself.
}

Is this right?

> - User is redirected to photo site to approve access to their photos.
> - The service provider correlates the opensocial owner ID of the user
> with their OAuth token, i.e. it stores a mapping like this:
>
> 12...@example-social-network.com -> bea...@photosite.com.
>
> Subsequent requests from the gadget are made using signed fetch, with
> use_oauth_token=optional, sign_owner=true, and sign_viewer=true. When
> a friend views my page, the request to the service provider does not
> include my OAuth token, but it does include the opensocial ids from
> the SNS:
>
> Owner: 12...@example-social-network.com
> Viewer 67...@example-socail-network.com

OK. Now SP know who on SNS is who on their DB. Also, Consumer has
access token for fetching SP's resource.

- For resource owner, consumer will behave as:
[use_oauth_token=yes]: use access token. when expired, authenticate again.
[use_oauth_token=no]: always use signed fetch without using the token.
[use_oauth_token=optional]: use access token unless it's expired. when
expired, use signed fetch.

- For resource viewer, consumer will always use signed fetch without
using the token. If the resource needs access rights, SP can Reverse
Phone Home to fetch social graph in the background to see if the
viewer is friend with the owner.

Am I understanding right?


> The photo site can look up my photos based on the owner id, and it can
> look up the friend graph by calling back to example-social-network
> with the REST-ful APIs.
>
> Does this sound like it would meet your use case?

If my assumption above is correct, it seems to work.
But for the complicated spec, I still need some more investigations
and practice.

By the way, I believe there still is no container which accepts
consumer_key/secret from developer to let gadget makeRequest with SP
using signed fetch.
What do you think is the best practice for doing this on container?
Just a plain HTML form on gadget development page to enter
consumer_key/secret is fine?

Reply all
Reply to author
Forward
0 new messages