= Desktop-wide Launchpad integration =
'''As a ''' third-party developer<
>
'''I want ''' to integrate my application into Launchpad without confusing my end-user<
>
'''so that ''' my end-user will actually use my Launchpad integration features. <
>
Currently, desktop applications and client-side scripts are authorized
to use Launchpad on a per-application basis. This annoys users and
doesn't provide any real security benefit. This LEP describes moving
to a system in which the entire desktop is authorized once and doesn't
need to be authorized again.
'''On Launchpad:''' https://bugs.launchpad.net/launchpad-project/+bugs?field.tag=desktop-integration
== Rationale ==
The most common reaction of a third-party developer faced with our
per-application authorization protocol is: "How can I hack around
this?" Their goal is a better user experience, but they're subverting
our security model and writing code that will eventually break--if it
doesn't start out broken.
Our per-application system was designed for integration of foreign
websites into Launchpad. On the desktop, a per-application system
looks much more impressive (security-wise) than it actually is. By
authorizing the entire desktop at once, we can reduce the annoyance
for users without reducing security, and hopefully get our third parties
to buy into our security model rather than hacking around it.
== Stakeholders ==
Stakeholders I've talked with:
* Launchpad technical architect Robert Collins
* The Ubuntu Single Sign-On team: John Lenton, Naty Bidart, et al.
* Ubuntu architect Allison Randal
* Ubuntu engineering manager Rick Spencer
* Ubuntu security engineer Kees Cook
* Third-party developer Martin Owens
Stakeholders I have yet to talk with:
* Third-party developer Markus Korn
Others I have talked with:
* Ubuntu developer Didier Roche
* Kubuntu developer Jonathan Riddle
== Constraints and Requirements ==
=== Must ===
A single OAuth token must be shared among every launchpadlib client
that calls Launchpad.login_with(). The token will have read-write
access to public and private data.
The desktop token must be authorized by hand, in the end-user's web
browser.
When deciding whether to authorize the desktop token, the user must be
able to see the kind of computer being authorized (eg. "Ubuntu
desktop") and the computer's name (eg. "hostname"). This information
is provided by the computer itself.
The string that launchpadlib clients pass in believing it to be the
OAuth consumer key, must actually be sent as part of the User-Agent
header.
The first client to call Launchpad.login_with() after the new system
is in place will result in a browser open.
After a desktop-wide token is authorized for a given site,
launchpadlib must crawl through .launchpadlib/[site]/credentials and
remove any per-application credentials left over by old versions of
launchpadlib.
The system must work on both GNOME and KDE desktops, storing the token in the GNOME keyring or KDE wallet.
=== Nice to have ===
It should be possible to authorize the desktop for a limited time--for
an hour, a day, or a week. This can be used to test the water, or
when troubleshooting someone else's computer.
The system should not require any new desktop GUI development.
=== Must not ===
Once the user has authorized their desktop, they must not have to
re-authorize it, ever--unless the authorization expires or they
manually revoke it.
== Subfeatures ==
[[https://dev.launchpad.net/LEP/ActivatingDevelopmentFromDesktop|Activating Development From Desktop]] covers a case in which temporary super-privileged tokens may be authorized on a per-application basis.
== Workflows ==
1. Client A calls Launchpad.login_with().
2. launchpadlib acquires an OAuth request token.
3. The user's web browser opens to Launchpad's +authorize-token view.
4. If necessary, the user logs in to Launchpad.
5. The user authorizes the request token and Launchpad issues a desktop-wide access token.
6. launchpadlib exchanges the request token for the access token.
7. launchpadlib stores the desktop-wide access token in the GNOME keyring (or equivalent).
8. launchpadlib initializes a Launchpad object using the access token.
9. Several days later, client B calls Launchpad.login_with().
10. launchpadlib retrieves the desktop-wide access token from the GNOME keyring and uses it to initialize a Launchpad object.
== Success ==
=== How will we know when we are done? ===
We're done when a normal user can integrate any number of applications
and scripts into Launchpad without experiencing more than one browser
open.
''We're done when the pertinent libraries are in Natty.''
=== How will we measure how well we have done? ===
If we do a good job, third-party developers will choose to use the new
system instead of hacks.
== Thoughts? ==
* [[https://lists.launchpad.net/launchpad-dev/msg04940.html|Detailed discussion of this design]]
== What's left? ==
We need to get the pertinent libraries in Natty.