On Fri, Dec 4, 2009 at 3:00 PM, David Recordon <
reco...@gmail.com> wrote:
> Sorry for the late notice, but we're hosting a small meeting to go
> over some Facebook Connect driven use cases for WRAP this coming
> Tuesday at our office in Palo Alto. We're really limited on space, so
> please let me know if you'd also like to attend instead of just
> showing up. :)
Sorry for the delay in posting the meeting minutes. I blame David.
OAuth WRAP for Pure Javascript Clients Meetup
Username/Password flow for FaceBook:
- only exposed to trusted partners
- only recommended if partner cannot open a web browser, e.g. devices
- examples: xbox, FB iphone app.
- main reason for not opening a web browser is user experience
- requests are signed with md5 and API key
- FB would be willing to give that up, replace with sending API key over https
- some risk of password cracking with this API
- Y! and Google have similar interfaces for similar use cases, but
sometimes require CAPTCHA for rate limiting
- the API key can also help rate limiting, but not if every device has
the same API key
Old Token flow for FaceBook
Direct user to
http://facebook.com/login.php?api_key=XXX&next=http://www.app.com/callback
User approves, dialog redirects to
http://www.app.com/callback?auth_token=YYY
Use case is mainly for old desktop/mobile apps, and some web sites.
Very similar to OAuth 1.0.
Passing control back to desktop app uses various tricks:
- desktop app runs a web server on localhost
- desktop app reads URL from web page
Above use cases very similar to rich client app profile in WRAP.
Third use case: if app really can't get token back from FB, there is a
flow where the desktop app creates a token, then user approves token
in web browser. WRAP requires that user cut and paste verification
code back into app instead. This has same security problem as OAuth
1.0 with session fixation.
Security: requires API key embedded in client apps, no good way to
protect the API key.
NetFlix Type Flow
There are use cases where entering codes/text on devices is hard,
because input tools are limited or non-existent. For example:
- user turns on television, plugs in new device
- device talks to NetFlix server, gets verification code
- verification code displayed on TV screen
- user visits
netflix.com, logs in.
- user copies code from TV screen to netflix
- user clicks "OK" on TV remote
- device is now authorized to fetch user's data from NetFlix.
This flow is basically OAuth 1.0, and has the same session fixation
attack. But it's a major usability win on some devices. We think we
can find appropriate messaging to make session fixation attacks
unlikely to succeed. Seems like a useful WRAP profile.
FB Connect Flow
Used for both desktop apps and web apps.
Direct user to
http://facebook.com/login.php?api_key=XXX&next=http://www.app.com/callback&return_session=1
User approves, dialog redirects to
http://www.app.com/callback?session=YYY
Use same tricks to pass control back to desktop apps.
Web apps can use server-side callback URL, or they can use
browser-based cross-domain communication via URL
fragments/window.postMessage/Flash. Server side callback URL is
http://www.app.com/xd_receiver.htm.
Requires preregistration of next URLs, tied to API key.
Security: comes from next URL validation rather than API key, no need
for API secret.
By default, session expires in hours, but refresh happens
automatically via background javascript pings. Session expires
automatically when user logs out of facebook. There is also an option
for apps to ask for "offline access", in which case session token
never expires.
Slightly simplified version of OAuth WRAP Rich App profile, but there
really is no equivalent in WRAP.
Callback URL validation is complicated, see Brent's note to
oauth-wrap-wg mailing list on this.
Two risks from callback URLs: one is spam, the other is leaking
session tokens via open redirectors or referers to third-party
content.
Spam is dealt with reactively.
Session token leakage is sometimes prevented by passing tokens in URL
hash fragment. Developers have incentive not to register open
redirectors as callback URL.
Default behavior is to use xd_receiver.htm, which gets the security
right, no leakage in referer or open redirector.
There are use cases for both identity and data access, web site can
call session.getLoggedInUser() to figure out who is at the browser.
Identity messages are passed back via browser, signed with API key.
Relying party can also make a server-to-server call to get identity
associated with session.
Interesting user experience optimization: what if the relying party
site knows the user-id, but identity provider does not? The RP can
pass a hint on the user-id to the identity provider. The identity
provider can optimize the user experience by prefilling login boxes,
or selecting automatically from multiple active sessions.
General consensus: passing session token back on URL fragment is a good idea.
Should this be a "javascript flow"?
Should this even be a "javascript flow", or should it be independent
of javascript bindings?
On one hand, we want people to be able to use ActionScript and other
client-side languages. Thick javascript bindings may not be reusable
across service providers.
On the other hand, standardizing best practices is a good idea.
Should we document best practices?
Should we provide standard libraries that implement best practices?
There is general consensus that we cannot standardize cross-domain
transport entirely; there are dozens of ways to do this in the wild,
with more being discovered all the time. This is a technical problem,
and there is going to be lots of innovation. Maybe someday we can all
standardize on window.postMessage, but browser support not prevalent
enough yet.
We can standardize bootstrapping trust cross-domain, though, if we are
willing to require that relying party sites host a single URL.
What is API key registration for?
Main point is to get developer to agree to developer terms of service (TOS).
Also used to get contact information for developer.
Also provides a point from which to start building up reputation of
apps. (Apps start up with no permissions, then build up users and
trust over time.)
Proposed WRAP Profile to support JS clients (maybe based on rich app
profile, maybe web app profile?)
Client does full page redirect to authorization server:
/authorization?
client_id=ABC
callback=
http://client-site.example.com/somepage
state=
scope=<some-scope>
Authorization server authenticates client via callback URL, asks user
to approve.
Authorization server redirects back to
http://client-site.example.com/somepage# (parameters on fragment):
state=...
access_token=<wrap-access-token>
Client server uses token via various tricks, e.g. jsonp:
<script src="
https://protected-resource/api_call?token=<wrap-access-token>"></script>
Security risks here are basically around how long token is valid, and
how it can leak.
- referer headers
- open redirectors
- browser history
- unencrypted http connections
Existing WRAP use cases provide security via server-to-server calls
via long-lived refresh token.
FB security model is mostly around checking that the user is still at
the browser, the browser cookies fill the same role as the refresh
token.
But FB also has an off-line access use case.
General consensus is that it doesn't make sense to combine permanent
access with pure javascript clients, pure javascript client can't even
run if the user isn't present. There are different use
cases/risks/etc.
How should we signal this new profile?
- maybe we should define different URLs at the authorization server?
- maybe we need a standard wrap_profile=X parameter?
- Simpler for developers to know about a single URL?
Can we standardize on a mechanism to refresh the session via browser
cookie at the authorization server?
Goal is to extend the lifetime on the session, but
- only if the user is still logged in
- without user interaction
Does not require passing in old active token.
No huge objections to doing this with iframe redirects, maybe a
special parameter ispassive=true or openid mode check-immediate.
How do we pass back identity parameters as well?
- additional signed blob in authentication redirect? (e.g FBConnect)
- embedded signed parameters in access token? (e.g Simple Web Token model)
- unsigned parameter in authentication redirect, only for use in javascript?
If the first thing every developer does is ask who a particular token
belongs to, why not just pass that along?
Developers don't understand the technical differences between
delegation protocols and authentication protocols, and they need them
to be the same protocol.
UX requirement: a single user approval page for both identity and delegation.
Does solving identity also require solving discovery?
- probably not. developers tend to hard code configuration for
particular identity providers and service providers.
Some security concerns about how identity is signed that aren't
present for delegation use cases. For identity, better to have
public/private key signings. For delegation, doesn't matter, most
people are using HMAC. Key management is much harder with HMAC.
Do we need signing at all? Yes, because in some use cases the
authentication message is bounced through untrusted third-party (e.g.
the browser).
In other cases, no. Just use a server-to-server call instead. (e.g.
client sends access token to Twitter, asks what user the token belongs
to.)
Not everyone is willing to pay the cost for a server-to-server call.
Options:
- pass it unsigned, but know it is only trustworthy for client-side
display purposes.
- make an API call, server-to-server, to verify it
- sign it as an extra parameter (beaton says we need a standard way to do this)
- make access tokens non-opaque, sign them