def check_totp_value(self, user_id, totp_value, *, tags=None): """ Returns True if the given TOTP is valid against the user's secret. If the user doesn't have a TOTP secret, returns False. """ tags = tags if tags is not None else [] self._metrics.increment("warehouse.authentication.two_factor.start", tags=tags) totp_secret = self.get_totp_secret(user_id) if totp_secret is None: self._metrics.increment( "warehouse.authentication.two_factor.failure", tags=tags + ["failure_reason:no_totp"], ) return False valid = otp.verify_totp(totp_secret, totp_value) if valid: self._metrics.increment("warehouse.authentication.two_factor.ok", tags=tags) else: self._metrics.increment( "warehouse.authentication.two_factor.failure", tags=tags + ["failure_reason:invalid_totp"], ) return valid
def test_verify_totp_failure(skew): secret = generate_totp_secret() totp = TOTP(secret, TOTP_LENGTH, SHA1(), TOTP_INTERVAL, backend=default_backend()) value = totp.generate(time.time() + skew) assert not verify_totp(secret, value)
def check_totp_value(self, user_id, totp_value, *, tags=None): """ Returns True if the given TOTP is valid against the user's secret. If the user doesn't have a TOTP secret or isn't allowed to use second factor methods, returns False. """ tags = tags if tags is not None else [] self._metrics.increment("warehouse.authentication.two_factor.start", tags=tags) # The very first thing we want to do is check to see if we've hit our # global rate limit or not, assuming that we've been configured with a # global rate limiter anyways. if not self.ratelimiters["global"].test(): logger.warning("Global failed login threshold reached.") self._metrics.increment( "warehouse.authentication.two_factor.ratelimited", tags=tags + ["ratelimiter:global"], ) raise TooManyFailedLogins( resets_in=self.ratelimiters["global"].resets_in()) # Now, check to make sure that we haven't hitten a rate limit on a # per user basis. if not self.ratelimiters["user"].test(user_id): self._metrics.increment( "warehouse.authentication.two_factor.ratelimited", tags=tags + ["ratelimiter:user"], ) raise TooManyFailedLogins( resets_in=self.ratelimiters["user"].resets_in(user_id)) totp_secret = self.get_totp_secret(user_id) if totp_secret is None: self._metrics.increment( "warehouse.authentication.two_factor.failure", tags=tags + ["failure_reason:no_totp"], ) return False valid = otp.verify_totp(totp_secret, totp_value) if valid: self._metrics.increment("warehouse.authentication.two_factor.ok", tags=tags) else: self._metrics.increment( "warehouse.authentication.two_factor.failure", tags=tags + ["failure_reason:invalid_totp"], ) return valid
def check_totp_value(self, user_id, totp_value, ip_address, *, tags=None): """ Returns True if the given TOTP is valid against the user's secret. If the user doesn't have a TOTP secret or isn't allowed to use second factor methods, returns False. """ tags = tags if tags is not None else [] tags.append("mechanism:check_totp_value") self._metrics.increment("warehouse.authentication.two_factor.start", tags=tags) self._check_ratelimits(userid=user_id, ip_address=ip_address, tags=tags) totp_secret = self.get_totp_secret(user_id) if totp_secret is None: self._metrics.increment( "warehouse.authentication.two_factor.failure", tags=tags + ["failure_reason:no_totp"], ) # If we've gotten here, then we'll want to record a failed attempt in our # rate limiting before returning False to indicate a failed totp # verification. self._hit_ratelimits(ip_address, userid=user_id) return False last_totp_value = self.get_last_totp_value(user_id) if last_totp_value is not None and totp_value == last_totp_value.encode( ): return False valid = otp.verify_totp(totp_secret, totp_value) if valid: self._metrics.increment("warehouse.authentication.two_factor.ok", tags=tags) else: self._metrics.increment( "warehouse.authentication.two_factor.failure", tags=tags + ["failure_reason:invalid_totp"], ) # If we've gotten here, then we'll want to record a failed attempt in our # rate limiting before returning False to indicate a failed totp # verification. self._hit_ratelimits(ip_address, userid=user_id) return valid
def validate_totp_value(self, field): totp_value = field.data.encode("utf8") if not otp.verify_totp(self.totp_secret, totp_value): raise wtforms.validators.ValidationError( "Invalid TOTP code. Try again?")
def test_verify_totp_failure(skew): secret = generate_totp_secret() totp = TOTP(secret, TOTP_LENGTH, SHA1(), TOTP_INTERVAL, backend=default_backend()) value = totp.generate(time.time() + skew) assert not verify_totp(secret, value)
def validate_totp_value(self, field): totp_value = field.data.encode("utf8") if not otp.verify_totp(self.totp_secret, totp_value): raise wtforms.validators.ValidationError("Invalid TOTP code. Try again?")