Merge lp:~leonardr/launchpad/anonymous-oauth into lp:launchpad/db-devel
| Status: | Merged |
|---|---|
| Approved by: | Guilherme Salgado on 2010-01-04 |
| Approved revision: | not available |
| Merged at revision: | not available |
| Proposed branch: | lp:~leonardr/launchpad/anonymous-oauth |
| Merge into: | lp:launchpad/db-devel |
| Diff against target: |
837 lines (+406/-63) 17 files modified
lib/canonical/launchpad/doc/account.txt (+7/-2) lib/canonical/launchpad/interfaces/account.py (+8/-8) lib/canonical/launchpad/pagetests/webservice/xx-service.txt (+72/-0) lib/canonical/launchpad/security.py (+36/-25) lib/canonical/launchpad/testing/pages.py (+31/-5) lib/canonical/launchpad/webapp/servers.py (+35/-3) lib/canonical/launchpad/zcml/account.zcml (+4/-1) lib/lp/bugs/scripts/checkwatches.py (+10/-1) lib/lp/bugs/scripts/tests/test_checkwatches.py (+83/-0) lib/lp/registry/browser/configure.zcml (+1/-1) lib/lp/registry/browser/person.py (+29/-6) lib/lp/registry/doc/person-account.txt (+2/-2) lib/lp/registry/stories/person/xx-admin-person-review.txt (+55/-1) lib/lp/registry/templates/person-review.pt (+2/-1) lib/lp/services/permission_helpers.py (+29/-4) lib/lp/translations/model/translationimportqueue.py (+1/-2) versions.cfg (+1/-1) |
| To merge this branch: | bzr merge lp:~leonardr/launchpad/anonymous-oauth |
| Related bugs: |
| Reviewer | Review Type | Date Requested | Status |
|---|---|---|---|
| Guilherme Salgado (community) | code | 2009-12-15 | Approve on 2010-01-04 |
|
Review via email:
|
|||
| Leonard Richardson (leonardr) wrote : | # |
| Guilherme Salgado (salgado) wrote : | # |
Hi Leonard,
This looks good; I have only a couple suggestions.
review needsfixing
On Tue, 2009-12-15 at 15:13 +0000, Leonard Richardson wrote:
> === modified file 'lib/canonical/
> --- lib/canonical/
> +++ lib/canonical/
> @@ -56,6 +56,39 @@
> HTTP/1.1 404 Not Found
> ...
>
> +== Anonymous requests ==
> +
> +A properly signed web service request whose OAuth token key is empty
> +is treated as an anonymous request.
> +
> + >>> root = 'http://
> + >>> body = anon_webservice
> + >>> print body['projects_
> + http://
> + >>> print body['me_link']
> + http://
> +
> +Anonymous requests can't access certain data:
> +
> + >>> response = anon_webservice
> + >>> print response.
> + 401 Unauthorized
> + >>> print response.body
> + You need to be logged in to view this URL.
> + ...
> +
> +Anonymous requests can't change the dataset.
> +
> + >>> import simplejson
> + >>> data = simplejson.
> + >>> response = anon_webservice
> + ... 'application/json', data)
> + >>> print response.
> + 401 Unauthorized
> + >>> print response.body
> + ...
> + Unauthorized: (<Person at...>, 'displayname', 'launchpad.Edit')
> + ...
>
> == API Requests to other hosts ==
>
>
> === modified file 'lib/canonical/
> --- lib/canonical/
> +++ lib/canonical/
> @@ -20,7 +20,8 @@
> from BeautifulSoup import (
> BeautifulSoup, CData, Comment, Declaration, NavigableString, PageElement,
> ProcessingInstr
> -from contrib.oauth import OAuthRequest, OAuthSignatureM
> +from contrib.oauth import (
> + OAuthConsumer, OAuthRequest, OAuthSignatureM
> from urlparse import urljoin
>
> from zope.app.
> @@ -95,10 +96,15 @@
> """
> if oauth_consumer_key is not None and oauth_access_key is not None:
> login(ANONYMOUS)
> - self.consumer = getUtility(
> - oauth_consumer_key)
> - self.access_token = self.consumer.
> - oauth_access_key)
> + consumers = getUtility(
> + self.consumer = consumers.
> + if self.consumer is None:
I find it really confusing that you rely on a non-registered consumer to
identify anonymous access here -- I was expecting you'd use an empty
token key for that.
To do that, though, you'll need to use the 'launchpad-library' as the
consumer key of your anon_webservice below, but when you do th...
| Leonard Richardson (leonardr) wrote : | # |
Check the incremental diff: http://
| Guilherme Salgado (salgado) wrote : | # |
> === modified file 'lib/canonical/
> --- lib/canonical/
> +++ lib/canonical/
> @@ -99,12 +99,24 @@
> consumers = getUtility(
> self.consumer = consumers.
> if self.consumer is None:
> - # Set up for anonymous access
> + # The client wants to make a request using an
> + # unrecognized consumer key. Only an anonymous request
> + # (one in which oauth_access_key is the empty string)
> + # will succeed, but we run this code in either case,
> + # so that we can verify that a non-anonymous request
> + # fails.
> self.consumer = OAuthConsumer(
> - self.access_token = OAuthToken('', '')
> + self.access_token = OAuthToken(
> else:
> - self.access_token = self.consumer.
> - oauth_access_key)
> + if oauth_access_key == '':
> + # The client wants to make an anonymous request
> + # using a recognized consumer key.
> + self.access_token = OAuthToken(
> + else:
> + # The client wants to make an authorized request
> + # using a recognized consumer key.
> + self.access_token = self.consumer.
> + oauth_access_key)
Although this is now making it clear that we identify anonymous requests
by the lack of an access key, I think this can be simplified a bit.
This is what I had in mind when I first commented on this change.
if oauth_access_key == '':
# The client wants to make an anonymous request.
if self.consumer is None:
# Anonymous requests don't need a registered consumer, so we
# manually create a "fake" OauthConsumer (we call it "fake"
# because it's not really an IOAuthConsumer as returned by
# IOAuthConsumerS
else:
assert self.consumer is not None, (
"Need a registered consumer key for authenticated requests.")
It's untested but I think it's equivalent to what you have.
> logout()
> else:
> self.consumer = None
> @@ -660,7 +672,7 @@
> test.globs[
> 'launchpad-
> test.globs[
> - 'anonymous-access', '')
> + 'launchpad-
> test.globs[
> test.globs[
> test.globs['a...

This branch fixes bug 385517 (but not all of it: see bug 496964). It allows OAuth requests to bypass the normal verification process (and enjoy the privileges of the unauthenticated principal) if their token key is the empty string. All the real data the client has to provide is a consumer key.
If a normal request comes in with an unrecognized consumer key, the request is still rejected. Access tokens are associated with specific known consumers, so there's no way that request can be valid. But an anonymous request is valid even if it mentions a consumer key never seen before. If that happens, my branch automatically creates a consumer object associated with the consumer key, so it can be recognized later.
I created an 'anonymous_ webservice' LaunchpadWebSer viceCaller for use in testing anonymous access to the web service, and added some basic tests to xx-service.txt.