gee-community/geemap

Error about ee.Initialize

zwy1502 opened this issue · 3 comments

Environment Information

<html>
<body>
<!--StartFragment-->
Thu Jan 11 01:28:14 2024 **标准时间
--
OS | Windows | CPU(s) | 20 | Machine | AMD64
Architecture | 64bit | RAM | 15.7 GiB | Environment | Jupyter
Python 3.11.3 \| packaged by conda-forge \| (main, Apr 6 2023, 08:50:54) [MSC v.1934 64 bit (AMD64)]
geemap | 0.29.6 | ee | 0.1.384 | ipyleaflet | 0.17.0
folium | 0.13.0 | jupyterlab | 3.5.3 | notebook | 6.5.4
ipyevents | 2.0.2 | geopandas | 0.14.2 | localtileserver | 0.7.1

<!--EndFragment-->
</body>
</html>

Description

Dear Professor Wu, hello, I have used the geemap software package for a long time. It is very easy to use and I am very grateful to Teacher Wu for his hard work. Now I read the problem shared by the teacher about the authentication token, and I also encountered it. I have the same problem. I have updated my geemap to the latest version, but the token problem still occurs. If I operate Map = geemap.Map() as usual, "Error 400: invalid_request" will appear.
The out-of-band (OOB) flow has been blocked in order to keep users secure. Follow the Out-of-Band (OOB) flow migration guide linked in the developer docs below to migrate your app to an alternative method." Error, I saw Professor Wu's temporary solution is ee.Initialize(project='ee-my-sdas'), but this line of code still reports an error. What should I do? I am very much looking forward to and thanking Professor Wu for his answer!

What I Did

import ee
import geemap
geemap.set_proxy(port='4780')
ee.Initialize(project='ee-my-abcd')

The error content is as follows


