def get_settings_two_factor(request: Request) -> dict: """Generate the two-factor authentication page.""" # Generate a new secret key if the user doesn't have one. if request.user.two_factor_secret is None: request.user.two_factor_secret = pyotp.random_base32() return { "two_factor_secret": separate_string(request.user.two_factor_secret, " ", 4) }
def post_view_two_factor_backup_codes(request: Request, code: str) -> Response: """Show the user their two-factor authentication backup codes.""" user = request.context if not user.is_correct_two_factor_code(code): raise HTTPUnauthorized(body="Invalid code") # format the backup codes to be easier to read for output backup_codes = [ separate_string(code, " ", 4) for code in user.two_factor_backup_codes ] return {"backup_codes": backup_codes}
def post_enable_two_factor(request: Request, code: str) -> dict: """Enable two-factor authentication for the user.""" user = request.context if not user.is_correct_two_factor_code(code): raise HTTPUnprocessableEntity("Invalid code, please try again.") request.user.two_factor_enabled = True # Generate 10 backup codes (16 lowercase letters each) request.user.two_factor_backup_codes = [ "".join(random.choices(string.ascii_lowercase, k=16)) for _ in range(10) ] # format the backup codes to be easier to read for output backup_codes = [ separate_string(code, " ", 4) for code in request.user.two_factor_backup_codes ] return {"backup_codes": backup_codes}
def __str__(self) -> str: """Format the code into a more easily readable version.""" return separate_string(self.code, "-", 5)