def __init__(self, user_service, settings): self.user_service = user_service self.serializer = URLSafeTimedSerializer( settings["password_reset.secret"], salt="password-reset", ) self.token_max_age = settings["password_reset.token_max_age"]
class UserTokenService: def __init__(self, user_service, settings): self.user_service = user_service self.serializer = URLSafeTimedSerializer( settings["password_reset.secret"], salt="password-reset", ) self.token_max_age = settings["password_reset.token_max_age"] def generate_token(self, user): return self.serializer.dumps({ "user.id": str(user.id), "user.last_login": str(user.last_login), "user.password_date": str(user.password_date), }) def get_user_by_token(self, token): if not token: raise InvalidPasswordResetToken( "Invalid token - No token supplied" ) try: data = self.serializer.loads(token, max_age=self.token_max_age) except SignatureExpired: raise InvalidPasswordResetToken( "Expired token - Token is expired, request a new password " "reset link" ) except BadData: # Catch all other exceptions raise InvalidPasswordResetToken( "Invalid token - Request a new password reset link" ) # Check whether a user with the given user ID exists user = self.user_service.get_user(uuid.UUID(data.get("user.id"))) if user is None: raise InvalidPasswordResetToken("Invalid token - User not found") last_login = data.get("user.last_login") if str(user.last_login) > last_login: raise InvalidPasswordResetToken( "Invalid token - User has logged in since this token was " "requested" ) # TODO: track and audit this, seems alertable password_date = data.get("user.password_date") if str(user.password_date) > password_date: raise InvalidPasswordResetToken( "Invalid token - Password has already been changed since this " "token was requested" ) return user
class TokenService: def __init__(self, secret, salt, max_age): self.serializer = URLSafeTimedSerializer(secret, salt=salt) self.max_age = max_age def dumps(self, data): return self.serializer.dumps({key: str(value) for key, value in data.items()}) def loads(self, token): if not token: raise TokenMissing try: data = self.serializer.loads(token, max_age=self.max_age) except SignatureExpired: raise TokenExpired except BadData: # Catch all other exceptions raise TokenInvalid return data
def __init__(self, secret, salt, max_age): self.serializer = URLSafeTimedSerializer(secret, salt=salt) self.max_age = max_age