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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
from __future__ import absolute_import
"""
oauthlib.oauth2.draft25.tokens
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This module contains methods for adding two types of access tokens to requests.
- Bearer http://tools.ietf.org/html/draft-ietf-oauth-saml2-bearer-08
- MAC http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-00
"""
from binascii import b2a_base64
import hashlib
import hmac
from urlparse import urlparse
from oauthlib.common import add_params_to_uri, add_params_to_qs
from . import utils
def prepare_mac_header(token, uri, key, http_method, nonce=None, headers=None,
body=None, ext=u'', hash_algorithm=u'hmac-sha-1'):
"""Add an `MAC Access Authentication`_ signature to headers.
Unlike OAuth 1, this HMAC signature does not require inclusion of the request
payload/body, neither does it use a combination of client_secret and
token_secret but rather a mac_key provided together with the access token.
Currently two algorithms are supported, "hmac-sha-1" and "hmac-sha-256",
`extension algorithms`_ are not supported.
Example MAC Authorization header, linebreaks added for clarity
Authorization: MAC id="h480djs93hd8",
nonce="1336363200:dj83hs9s",
mac="bhCQXTVyfj5cmA9uKkPFx1zeOXM="
.. _`MAC Access Authentication`: http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-01
.. _`extension algorithms`: http://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac-01#section-7.1
:param uri: Request URI.
:param headers: Request headers as a dictionary.
:param http_method: HTTP Request method.
:param key: MAC given provided by token endpoint.
:param algorithm: HMAC algorithm provided by token endpoint.
:return: headers dictionary with the authorization field added.
"""
http_method = http_method.upper()
host, port = utils.host_from_uri(uri)
if hash_algorithm.lower() == u'hmac-sha-1':
h = hashlib.sha1
else:
h = hashlib.sha256
nonce = nonce or u'{0}:{1}'.format(utils.generate_nonce(), utils.generate_timestamp())
sch, net, path, par, query, fra = urlparse(uri)
if query:
request_uri = path + u'?' + query
else:
request_uri = path
# Hash the body/payload
if body is not None:
bodyhash = b2a_base64(h(body).digest())[:-1].decode('utf-8')
else:
bodyhash = u''
# Create the normalized base string
base = []
base.append(nonce)
base.append(http_method.upper())
base.append(request_uri)
base.append(host)
base.append(port)
base.append(bodyhash)
base.append(ext)
base_string = '\n'.join(base) + u'\n'
# hmac struggles with unicode strings - http://bugs.python.org/issue5285
if isinstance(key, unicode):
key = key.encode('utf-8')
sign = hmac.new(key, base_string, h)
sign = b2a_base64(sign.digest())[:-1].decode('utf-8')
header = []
header.append(u'MAC id="%s"' % token)
header.append(u'nonce="%s"' % nonce)
if bodyhash:
header.append(u'bodyhash="%s"' % bodyhash)
if ext:
header.append(u'ext="%s"' % ext)
header.append(u'mac="%s"' % sign)
headers = headers or {}
headers[u'Authorization'] = u', '.join(header)
return headers
def prepare_bearer_uri(token, uri):
"""Add a `Bearer Token`_ to the request URI.
Not recommended, use only if client can't use authorization header or body.
http://www.example.com/path?access_token=h480djs93hd8
.. _`Bearer Token`: http://tools.ietf.org/html/draft-ietf-oauth-v2-bearer-18
"""
return add_params_to_uri(uri, [((u'access_token', token))])
def prepare_bearer_headers(token, headers=None):
"""Add a `Bearer Token`_ to the request URI.
Recommended method of passing bearer tokens.
Authorization: Bearer h480djs93hd8
.. _`Bearer Token`: http://tools.ietf.org/html/draft-ietf-oauth-v2-bearer-18
"""
headers = headers or {}
headers[u'Authorization'] = u'Bearer %s' % token
return headers
def prepare_bearer_body(token, body=u''):
"""Add a `Bearer Token`_ to the request body.
access_token=h480djs93hd8
.. _`Bearer Token`: http://tools.ietf.org/html/draft-ietf-oauth-v2-bearer-18
"""
return add_params_to_qs(body, [((u'access_token', token))])
|