1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
= Exchanging a request token for an access token =
Once the user has logged into Launchpad and granted access to the
consumer, the request token is eligible for being exchanged for an
access token.
# First we create a new request token and review it.
>>> from zope.component import getUtility
>>> from lp.services.oauth.interfaces import IOAuthConsumerSet
>>> from lp.services.webapp.interfaces import OAuthPermission
>>> from lp.registry.interfaces.person import IPersonSet
>>> from lp.registry.interfaces.product import IProductSet
>>> from lp.testing import login, logout
>>> login('salgado@ubuntu.com')
>>> consumer = getUtility(IOAuthConsumerSet).getByKey('foobar123451432')
>>> token = consumer.newRequestToken()
>>> salgado = getUtility(IPersonSet).getByName('salgado')
>>> token.review(salgado, OAuthPermission.WRITE_PUBLIC)
>>> logout()
>>> import time
>>> from urllib import urlencode
>>> data = dict(
... oauth_consumer_key='foobar123451432',
... oauth_version='1.0',
... oauth_token=token.key,
... oauth_signature_method='PLAINTEXT',
... oauth_signature='&'.join([consumer.secret, token.secret]),
... oauth_timestamp=time.time(),
... oauth_nonce='4572616e48616d6d65724c61686176')
>>> anon_browser.open(
... 'http://launchpad.dev/+access-token', data=urlencode(data))
>>> print anon_browser.contents
oauth_token=...&oauth_token_secret=...
Any further attempt to exchange that request token for an access token
will fail because request tokens can be used only once.
>>> anon_browser.open(
... 'http://launchpad.dev/+access-token', data=urlencode(data))
Traceback (most recent call last):
...
HTTPError: HTTP Error 401: Unauthorized
The token's context, when not None, is sent to the consumer together
with the token's key and secret.
# Create a new request token, with firefox as its context, and review it.
>>> login('salgado@ubuntu.com')
>>> token = consumer.newRequestToken()
>>> firefox = getUtility(IProductSet)['firefox']
>>> token.review(salgado, OAuthPermission.WRITE_PUBLIC, context=firefox)
>>> logout()
# Exchange the request token for an access token.
>>> data2 = data.copy()
>>> data2['oauth_token'] = token.key
>>> data2['oauth_signature'] = '&'.join([consumer.secret, token.secret])
>>> anon_browser.open(
... 'http://launchpad.dev/+access-token', data=urlencode(data2))
>>> print anon_browser.contents
oauth_token=...&oauth_token_secret=...&lp.context=firefox
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()
>>> data2 = data.copy()
>>> data2['oauth_token'] = token.key
>>> data2['oauth_signature'] = '&'.join([consumer.secret, token.secret])
>>> print http(r"""
... GET /+access-token?%s HTTP/1.1
... Host: launchpad.dev
... """ % urlencode(data2))
HTTP/1.1 401 Unauthorized
...
Request token has not yet been reviewed. Try again later.
If the token is missing or the signature is wrong the response will
also be 401.
>>> data2['oauth_signature'] = '&'.join(['foobar', token.secret])
>>> print http(r"""
... GET /+access-token?%s HTTP/1.1
... Host: launchpad.dev
... """ % urlencode(data2))
HTTP/1.1 401 Unauthorized
...
Invalid OAuth signature.
>>> data3 = data.copy()
>>> del(data3['oauth_token'])
>>> print http(r"""
... GET /+access-token?%s HTTP/1.1
... Host: launchpad.dev
... """ % urlencode(data3))
HTTP/1.1 401 Unauthorized
...
No request token specified.
If the token's permission is set to UNAUTHORIZED, the response code is
403 ("Forbidden"). This conveys that (to quote the HTTP RFC)
"authorization will not help" and that the token can _never_ be
exchanged for an access token.
>>> token.review(salgado, OAuthPermission.UNAUTHORIZED)
>>> data2['oauth_signature'] = '&'.join([consumer.secret, token.secret])
>>> print http(r"""
... GET /+access-token?%s HTTP/1.1
... Host: launchpad.dev
... """ % urlencode(data2))
HTTP/1.1 403 Forbidden
...
End-user refused to authorize request token.
|