@@ -154,6 +154,31 @@ async def _start(self, authorize_params) -> CIBAAuthorizationRequest:
154154 else :
155155 raise
156156
157+ def _extract_retry_after_header (self , error : Auth0Error ) -> Optional [int ]:
158+ """
159+ Extract the Retry-After header value from an Auth0Error.
160+
161+ Args:
162+ error: The Auth0Error object that may contain HTTP headers
163+
164+ Returns:
165+ The retry-after value in seconds as an integer, or None if not present
166+ """
167+
168+ if not hasattr (error , 'headers' ) or not error .headers :
169+ return None
170+
171+ retry_after = error .headers .get ('retry-after' ) or error .headers .get ('Retry-After' )
172+
173+ if retry_after is None :
174+ return None
175+
176+ try :
177+ return int (retry_after )
178+ except (ValueError , TypeError ):
179+ # If the retry-after value is not a valid integer, return None
180+ return None
181+
157182 def _get_credentials_internal (self , auth_request : CIBAAuthorizationRequest ) -> TokenResponse | None :
158183 try :
159184 # Calculate elapsed time in seconds
@@ -180,7 +205,8 @@ def _get_credentials_internal(self, auth_request: CIBAAuthorizationRequest) -> T
180205 raise AuthorizationPendingInterrupt (e .message , auth_request )
181206
182207 if e .error_code == "slow_down" :
183- raise AuthorizationPollingInterrupt (e .message , auth_request )
208+ retry_after = self ._extract_retry_after_header (e )
209+ raise AuthorizationPollingInterrupt (e .message , auth_request , retry_after )
184210
185211 if e .error_code == "invalid_grant" :
186212 raise InvalidGrantInterrupt (e .message , auth_request )
@@ -203,7 +229,7 @@ async def get_credentials_polling(self, auth_request: CIBAAuthorizationRequest)
203229 try :
204230 credentials = self ._get_credentials_internal (auth_request )
205231 except (AuthorizationPendingInterrupt , AuthorizationPollingInterrupt ) as err :
206- await asyncio .sleep (err .request [ "interval" ] )
232+ await asyncio .sleep (err .next_retry_interval () )
207233 except Exception :
208234 raise
209235
0 commit comments