|
3 | 3 |
|
4 | 4 | import json
|
5 | 5 | try:
|
6 |
| - from urllib.parse import urlencode, parse_qs |
| 6 | + from urllib.parse import urlencode, parse_qs, quote_plus |
7 | 7 | except ImportError:
|
8 | 8 | from urlparse import parse_qs
|
9 |
| - from urllib import urlencode |
| 9 | + from urllib import urlencode, quote_plus |
10 | 10 | import logging
|
11 | 11 | import warnings
|
12 | 12 | import time
|
@@ -205,9 +205,14 @@ def _obtain_token( # The verb "obtain" is influenced by OAUTH2 RFC 6749
|
205 | 205 | # client credentials in the request-body using the following
|
206 | 206 | # parameters: client_id, client_secret.
|
207 | 207 | if self.client_secret and self.client_id:
|
208 |
| - _headers["Authorization"] = "Basic " + base64.b64encode( |
209 |
| - "{}:{}".format(self.client_id, self.client_secret) |
210 |
| - .encode("ascii")).decode("ascii") |
| 208 | + _headers["Authorization"] = "Basic " + base64.b64encode("{}:{}".format( |
| 209 | + # Per https://tools.ietf.org/html/rfc6749#section-2.3.1 |
| 210 | + # client_id and client_secret needs to be encoded by |
| 211 | + # "application/x-www-form-urlencoded" |
| 212 | + # https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 |
| 213 | + # BEFORE they are fed into HTTP Basic Authentication |
| 214 | + quote_plus(self.client_id), quote_plus(self.client_secret) |
| 215 | + ).encode("ascii")).decode("ascii") |
211 | 216 |
|
212 | 217 | if "token_endpoint" not in self.configuration:
|
213 | 218 | raise ValueError("token_endpoint not found in configuration")
|
|
0 commit comments