RefreshError Traceback (most recent call last)
Cell In[5], line 1
----> 1 ee.Initialize(project='ee-my-zwy')

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\ee_utils.py:39, in accept_opt_prefix..opt_fixed..wrapper(*args, **kwargs)
37 if new_key not in kwargs:
38 kwargs[new_key] = old_key_val
---> 39 return func(*args, **kwargs)

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\ee_init_.py:140, in Initialize(credentials, url, cloud_api_key, http_transport, project)
137 if credentials == 'persistent':
138 credentials = data.get_persistent_credentials()
--> 140 data.initialize(
141 credentials=credentials,
142 api_base_url=(url + '/api' if url else None),
143 tile_base_url=url,
144 cloud_api_base_url=url,
145 cloud_api_key=cloud_api_key,
146 project=project,
147 http_transport=http_transport,
148 )
150 # Initialize the dynamically loaded functions on the objects that want them.
151 ApiFunction.initialize()

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\ee\data.py:225, in initialize(credentials, api_base_url, tile_base_url, cloud_api_base_url, cloud_api_key, project, http_transport)
222 if _requests_session is None:
223 _requests_session = requests.Session()
--> 225 _install_cloud_api_resource()
227 if project is not None:
228 _cloud_api_user_project = project

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\ee\data.py:300, in _install_cloud_api_resource()
298 timeout = (_deadline_ms / 1000.0) or None
299 assert _requests_session is not None
--> 300 _cloud_api_resource = _cloud_api_utils.build_cloud_resource(
301 _cloud_api_base_url,
302 _requests_session,
303 credentials=_credentials,
304 api_key=_cloud_api_key,
305 timeout=timeout,
306 headers_supplier=_make_request_headers,
307 response_inspector=_handle_profiling_response,
308 http_transport=_http_transport,
309 )
311 _cloud_api_resource_raw = _cloud_api_utils.build_cloud_resource(
312 _cloud_api_base_url,
313 _requests_session,
(...)
320 raw=True,
321 )

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\ee_cloud_api_utils.py:195, in build_cloud_resource(api_base_url, session, api_key, credentials, timeout, headers_supplier, response_inspector, http_transport, raw)
190 resource = None
191 try:
192 # google-api-python-client made static_discovery the default in version 2,
193 # but it's not backward-compatible. There's no reliable way to check the
194 # package version, either.
--> 195 resource = build(static_discovery=False)
196 except TypeError:
197 pass # Handle fallback case outside except block, for cleaner stack traces.

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\ee_cloud_api_utils.py:179, in build_cloud_resource..build(**kwargs)
178 def build(**kwargs):
--> 179 return discovery.build(
180 'earthengine',
181 VERSION,
182 discoveryServiceUrl=discovery_service_url,
183 developerKey=api_key,
184 http=http_transport,
185 requestBuilder=request_builder,
186 model=alt_model,
187 cache_discovery=False,
188 **kwargs)

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\googleapiclient_helpers.py:130, in positional..positional_decorator..positional_wrapper(*args, **kwargs)
128 elif positional_parameters_enforcement == POSITIONAL_WARNING:
129 logger.warning(message)
--> 130 return wrapped(*args, **kwargs)

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\googleapiclient\discovery.py:287, in build(serviceName, version, http, discoveryServiceUrl, developerKey, model, requestBuilder, credentials, cache_discovery, cache, client_options, adc_cert_path, adc_key_path, num_retries, static_discovery, always_use_jwt_access)
284 requested_url = uritemplate.expand(discovery_url, params)
286 try:
--> 287 content = _retrieve_discovery_doc(
288 requested_url,
289 discovery_http,
290 cache_discovery,
291 serviceName,
292 version,
293 cache,
294 developerKey,
295 num_retries=num_retries,
296 static_discovery=static_discovery,
297 )
298 service = build_from_document(
299 content,
300 base=discovery_url,
(...)
309 always_use_jwt_access=always_use_jwt_access,
310 )
311 break # exit if a service was created

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\googleapiclient\discovery.py:422, in _retrieve_discovery_doc(url, http, cache_discovery, serviceName, version, cache, developerKey, num_retries, static_discovery)
419 # Execute this request with retries build into HttpRequest
420 # Note that it will already raise an error if we don't get a 2xx response
421 req = HttpRequest(http, HttpRequest.null_postproc, actual_url)
--> 422 resp, content = req.execute(num_retries=num_retries)
424 try:
425 content = content.decode("utf-8")

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\googleapiclient_helpers.py:130, in positional..positional_decorator..positional_wrapper(*args, **kwargs)
128 elif positional_parameters_enforcement == POSITIONAL_WARNING:
129 logger.warning(message)
--> 130 return wrapped(*args, **kwargs)

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\googleapiclient\http.py:923, in HttpRequest.execute(self, http, num_retries)
920 self.headers["content-length"] = str(len(self.body))
922 # Handle retries for server-side errors.
--> 923 resp, content = _retry_request(
924 http,
925 num_retries,
926 "request",
927 self._sleep,
928 self._rand,
929 str(self.uri),
930 method=str(self.method),
931 body=self.body,
932 headers=self.headers,
933 )
935 for callback in self.response_callbacks:
936 callback(resp)

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\googleapiclient\http.py:191, in _retry_request(http, num_retries, req_type, sleep, rand, uri, method, *args, **kwargs)
189 try:
190 exception = None
--> 191 resp, content = http.request(uri, method, *args, **kwargs)
192 # Retry on SSL errors and socket timeout errors.
193 except _ssl_SSLError as ssl_error:

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\google_auth_httplib2.py:209, in AuthorizedHttp.request(self, uri, method, body, headers, redirections, connection_type, **kwargs)
205 # Make a copy of the headers. They will be modified by the credentials
206 # and we want to pass the original headers if we recurse.
207 request_headers = headers.copy() if headers is not None else {}
--> 209 self.credentials.before_request(self._request, method, uri, request_headers)
211 # Check if the body is a file-like stream, and if so, save the body
212 # stream position so that it can be restored in case of refresh.
213 body_stream_position = None

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\google\auth\credentials.py:228, in Credentials.before_request(self, request, method, url, headers)
226 self._non_blocking_refresh(request)
227 else:
--> 228 self._blocking_refresh(request)
230 metrics.add_metric_header(headers, self._metric_header_for_usage())
231 self.apply(headers)

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\google\auth\credentials.py:191, in Credentials._blocking_refresh(self, request)
189 def _blocking_refresh(self, request):
190 if not self.valid:
--> 191 self.refresh(request)

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\google\oauth2\credentials.py:390, in Credentials.refresh(self, request)
372 if (
373 self._refresh_token is None
374 or self._token_uri is None
375 or self._client_id is None
376 or self._client_secret is None
377 ):
378 raise exceptions.RefreshError(
379 "The credentials do not contain the necessary fields need to "
380 "refresh the access token. You must specify refresh_token, "
381 "token_uri, client_id, and client_secret."
382 )
384 (
385 access_token,
386 refresh_token,
387 expiry,
388 grant_response,
389 rapt_token,
--> 390 ) = reauth.refresh_grant(
391 request,
392 self._token_uri,
393 self._refresh_token,
394 self._client_id,
395 self._client_secret,
396 scopes=scopes,
397 rapt_token=self._rapt_token,
398 enable_reauth_refresh=self._enable_reauth_refresh,
399 )
401 self.token = access_token
402 self.expiry = expiry

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\google\oauth2\reauth.py:365, in refresh_grant(request, token_uri, refresh_token, client_id, client_secret, scopes, rapt_token, enable_reauth_refresh)
356 (
357 response_status_ok,
358 response_data,
(...)
361 request, token_uri, body, headers=metrics_header
362 )
364 if not response_status_ok:
--> 365 _client._handle_error_response(response_data, retryable_error)
366 return _client._handle_refresh_grant_response(response_data, refresh_token) + (
367 rapt_token,
368 )

File E:\Anacondapy\Anaconda3\envs\gee\Lib\site-packages\google\oauth2_client.py:72, in _handle_error_response(response_data, retryable_error)
69 except (KeyError, ValueError):
70 error_details = json.dumps(response_data)
---> 72 raise exceptions.RefreshError(
73 error_details, response_data, retryable=retryable_error
74 )

RefreshError: ('invalid_grant: Token has been expired or revoked.', {'error': 'invalid_grant', 'error_description': 'Token has been expired or revoked.'})

This bug has been fixed. Run pip install -U geemap and restart the kernel to take effect.

You should try to first Authenticate with ee and then Initialize.

ee.Authenticate(auth_mode='localhost')
ee.Initialize(project='my-project-id')

For others reading this later. There were changes to Earth Engine authentication and initialization in v0.1.383 that adds options for authenticating and essentially requires a cloud project be specified in one way or another. The guide pages on auth and init have been updated to include the options, please read the options carefully if you are having auth / init issues.

https://developers.google.com/earth-engine/guides/auth

Be sure that your earthengine-api and geemap libraries are up to date. geemap tries to help you handle auth and init, but sometimes changes that Earth Engine or Google oauth make break geemaps auth / init helpers and newer versions include fixes.