@@ -431,10 +431,40 @@ def acquire_token_silent(
431431 ** kwargs ):
432432 """Acquire an access token for given account, without user interaction.
433433
434+ It behaves same as :func:`~acquire_token_silent_with_error`,
435+ except that this method will combine the cache empty and refresh error
436+ into one return value, `None`.
437+ If your app does not need to care the exact token refresh error during
438+ token cache look-up, then this method is easier to use.
439+
440+ Internally, this method calls :func:`~acquire_token_silent_with_error`.
441+
442+ :return:
443+ - A dict containing no "error" key,
444+ and typically contains an "access_token" key,
445+ if cache lookup succeeded.
446+ - None when cache lookup does not yield a token.
447+ """
448+ result = self .acquire_token_silent_with_error (
449+ scopes , account , authority , force_refresh , ** kwargs )
450+ return result if result and "error" not in result else None
451+
452+ def acquire_token_silent_with_error (
453+ self ,
454+ scopes , # type: List[str]
455+ account , # type: Optional[Account]
456+ authority = None , # See get_authorization_request_url()
457+ force_refresh = False , # type: Optional[boolean]
458+ ** kwargs ):
459+ """Acquire an access token for given account, without user interaction.
460+
434461 It is done either by finding a valid access token from cache,
435462 or by finding a valid refresh token from cache and then automatically
436463 use it to redeem a new access token.
437464
465+ Unlike :func:`~acquire_token_silent`,
466+ error happened during token refresh would also be returned.
467+
438468 :param list[str] scopes: (Required)
439469 Scopes requested to access a protected API (a resource).
440470 :param account:
@@ -444,8 +474,11 @@ def acquire_token_silent(
444474 If True, it will skip Access Token look-up,
445475 and try to find a Refresh Token to obtain a new Access Token.
446476 :return:
447- - A dict containing "access_token" key, when cache lookup succeeds.
448- - None when cache lookup does not yield anything.
477+ - A dict containing no "error" key,
478+ and typically contains an "access_token" key,
479+ if cache lookup succeeded.
480+ - None when there is simply no token in the cache.
481+ - A dict containing an "error" key, when token refresh failed.
449482 """
450483 assert isinstance (scopes , list ), "Invalid parameter type"
451484 self ._validate_ssh_cert_input_data (kwargs .get ("data" , {}))
@@ -460,8 +493,9 @@ def acquire_token_silent(
460493 scopes , account , self .authority , force_refresh = force_refresh ,
461494 correlation_id = correlation_id ,
462495 ** kwargs )
463- if result :
496+ if result and "error" not in result :
464497 return result
498+ final_result = result
465499 for alias in self ._get_authority_aliases (self .authority .instance ):
466500 the_authority = Authority (
467501 "https://" + alias + "/" + self .authority .tenant ,
@@ -472,7 +506,10 @@ def acquire_token_silent(
472506 correlation_id = correlation_id ,
473507 ** kwargs )
474508 if result :
475- return result
509+ if "error" not in result :
510+ return result
511+ final_result = result
512+ return final_result
476513
477514 def _acquire_token_silent_from_cache_and_possibly_refresh_it (
478515 self ,
@@ -533,13 +570,13 @@ def _acquire_token_silent_by_finding_rt_belongs_to_me_or_my_family(
533570 # https://msazure.visualstudio.com/One/_git/ESTS-Docs/pullrequest/1138595
534571 "client_mismatch" in response .get ("error_additional_info" , []),
535572 ** kwargs )
536- if at :
573+ if at and "error" not in at :
537574 return at
538575 if app_metadata .get ("family_id" ): # Meaning this app belongs to this family
539576 at = self ._acquire_token_silent_by_finding_specific_refresh_token (
540577 authority , scopes , dict (query , family_id = app_metadata ["family_id" ]),
541578 ** kwargs )
542- if at :
579+ if at and "error" not in at :
543580 return at
544581 # Either this app is an orphan, so we will naturally use its own RT;
545582 # or all attempts above have failed, so we fall back to non-foci behavior.
@@ -562,6 +599,8 @@ def _acquire_token_silent_by_finding_specific_refresh_token(
562599 query = query )
563600 logger .debug ("Found %d RTs matching %s" , len (matches ), query )
564601 client = self ._build_client (self .client_credential , authority )
602+
603+ response = None # A distinguishable value to mean cache is empty
565604 for entry in matches :
566605 logger .debug ("Cache attempts an RT" )
567606 response = client .obtain_token_by_refresh_token (
@@ -582,6 +621,7 @@ def _acquire_token_silent_by_finding_specific_refresh_token(
582621 ))
583622 if break_condition (response ):
584623 break
624+ return response # Returns the latest error (if any), or just None
585625
586626 def _validate_ssh_cert_input_data (self , data ):
587627 if data .get ("token_type" ) == "ssh-cert" :
0 commit comments