@@ -44,11 +44,13 @@ def _handle_error_response(response_data):
44
44
"""Translates an error response into an exception.
45
45
46
46
Args:
47
- response_data (Mapping): The decoded response data.
47
+ response_data (Mapping | str ): The decoded response data.
48
48
49
49
Raises:
50
50
google.auth.exceptions.RefreshError: The errors contained in response_data.
51
51
"""
52
+ if isinstance (response_data , six .string_types ):
53
+ raise exceptions .RefreshError (response_data )
52
54
try :
53
55
error_details = "{}: {}" .format (
54
56
response_data ["error" ], response_data .get ("error_description" )
@@ -79,7 +81,13 @@ def _parse_expiry(response_data):
79
81
80
82
81
83
def _token_endpoint_request_no_throw (
82
- request , token_uri , body , access_token = None , use_json = False
84
+ request ,
85
+ token_uri ,
86
+ body ,
87
+ access_token = None ,
88
+ use_json = False ,
89
+ expected_status_code = http_client .OK ,
90
+ ** kwargs
83
91
):
84
92
"""Makes a request to the OAuth 2.0 authorization server's token endpoint.
85
93
This function doesn't throw on response errors.
@@ -93,6 +101,16 @@ def _token_endpoint_request_no_throw(
93
101
access_token (Optional(str)): The access token needed to make the request.
94
102
use_json (Optional(bool)): Use urlencoded format or json format for the
95
103
content type. The default value is False.
104
+ expected_status_code (Optional(int)): The expected the status code of
105
+ the token response. The default value is 200. We may expect other
106
+ status code like 201 for GDCH credentials.
107
+ kwargs: Additional arguments passed on to the request method. The
108
+ kwargs will be passed to `requests.request` method, see:
109
+ https://docs.python-requests.org/en/latest/api/#requests.request.
110
+ For example, you can use `cert=("cert_pem_path", "key_pem_path")`
111
+ to set up client side SSL certificate, and use
112
+ `verify="ca_bundle_path"` to set up the CA certificates for sever
113
+ side SSL certificate verification.
96
114
97
115
Returns:
98
116
Tuple(bool, Mapping[str, str]): A boolean indicating if the request is
@@ -112,32 +130,46 @@ def _token_endpoint_request_no_throw(
112
130
# retry to fetch token for maximum of two times if any internal failure
113
131
# occurs.
114
132
while True :
115
- response = request (method = "POST" , url = token_uri , headers = headers , body = body )
133
+ response = request (
134
+ method = "POST" , url = token_uri , headers = headers , body = body , ** kwargs
135
+ )
116
136
response_body = (
117
137
response .data .decode ("utf-8" )
118
138
if hasattr (response .data , "decode" )
119
139
else response .data
120
140
)
121
- response_data = json .loads (response_body )
122
141
123
- if response .status == http_client .OK :
142
+ if response .status == expected_status_code :
143
+ # response_body should be a JSON
144
+ response_data = json .loads (response_body )
124
145
break
125
146
else :
126
- error_desc = response_data .get ("error_description" ) or ""
127
- error_code = response_data .get ("error" ) or ""
128
- if (
129
- any (e == "internal_failure" for e in (error_code , error_desc ))
130
- and retry < 1
131
- ):
132
- retry += 1
133
- continue
134
- return response .status == http_client .OK , response_data
135
-
136
- return response .status == http_client .OK , response_data
147
+ # For a failed response, response_body could be a string
148
+ try :
149
+ response_data = json .loads (response_body )
150
+ error_desc = response_data .get ("error_description" ) or ""
151
+ error_code = response_data .get ("error" ) or ""
152
+ if (
153
+ any (e == "internal_failure" for e in (error_code , error_desc ))
154
+ and retry < 1
155
+ ):
156
+ retry += 1
157
+ continue
158
+ except ValueError :
159
+ response_data = response_body
160
+ return False , response_data
161
+
162
+ return response .status == expected_status_code , response_data
137
163
138
164
139
165
def _token_endpoint_request (
140
- request , token_uri , body , access_token = None , use_json = False
166
+ request ,
167
+ token_uri ,
168
+ body ,
169
+ access_token = None ,
170
+ use_json = False ,
171
+ expected_status_code = http_client .OK ,
172
+ ** kwargs
141
173
):
142
174
"""Makes a request to the OAuth 2.0 authorization server's token endpoint.
143
175
@@ -150,6 +182,16 @@ def _token_endpoint_request(
150
182
access_token (Optional(str)): The access token needed to make the request.
151
183
use_json (Optional(bool)): Use urlencoded format or json format for the
152
184
content type. The default value is False.
185
+ expected_status_code (Optional(int)): The expected the status code of
186
+ the token response. The default value is 200. We may expect other
187
+ status code like 201 for GDCH credentials.
188
+ kwargs: Additional arguments passed on to the request method. The
189
+ kwargs will be passed to `requests.request` method, see:
190
+ https://docs.python-requests.org/en/latest/api/#requests.request.
191
+ For example, you can use `cert=("cert_pem_path", "key_pem_path")`
192
+ to set up client side SSL certificate, and use
193
+ `verify="ca_bundle_path"` to set up the CA certificates for sever
194
+ side SSL certificate verification.
153
195
154
196
Returns:
155
197
Mapping[str, str]: The JSON-decoded response data.
@@ -159,7 +201,13 @@ def _token_endpoint_request(
159
201
an error.
160
202
"""
161
203
response_status_ok , response_data = _token_endpoint_request_no_throw (
162
- request , token_uri , body , access_token = access_token , use_json = use_json
204
+ request ,
205
+ token_uri ,
206
+ body ,
207
+ access_token = access_token ,
208
+ use_json = use_json ,
209
+ expected_status_code = expected_status_code ,
210
+ ** kwargs
163
211
)
164
212
if not response_status_ok :
165
213
_handle_error_response (response_data )
0 commit comments