Authenticate and return a user following an email and a password. Will automatically upgrade password hash if necessary. :param credentials: The user credentials. :return: The authenticated user of type models.UP if credentials are valid, otherwise None.
(
self, credentials: OAuth2PasswordRequestForm
)
| 634 | return # pragma: no cover |
| 635 | |
| 636 | async def authenticate( |
| 637 | self, credentials: OAuth2PasswordRequestForm |
| 638 | ) -> models.UP | None: |
| 639 | """ |
| 640 | Authenticate and return a user following an email and a password. |
| 641 | |
| 642 | Will automatically upgrade password hash if necessary. |
| 643 | |
| 644 | :param credentials: The user credentials. |
| 645 | :return: The authenticated user of type models.UP if credentials are valid, |
| 646 | otherwise None. |
| 647 | """ |
| 648 | try: |
| 649 | user = await self.get_by_email(credentials.username) |
| 650 | except exceptions.UserNotExists: |
| 651 | # Run the hasher to mitigate timing attack |
| 652 | # Inspired from Django: https://code.djangoproject.com/ticket/20760 |
| 653 | self.password_helper.hash(credentials.password) |
| 654 | return None |
| 655 | |
| 656 | verified, updated_password_hash = self.password_helper.verify_and_update( |
| 657 | credentials.password, user.hashed_password |
| 658 | ) |
| 659 | if not verified: |
| 660 | return None |
| 661 | # Update password hash to a more robust one if needed |
| 662 | if updated_password_hash is not None: |
| 663 | await self.user_db.update(user, {"hashed_password": updated_password_hash}) |
| 664 | |
| 665 | return user |
| 666 | |
| 667 | async def _update(self, user: models.UP, update_dict: dict[str, Any]) -> models.UP: |
| 668 | validated_update_dict = {} |