launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #17029
[Merge] lp:~wgrant/launchpad/oauth-secret-split into lp:launchpad
William Grant has proposed merging lp:~wgrant/launchpad/oauth-secret-split into lp:launchpad with lp:~wgrant/launchpad/oauth-secret-checking as a prerequisite.
Commit message:
Change OAuth token generation APIs to return the secret as well as the token, as the token soon won't know the plaintext secret.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~wgrant/launchpad/oauth-secret-split/+merge/224762
Change OAuth token generation APIs to return the secret as well as the token, as the token soon won't know the plaintext secret.
--
https://code.launchpad.net/~wgrant/launchpad/oauth-secret-split/+merge/224762
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~wgrant/launchpad/oauth-secret-split into lp:launchpad.
=== modified file 'lib/lp/services/oauth/browser/__init__.py'
--- lib/lp/services/oauth/browser/__init__.py 2013-04-11 02:12:09 +0000
+++ lib/lp/services/oauth/browser/__init__.py 2014-06-27 08:22:29 +0000
@@ -46,7 +46,7 @@
class JSONTokenMixin:
def getJSONRepresentation(self, permissions, token=None,
- include_secret=False):
+ secret=None):
"""Return a JSON representation of the authorization policy.
This includes a description of some subset of OAuthPermission,
@@ -56,8 +56,8 @@
if token is not None:
structure['oauth_token'] = token.key
structure['oauth_token_consumer'] = token.consumer.key
- if include_secret:
- structure['oauth_token_secret'] = token.secret
+ if secret is not None:
+ structure['oauth_token_secret'] = secret
access_levels = [{
'value': permission.name,
'title': permission.title,
@@ -93,7 +93,7 @@
if not check_oauth_signature(self.request, consumer, None):
return u''
- token = consumer.newRequestToken()
+ token, secret = consumer.newRequestToken()
if self.request.headers.get('Accept') == HTTPResource.JSON_TYPE:
# Don't show the client the DESKTOP_INTEGRATION access
# level. If they have a legitimate need to use it, they'll
@@ -103,7 +103,7 @@
if (permission != OAuthPermission.DESKTOP_INTEGRATION)
]
return self.getJSONRepresentation(
- permissions, token, include_secret=True)
+ permissions, token, secret=secret)
return u'oauth_token=%s&oauth_token_secret=%s' % (
token.key, token.secret)
@@ -442,7 +442,7 @@
'End-user refused to authorize request token.')
try:
- access_token = token.createAccessToken()
+ access_token, access_secret = token.createAccessToken()
except OAuthValidationError as e:
return self._set_status_and_error(e)
@@ -450,5 +450,5 @@
if access_token.context is not None:
context_name = access_token.context.name
body = u'oauth_token=%s&oauth_token_secret=%s&lp.context=%s' % (
- access_token.key, access_token.secret, context_name)
+ access_token.key, access_secret, context_name)
return body
=== modified file 'lib/lp/services/oauth/doc/oauth-pages.txt'
--- lib/lp/services/oauth/doc/oauth-pages.txt 2011-12-24 17:49:30 +0000
+++ lib/lp/services/oauth/doc/oauth-pages.txt 2014-06-27 08:22:29 +0000
@@ -17,7 +17,7 @@
>>> consumer = getUtility(IOAuthConsumerSet).getByKey('launchpad-library')
>>> root = getUtility(ILaunchpadRoot)
>>> def get_view_with_fresh_token(form):
- ... token = consumer.newRequestToken()
+ ... token, _ = consumer.newRequestToken()
... form.update({'oauth_token': token.key})
... request = LaunchpadTestRequest(form=form)
... login('salgado@xxxxxxxxxx', request)
=== modified file 'lib/lp/services/oauth/doc/oauth.txt'
--- lib/lp/services/oauth/doc/oauth.txt 2014-01-30 15:04:06 +0000
+++ lib/lp/services/oauth/doc/oauth.txt 2014-06-27 08:22:29 +0000
@@ -18,7 +18,7 @@
Here's a quick demonstration of the behaviour.
>>> login('foo.bar@xxxxxxxxxxxxx')
- >>> access_token = factory.makeOAuthAccessToken()
+ >>> access_token, _ = factory.makeOAuthAccessToken()
>>> logout()
- We can use a nonce.
=== modified file 'lib/lp/services/oauth/interfaces.py'
--- lib/lp/services/oauth/interfaces.py 2014-06-27 08:22:29 +0000
+++ lib/lp/services/oauth/interfaces.py 2014-06-27 08:22:29 +0000
@@ -87,10 +87,11 @@
"""Check if a secret is valid for this consumer."""
def newRequestToken():
- """Return a new `IOAuthRequestToken` with a random key and secret.
+ """Return a new `IOAuthRequestToken` and its random secret.
- The other attributes of the token are supposed to be set whenever the
- user logs into Launchpad and grants (or not) access to this consumer.
+ The key and secret are random, while the other attributes of the
+ token are supposed to be set whenever the user logs into
+ Launchpad and grants (or not) access to this consumer.
"""
def getAccessToken(key):
@@ -272,6 +273,8 @@
def createAccessToken():
"""Create an `IOAuthAccessToken` identical to this request token.
+ The new token and its secret are returned.
+
After the access token is created, this one is deleted as it can't be
used anymore.
=== modified file 'lib/lp/services/oauth/model.py'
--- lib/lp/services/oauth/model.py 2014-06-27 08:22:29 +0000
+++ lib/lp/services/oauth/model.py 2014-06-27 08:22:29 +0000
@@ -178,8 +178,8 @@
def newRequestToken(self):
"""See `IOAuthConsumer`."""
key, secret = create_token_key_and_secret(table=OAuthRequestToken)
- return OAuthRequestToken(
- consumer=self, key=key, secret=secret)
+ return (
+ OAuthRequestToken(consumer=self, key=key, secret=secret), secret)
def getAccessToken(self, key):
"""See `IOAuthConsumer`."""
@@ -401,7 +401,7 @@
"A new OAuth token consumer was enabled in Launchpad.")
self.destroySelf()
- return access_token
+ return access_token, secret
@property
def is_reviewed(self):
=== modified file 'lib/lp/services/oauth/stories/access-token.txt'
--- lib/lp/services/oauth/stories/access-token.txt 2011-12-24 17:49:30 +0000
+++ lib/lp/services/oauth/stories/access-token.txt 2014-06-27 08:22:29 +0000
@@ -13,7 +13,7 @@
>>> from lp.testing import login, logout
>>> login('salgado@xxxxxxxxxx')
>>> consumer = getUtility(IOAuthConsumerSet).getByKey('foobar123451432')
- >>> token = consumer.newRequestToken()
+ >>> token, secret = consumer.newRequestToken()
>>> salgado = getUtility(IPersonSet).getByName('salgado')
>>> token.review(salgado, OAuthPermission.WRITE_PUBLIC)
>>> logout()
@@ -25,7 +25,7 @@
... oauth_version='1.0',
... oauth_token=token.key,
... oauth_signature_method='PLAINTEXT',
- ... oauth_signature='&'.join([consumer.secret, token.secret]),
+ ... oauth_signature='&'.join(['', secret]),
... oauth_timestamp=time.time(),
... oauth_nonce='4572616e48616d6d65724c61686176')
>>> anon_browser.open(
@@ -48,7 +48,7 @@
# Create a new request token, with firefox as its context, and review it.
>>> login('salgado@xxxxxxxxxx')
- >>> token = consumer.newRequestToken()
+ >>> token, secret = consumer.newRequestToken()
>>> firefox = getUtility(IProductSet)['firefox']
>>> token.review(salgado, OAuthPermission.WRITE_PUBLIC, context=firefox)
>>> logout()
@@ -56,7 +56,7 @@
# Exchange the request token for an access token.
>>> data2 = data.copy()
>>> data2['oauth_token'] = token.key
- >>> data2['oauth_signature'] = '&'.join([consumer.secret, token.secret])
+ >>> data2['oauth_signature'] = '&'.join(['', secret])
>>> anon_browser.open(
... 'http://launchpad.dev/+access-token', data=urlencode(data2))
>>> print anon_browser.contents
@@ -65,10 +65,10 @@
The consumer shall not attempt to exchange any given request token
before it's been reviewed, though, or it'll get a 401 response.
- >>> token = consumer.newRequestToken()
+ >>> token, secret = consumer.newRequestToken()
>>> data2 = data.copy()
>>> data2['oauth_token'] = token.key
- >>> data2['oauth_signature'] = '&'.join([consumer.secret, token.secret])
+ >>> data2['oauth_signature'] = '&'.join(['', secret])
>>> print http(r"""
... GET /+access-token?%s HTTP/1.1
... Host: launchpad.dev
@@ -80,7 +80,7 @@
If the token is missing or the signature is wrong the response will
also be 401.
- >>> data2['oauth_signature'] = '&'.join(['foobar', token.secret])
+ >>> data2['oauth_signature'] = '&'.join(['foobar', secret])
>>> print http(r"""
... GET /+access-token?%s HTTP/1.1
... Host: launchpad.dev
@@ -105,7 +105,7 @@
exchanged for an access token.
>>> token.review(salgado, OAuthPermission.UNAUTHORIZED)
- >>> data2['oauth_signature'] = '&'.join([consumer.secret, token.secret])
+ >>> data2['oauth_signature'] = '&'.join(['', secret])
>>> print http(r"""
... GET /+access-token?%s HTTP/1.1
... Host: launchpad.dev
=== modified file 'lib/lp/services/oauth/stories/authorize-token.txt'
--- lib/lp/services/oauth/stories/authorize-token.txt 2012-10-03 07:04:24 +0000
+++ lib/lp/services/oauth/stories/authorize-token.txt 2014-06-27 08:22:29 +0000
@@ -8,7 +8,7 @@
>>> def request_token_for(consumer):
... """Helper method to create a request token."""
... login('salgado@xxxxxxxxxx')
- ... token = consumer.newRequestToken()
+ ... token, _ = consumer.newRequestToken()
... logout()
... return token
=== modified file 'lib/lp/services/oauth/stories/managing-tokens.txt'
--- lib/lp/services/oauth/stories/managing-tokens.txt 2013-09-27 04:13:23 +0000
+++ lib/lp/services/oauth/stories/managing-tokens.txt 2014-06-27 08:22:29 +0000
@@ -12,7 +12,7 @@
>>> consumer = factory.makeOAuthConsumer(
... "System-wide: Ubuntu (mycomputer)")
>>> salgado = getUtility(IPersonSet).getByName('salgado')
- >>> desktop_token = factory.makeOAuthAccessToken(
+ >>> desktop_token, _ = factory.makeOAuthAccessToken(
... consumer, salgado, OAuthPermission.DESKTOP_INTEGRATION)
# Create a request token, authorize it for READ_PRIVATE access,
@@ -111,11 +111,11 @@
>>> from lp.registry.interfaces.product import IProductSet
>>> from lp.services.oauth.interfaces import IOAuthConsumerSet
>>> login('salgado@xxxxxxxxxx')
- >>> token = getUtility(IOAuthConsumerSet).getByKey(
+ >>> token, _ = getUtility(IOAuthConsumerSet).getByKey(
... 'launchpad-library').newRequestToken()
>>> token.review(salgado, OAuthPermission.WRITE_PUBLIC,
... context=getUtility(IProductSet)['firefox'])
- >>> access_token = token.createAccessToken()
+ >>> access_token, _ = token.createAccessToken()
>>> logout()
>>> my_browser.open('http://launchpad.dev/~salgado/+oauth-tokens')
>>> print extract_text(find_tag_by_id(my_browser.contents, 'maincontent'))
=== modified file 'lib/lp/services/oauth/tests/test_tokens.py'
--- lib/lp/services/oauth/tests/test_tokens.py 2014-06-27 08:22:29 +0000
+++ lib/lp/services/oauth/tests/test_tokens.py 2014-06-27 08:22:29 +0000
@@ -15,7 +15,6 @@
import pytz
import transaction
from zope.component import getUtility
-from zope.proxy import sameProxiedObjects
from zope.security.interfaces import Unauthorized
from lp.services.mail import stub
@@ -95,7 +94,7 @@
self.tokens = getUtility(IOAuthRequestTokenSet)
def test_getByKey(self):
- token = self.consumer.newRequestToken()
+ token, _ = self.consumer.newRequestToken()
self.assertEquals(token, self.tokens.getByKey(token.key))
def test_getByKey_returns_none_for_unused_key(self):
@@ -106,21 +105,23 @@
"""Tests for OAuth request token objects."""
def test_newRequestToken(self):
- request_token = self.consumer.newRequestToken()
+ request_token, secret = self.consumer.newRequestToken()
verifyObject(IOAuthRequestToken, request_token)
+ self.assertIsInstance(secret, unicode)
+ self.assertEqual(request_token.secret, secret)
def test_key_and_secret_automatically_generated(self):
- request_token = self.consumer.newRequestToken()
+ request_token, secret = self.consumer.newRequestToken()
self.assertEqual(len(request_token.key), 20)
self.assertEqual(len(request_token.secret), 80)
def test_date_created(self):
- request_token = self.consumer.newRequestToken()
+ request_token, _ = self.consumer.newRequestToken()
now = datetime.now(pytz.timezone('UTC'))
self.assertTrue(request_token.date_created <= now)
def test_new_token_is_not_reviewed(self):
- request_token = self.consumer.newRequestToken()
+ request_token, _ = self.consumer.newRequestToken()
self.assertFalse(request_token.is_reviewed)
self.assertEqual(None, request_token.person)
self.assertEqual(None, request_token.date_reviewed)
@@ -132,12 +133,12 @@
self.assertEqual(None, request_token.context)
def test_getRequestToken(self):
- token_1 = self.consumer.newRequestToken()
+ token_1, _ = self.consumer.newRequestToken()
token_2 = self.consumer.getRequestToken(token_1.key)
self.assertEqual(token_1, token_2)
def test_getRequestToken_for_wrong_consumer_returns_none(self):
- token_1 = self.consumer.newRequestToken()
+ token_1, _ = self.consumer.newRequestToken()
consumer_2 = self.factory.makeOAuthConsumer()
self.assertEquals(
None, consumer_2.getRequestToken(token_1.key))
@@ -147,12 +148,12 @@
None, self.consumer.getRequestToken("no-such-token"))
def test_isSecretValid(self):
- token = self.consumer.newRequestToken()
- self.assertTrue(token.isSecretValid(token.secret))
- self.assertFalse(token.isSecretValid(token.secret + 'a'))
+ token, secret = self.consumer.newRequestToken()
+ self.assertTrue(token.isSecretValid(secret))
+ self.assertFalse(token.isSecretValid(secret + 'a'))
def test_token_review(self):
- request_token = self.consumer.newRequestToken()
+ request_token, _ = self.consumer.newRequestToken()
request_token.review(self.person, OAuthPermission.WRITE_PUBLIC)
now = datetime.now(pytz.timezone('UTC'))
@@ -170,7 +171,7 @@
self.assertEquals(request_token.date_expires, None)
def test_token_review_as_unauthorized(self):
- request_token = self.consumer.newRequestToken()
+ request_token, _ = self.consumer.newRequestToken()
request_token.review(self.person, OAuthPermission.UNAUTHORIZED)
# This token has been reviewed, but it may not be used for any
@@ -182,7 +183,7 @@
def test_review_with_expiration_date(self):
# A request token may be associated with an expiration date
# upon review.
- request_token = self.consumer.newRequestToken()
+ request_token, _ = self.consumer.newRequestToken()
request_token.review(
self.person, OAuthPermission.WRITE_PUBLIC,
date_expires=self.in_a_while)
@@ -196,7 +197,7 @@
#
# Setting a request token's date_expires to a date in the past
# is not a good idea, but it won't expire the request token.
- request_token = self.consumer.newRequestToken()
+ request_token, _ = self.consumer.newRequestToken()
request_token.review(
self.person, OAuthPermission.WRITE_PUBLIC,
date_expires=self.a_long_time_ago)
@@ -205,7 +206,7 @@
def _reviewed_token_for_context(self, context_factory):
"""Create and review a request token with a given context."""
- token = self.consumer.newRequestToken()
+ token, _ = self.consumer.newRequestToken()
name = self.factory.getUniqueString('context')
context = context_factory(name)
token.review(
@@ -269,17 +270,19 @@
# a) to show how a request token is exchanged for an access
# token, b) acquire a reference to the request token that was
# used to create the access token.
- request_token = self.consumer.newRequestToken()
+ request_token, _ = self.consumer.newRequestToken()
request_token.review(self.person, OAuthPermission.WRITE_PRIVATE)
- access_token = request_token.createAccessToken()
- return request_token, access_token
+ access_token, access_secret = request_token.createAccessToken()
+ return request_token, access_token, access_secret
def test_exchange_request_token_for_access_token(self):
# Make sure the basic exchange of request token for access
# token works.
- request_token, access_token = (
+ request_token, access_token, access_secret = (
self._exchange_request_token_for_access_token())
verifyObject(IOAuthAccessToken, access_token)
+ self.assertIsInstance(access_secret, unicode)
+ self.assertEqual(access_token.secret, access_secret)
# Make sure the security notification email went out that the new
# token was created.
@@ -289,7 +292,7 @@
self.assertIn('@example.com', to_addr[0])
def test_access_token_inherits_data_fields_from_request_token(self):
- request_token, access_token = (
+ request_token, access_token, _ = (
self._exchange_request_token_for_access_token())
self.assertEquals(request_token.consumer, access_token.consumer)
@@ -309,30 +312,30 @@
# Make sure that specific fields like context and expiration
# date are passed down from request token to access token.
context = self.factory.makeProduct()
- request_token = self.consumer.newRequestToken()
+ request_token, _ = self.consumer.newRequestToken()
request_token.review(
self.person, OAuthPermission.WRITE_PRIVATE,
context=context, date_expires=self.in_a_while)
- access_token = request_token.createAccessToken()
+ access_token, _ = request_token.createAccessToken()
self.assertEquals(request_token.context, access_token.context)
self.assertEquals(
request_token.date_expires, access_token.date_expires)
def test_request_token_disappears_when_exchanged(self):
- request_token, access_token = (
+ request_token, access_token, _ = (
self._exchange_request_token_for_access_token())
self.assertEquals(
None, self.consumer.getRequestToken(request_token.key))
def test_cant_exchange_unreviewed_request_token(self):
# An unreviewed request token cannot be exchanged for an access token.
- token = self.consumer.newRequestToken()
+ token, _ = self.consumer.newRequestToken()
self.assertRaises(OAuthValidationError, token.createAccessToken)
def test_cant_exchange_unauthorized_request_token(self):
# A request token associated with the UNAUTHORIZED
# OAuthPermission cannot be exchanged for an access token.
- token = self.consumer.newRequestToken()
+ token, _ = self.consumer.newRequestToken()
token.review(self.person, OAuthPermission.UNAUTHORIZED)
self.assertRaises(OAuthValidationError, token.createAccessToken)
@@ -347,7 +350,7 @@
def test_write_permission(self):
"""An access token can only be modified by its creator."""
- access_token = self.factory.makeOAuthAccessToken()
+ access_token, _ = self.factory.makeOAuthAccessToken()
def try_to_set():
access_token.permission = AccessLevel.WRITE_PUBLIC
@@ -358,11 +361,11 @@
try_to_set()
def test_isSecretValid(self):
- request_token = self.consumer.newRequestToken()
+ request_token, _ = self.consumer.newRequestToken()
request_token.review(self.person, OAuthPermission.WRITE_PRIVATE)
- token = request_token.createAccessToken()
- self.assertTrue(token.isSecretValid(token.secret))
- self.assertFalse(token.isSecretValid(token.secret + 'a'))
+ token, secret = request_token.createAccessToken()
+ self.assertTrue(token.isSecretValid(secret))
+ self.assertFalse(token.isSecretValid(secret + 'a'))
def test_get_access_tokens_for_person(self):
"""It's possible to get a person's access tokens."""
@@ -375,7 +378,7 @@
def test_expired_access_token_disappears_from_list(self):
person = self.factory.makePerson()
self.assertEquals(person.oauth_access_tokens.count(), 0)
- access_token = self.factory.makeOAuthAccessToken(
+ access_token, _ = self.factory.makeOAuthAccessToken(
self.consumer, person)
self.assertEquals(person.oauth_access_tokens.count(), 1)
@@ -400,25 +403,9 @@
self.context)
self.assertEquals(person.oauth_access_tokens.count(), 1)
- def test_oauth_access_token_for_retrieves_existing_token(self):
- # If there's already a token for a
- # user/consumer key/permission/context, it's retrieved.
- person = self.factory.makePerson()
- self.assertEquals(person.oauth_access_tokens.count(), 0)
- access_token = oauth_access_token_for(
- self.consumer.key, person, OAuthPermission.WRITE_PUBLIC,
- self.context)
- self.assertEquals(person.oauth_access_tokens.count(), 1)
-
- access_token_2 = oauth_access_token_for(
- access_token.consumer.key, access_token.person,
- access_token.permission, access_token.context)
- self.assertEquals(person.oauth_access_tokens.count(), 1)
- self.assertTrue(sameProxiedObjects(access_token, access_token_2))
-
def test_oauth_access_token_string_permission(self):
"""You can pass in a string instead of an OAuthPermission."""
- access_token = oauth_access_token_for(
+ access_token, _ = oauth_access_token_for(
self.consumer.key, self.person, 'WRITE_PUBLIC')
self.assertEqual(access_token.permission, AccessLevel.WRITE_PUBLIC)
=== modified file 'lib/lp/services/webapp/doc/webapp-publication.txt'
--- lib/lp/services/webapp/doc/webapp-publication.txt 2014-02-27 08:39:44 +0000
+++ lib/lp/services/webapp/doc/webapp-publication.txt 2014-06-27 08:22:29 +0000
@@ -919,9 +919,9 @@
>>> salgado = getUtility(IPersonSet).getByName('salgado')
>>> consumer = getUtility(IOAuthConsumerSet).getByKey('foobar123451432')
- >>> token = consumer.newRequestToken()
+ >>> token, _ = consumer.newRequestToken()
>>> token.review(salgado, OAuthPermission.WRITE_PUBLIC)
- >>> access_token = token.createAccessToken()
+ >>> access_token, access_secret = token.createAccessToken()
>>> policy = getUtility(IStoreSelector).pop()
>>> transaction.commit()
>>> form = dict(
@@ -929,7 +929,7 @@
... oauth_token=access_token.key,
... oauth_version='1.0',
... oauth_signature_method='PLAINTEXT',
- ... oauth_signature="&".join([consumer.secret, access_token.secret]),
+ ... oauth_signature="&".join(['', access_secret]),
... oauth_timestamp=time.time(),
... oauth_nonce='1234572616e48616d6d65724c61686176')
>>> test_request, publication = get_request_and_publication(
@@ -1107,16 +1107,16 @@
>>> getUtility(IStoreSelector).push(MasterDatabasePolicy())
>>> salgado = getUtility(IPersonSet).getByName('salgado')
>>> consumer = getUtility(IOAuthConsumerSet).getByKey('foobar123451432')
- >>> token = consumer.newRequestToken()
+ >>> token, _ = consumer.newRequestToken()
>>> firefox = getUtility(IProductSet)['firefox']
>>> token.review(salgado, OAuthPermission.WRITE_PUBLIC, context=firefox)
- >>> access_token = token.createAccessToken()
+ >>> access_token, access_secret = token.createAccessToken()
>>> form = dict(
... oauth_consumer_key='foobar123451432',
... oauth_token=access_token.key,
... oauth_version='1.0',
... oauth_signature_method='PLAINTEXT',
- ... oauth_signature="&".join([consumer.secret, access_token.secret]),
+ ... oauth_signature="&".join(['', access_secret]),
... oauth_timestamp=time.time(),
... oauth_nonce='4572616e48616d6d65724c61686176')
>>> policy = getUtility(IStoreSelector).pop()
=== modified file 'lib/lp/services/webapp/tests/test_authentication.py'
--- lib/lp/services/webapp/tests/test_authentication.py 2014-06-27 08:22:29 +0000
+++ lib/lp/services/webapp/tests/test_authentication.py 2014-06-27 08:22:29 +0000
@@ -60,35 +60,35 @@
return LaunchpadTestRequest(form=form)
def test_valid(self):
- token = self.factory.makeOAuthAccessToken()
- request = self.makeRequest('&%s' % token.secret)
+ token, secret = self.factory.makeOAuthAccessToken()
+ request = self.makeRequest('&%s' % secret)
self.assertTrue(check_oauth_signature(request, token.consumer, token))
def test_bad_secret(self):
- token = self.factory.makeOAuthAccessToken()
- request = self.makeRequest('&%slol' % token.secret)
+ token, secret = self.factory.makeOAuthAccessToken()
+ request = self.makeRequest('&%slol' % secret)
self.assertFalse(check_oauth_signature(request, token.consumer, token))
self.assertEqual(401, request.response.getStatus())
def test_valid_no_token(self):
- token = self.factory.makeOAuthAccessToken()
+ token, _ = self.factory.makeOAuthAccessToken()
request = self.makeRequest('&')
self.assertTrue(check_oauth_signature(request, token.consumer, None))
def test_bad_secret_no_token(self):
- token = self.factory.makeOAuthAccessToken()
+ token, _ = self.factory.makeOAuthAccessToken()
request = self.makeRequest('&lol')
self.assertFalse(check_oauth_signature(request, token.consumer, None))
self.assertEqual(401, request.response.getStatus())
def test_not_plaintext(self):
- token = self.factory.makeOAuthAccessToken()
+ token, _ = self.factory.makeOAuthAccessToken()
request = self.makeRequest('&lol', method='HMAC-SHA1')
self.assertFalse(check_oauth_signature(request, token.consumer, token))
self.assertEqual(400, request.response.getStatus())
def test_bad_signature_format(self):
- token = self.factory.makeOAuthAccessToken()
+ token, _ = self.factory.makeOAuthAccessToken()
request = self.makeRequest('lol')
self.assertFalse(check_oauth_signature(request, token.consumer, token))
self.assertEqual(401, request.response.getStatus())
=== modified file 'lib/lp/services/webapp/tests/test_publication.py'
--- lib/lp/services/webapp/tests/test_publication.py 2013-06-20 05:50:00 +0000
+++ lib/lp/services/webapp/tests/test_publication.py 2014-06-27 08:22:29 +0000
@@ -100,10 +100,10 @@
# Create an access token for our new person.
consumer = getUtility(IOAuthConsumerSet).new('test-consumer')
- request_token = consumer.newRequestToken()
+ request_token, _ = consumer.newRequestToken()
request_token.review(
person, permission=OAuthPermission.READ_PUBLIC, context=None)
- access_token = request_token.createAccessToken()
+ access_token, _ = request_token.createAccessToken()
# Use oauth.OAuthRequest just to generate a dictionary containing all
# the parameters we need to use in a valid OAuth request, using the
=== modified file 'lib/lp/testing/_webservice.py'
--- lib/lp/testing/_webservice.py 2013-04-10 09:12:32 +0000
+++ lib/lp/testing/_webservice.py 2014-06-27 08:22:29 +0000
@@ -60,7 +60,7 @@
:param context: The OAuth context for the credentials (or a string
designating same).
- :return: An OAuthAccessToken object.
+ :return: A tuple of an OAuthAccessToken object and its secret.
"""
if isinstance(person, basestring):
# Look up a person by name.
@@ -79,23 +79,11 @@
consumer = consumer_set.getByKey(consumer_name)
if consumer is None:
consumer = consumer_set.new(consumer_name)
- else:
- # We didn't have to create the consumer. Maybe this user
- # already has an access token for this
- # consumer+person+permission?
- existing_token = [token for token in person.oauth_access_tokens
- if (token.consumer == consumer
- and token.permission == permission
- and token.context == context)]
- if len(existing_token) >= 1:
- return existing_token[0]
- # There is no existing access token for this
- # consumer+person+permission+context. Create one and review it.
- request_token = consumer.newRequestToken()
+ request_token, _ = consumer.newRequestToken()
request_token.review(person, permission, context)
- access_token = request_token.createAccessToken()
- return access_token
+ access_token, access_secret = request_token.createAccessToken()
+ return access_token, access_secret
def launchpadlib_credentials_for(
@@ -117,11 +105,10 @@
# PageTestLayer, when a Launchpad instance is running for
# launchpadlib to use.
login(ANONYMOUS)
- access_token = oauth_access_token_for(
+ access_token, access_secret = oauth_access_token_for(
consumer_name, person, permission, context)
logout()
- launchpadlib_token = AccessToken(
- access_token.key, access_token.secret)
+ launchpadlib_token = AccessToken(access_token.key, access_secret)
return Credentials(consumer_name=consumer_name,
access_token=launchpadlib_token)
=== modified file 'lib/lp/testing/factory.py'
--- lib/lp/testing/factory.py 2014-06-20 10:53:51 +0000
+++ lib/lp/testing/factory.py 2014-06-27 08:22:29 +0000
@@ -4166,7 +4166,7 @@
"""Create a (possibly reviewed) OAuth request token."""
if consumer is None:
consumer = self.makeOAuthConsumer()
- token = consumer.newRequestToken()
+ token, _ = consumer.newRequestToken()
if reviewed_by is not None:
# Review the token before modifying the date_created,
=== modified file 'lib/lp/testing/pages.py'
--- lib/lp/testing/pages.py 2013-09-27 04:13:23 +0000
+++ lib/lp/testing/pages.py 2014-06-27 08:22:29 +0000
@@ -715,9 +715,9 @@
consumer = oacs.getByKey(consumer_key)
if consumer is None:
consumer = oacs.new(consumer_key)
- request_token = consumer.newRequestToken()
+ request_token, _ = consumer.newRequestToken()
request_token.review(person, permission, context)
- access_token = request_token.createAccessToken()
+ access_token, _ = request_token.createAccessToken()
logout()
service = LaunchpadWebServiceCaller(consumer_key, access_token.key)
service.user = person
Follow ups