@@ -1864,12 +1864,28 @@ def assert_downloaded_file(self, file):
18641864 def get_google_auth_password (self , totp_key = None ):
18651865 """ Returns a time-based one-time password based on the
18661866 Google Authenticator password algorithm. Works with Authy.
1867- If "totp_key" is not specified, will default to using
1868- the one provided in seleniumbase/config/settings.py
1869- (See https://pyotp.readthedocs.io/en/latest/ for details.) """
1867+ If "totp_key" is not specified, defaults to using the one
1868+ provided in seleniumbase/config/settings.py
1869+ Google Auth passwords expire and change at 30-second intervals.
1870+ If the fetched password expires in the next 3 seconds, waits
1871+ for a fresh one before returning it (may take up to 3 seconds).
1872+ See https://pyotp.readthedocs.io/en/latest/ for details. """
18701873 import pyotp
18711874 if not totp_key :
18721875 totp_key = settings .TOTP_KEY
1876+
1877+ epoch_interval = time .time () / 30.0
1878+ cycle_lifespan = float (epoch_interval ) - int (epoch_interval )
1879+ if float (cycle_lifespan ) > 0.90 :
1880+ # Password expires in less than 3 seconds. Wait for a fresh one.
1881+ for i in range (60 ):
1882+ time .sleep (0.05 )
1883+ epoch_interval = time .time () / 30.0
1884+ cycle_lifespan = float (epoch_interval ) - int (epoch_interval )
1885+ if not float (cycle_lifespan ) > 0.90 :
1886+ # The new password cycle has begun
1887+ break
1888+
18731889 totp = pyotp .TOTP (totp_key )
18741890 return str (totp .now ())
18751891
0 commit comments