def _execute_token_request(self, data, access_token, expect_refresh_token=True): """ Send the request to acquire or refresh an access token. :param data: Dictionary containing the request parameters as specified by the Box API. :type data: `dict` :param access_token: The current access token. :type access_token: `unicode` or None :return: The response for the token request. :rtype: :class:`TokenResponse` """ self._check_closed() url = '{base_auth_url}/token'.format( base_auth_url=self._api_config.OAUTH2_API_URL) headers = {'content-type': 'application/x-www-form-urlencoded'} network_response = self._network_layer.request( 'POST', url, data=data, headers=headers, access_token=access_token, ) if not network_response.ok: raise BoxOAuthException(network_response.status_code, network_response.content, url, 'POST', network_response) try: token_response = TokenResponse(network_response.json()) except ValueError: raise BoxOAuthException(network_response.status_code, network_response.content, url, 'POST', network_response) if ('access_token' not in token_response) or (expect_refresh_token and 'refresh_token' not in token_response): raise BoxOAuthException(network_response.status_code, network_response.content, url, 'POST', network_response) return token_response
def revoke(self): """ Revoke the authorization for the current access/refresh token pair. """ with self._refresh_lock: access_token, refresh_token = self._get_and_update_current_tokens() token_to_revoke = access_token or refresh_token if token_to_revoke is None: return url = '{base_auth_url}/revoke'.format( base_auth_url=API.OAUTH2_API_URL) network_response = self._network_layer.request( 'POST', url, data={ 'client_id': self._client_id, 'client_secret': self._client_secret, 'token': token_to_revoke, }, access_token=access_token, ) if not network_response.ok: raise BoxOAuthException(network_response.status_code, network_response.content, url, 'POST') self._store_tokens(None, None)
def test_auth_retry_for_invalid_exp_claim( jwt_auth_init_mocks, expect_auth_retry, unsuccessful_jwt_response, box_datetime, ): # pylint:disable=redefined-outer-name enterprise_id = 'fake_enterprise_id' with jwt_auth_init_mocks(assert_authed=False) as params: auth = params[0] with patch.object(auth, '_construct_and_send_jwt_auth') as mock_send_jwt: mock_send_jwt.side_effect = [ BoxOAuthException(400, network_response=unsuccessful_jwt_response), 'jwt_token' ] if not expect_auth_retry: with pytest.raises(BoxOAuthException): auth.authenticate_instance(enterprise_id) else: auth.authenticate_instance(enterprise_id) expected_calls = [call(enterprise_id, 'enterprise')] if expect_auth_retry: expected_calls.append( call(enterprise_id, 'enterprise', box_datetime.replace(microsecond=0, tzinfo=None))) assert len(mock_send_jwt.mock_calls) == len(expected_calls) mock_send_jwt.assert_has_calls(expected_calls)
def test_auth_max_retries_for_internal_server_error( jwt_auth_init_mocks, unsuccessful_jwt_response, ): # pylint:disable=redefined-outer-name enterprise_id = 'fake_enterprise_id' with jwt_auth_init_mocks(assert_authed=False) as params: auth = params[0] with patch.object(auth, '_construct_and_send_jwt_auth') as mock_send_jwt: side_effect = [] expected_calls = [] # Retries max number of times, then throws the error for _ in range(API.MAX_RETRY_ATTEMPTS + 1): side_effect.append( BoxOAuthException( 500, network_response=unsuccessful_jwt_response)) expected_calls.append(call(enterprise_id, 'enterprise', None)) mock_send_jwt.side_effect = side_effect with pytest.raises(BoxOAuthException) as error: auth.authenticate_instance(enterprise_id) assert error.value.status == 500 assert len(mock_send_jwt.mock_calls) == len(expected_calls) mock_send_jwt.assert_has_calls(expected_calls)
def test_auth_retry_for_internal_server_error( jwt_auth_init_mocks, unsuccessful_jwt_response, ): # pylint:disable=redefined-outer-name enterprise_id = 'fake_enterprise_id' with jwt_auth_init_mocks(assert_authed=False) as params: auth = params[0] with patch.object(auth, '_construct_and_send_jwt_auth') as mock_send_jwt: side_effect = [] expected_calls = [] # Retries multiple times, but less than max retries. Then succeeds when it gets a token. for _ in range(API.MAX_RETRY_ATTEMPTS - 2): side_effect.append( BoxOAuthException( 500, network_response=unsuccessful_jwt_response)) expected_calls.append(call(enterprise_id, 'enterprise', None)) side_effect.append('jwt_token') expected_calls.append(call(enterprise_id, 'enterprise', None)) mock_send_jwt.side_effect = side_effect auth.authenticate_instance(enterprise_id) assert len(mock_send_jwt.mock_calls) == len(expected_calls) mock_send_jwt.assert_has_calls(expected_calls)
def send_token_request(self, data, access_token, expect_refresh_token=True): """ Send the request to acquire or refresh an access token. :param data: Dictionary containing the request parameters as specified by the Box API. :type data: `dict` :param access_token: The current access token. :type access_token: `unicode` or None :return: The access token and refresh token. :rtype: (`unicode`, `unicode`) """ url = '{base_auth_url}/token'.format(base_auth_url=API.OAUTH2_API_URL) headers = {'content-type': 'application/x-www-form-urlencoded'} network_response = self._network_layer.request( 'POST', url, data=data, headers=headers, access_token=access_token, ) if not network_response.ok: raise BoxOAuthException(network_response.status_code, network_response.content, url, 'POST') try: response = network_response.json() access_token = response['access_token'] refresh_token = response.get('refresh_token', None) if refresh_token is None and expect_refresh_token: raise BoxOAuthException(network_response.status_code, network_response.content, url, 'POST') except (ValueError, KeyError): raise BoxOAuthException(network_response.status_code, network_response.content, url, 'POST') self._store_tokens(access_token, refresh_token) return self._access_token, self._refresh_token
def test_auth_object_is_closed_even_if_revoke_fails(client_id, client_secret, access_token, mock_box_session): auth = OAuth2(client_id=client_id, client_secret=client_secret, access_token=access_token, session=mock_box_session) with patch.object(auth, 'revoke', side_effect=BoxOAuthException(status=500)): with pytest.raises(BoxOAuthException): auth.close(revoke=True) assert auth.closed is True
def test_box_oauth_exception(): status = 'status' message = 'message' url = 'https://example.com' method = 'GET' box_exception = BoxOAuthException( status, message=message, url=url, method=method, ) assert str(box_exception) == ''' Message: {0} Status: {1} URL: {2} Method: {3}'''.format(message, status, url, method)
def test_box_oauth_exception(has_network_response): status = 'status' message = 'message' url = 'https://example.com' method = 'GET' headers = {'header': 'value'} network_response = Mock(DefaultNetworkResponse, headers=headers) if has_network_response else None box_exception = BoxOAuthException( status, message=message, url=url, method=method, network_response=network_response, ) assert str(box_exception) == ''' Message: {0} Status: {1} URL: {2} Method: {3} Headers: {4}'''.format(message, status, url, method, headers if has_network_response else 'N/A') assert box_exception.network_response is network_response
def test_revoke_on_close_can_be_skipped(client_id, client_secret, access_token, mock_box_session, close_args, close_kwargs): auth = OAuth2(client_id=client_id, client_secret=client_secret, access_token=access_token, session=mock_box_session) with patch.object(auth, 'revoke') as mock_revoke: auth.close(*close_args, **close_kwargs) mock_revoke.assert_not_called() @pytest.mark.parametrize( ('raise_from_block', 'raise_from_close', 'expected_exception'), [ (MyError, None, MyError), (None, BoxOAuthException(status=500), BoxOAuthException), (MyError, BoxOAuthException(status=500), MyError), ]) @pytest.mark.parametrize( 'close_kwargs', [{}, dict(revoke=False), dict(revoke=True)]) def test_context_manager_reraises_first_exception_after_close( client_id, client_secret, mock_box_session, close_kwargs, raise_from_block, raise_from_close, expected_exception, ): auth = OAuth2(client_id=client_id,
def box_auth(oauth): raise BoxOAuthException(status="Failed")