def reset_password(token): """Users can reset their password with a token. The token is valid once and for a limited time.""" data = decode_email_token(token) posted_data = request.get_json() if data: # First try to validate the token with db.connect() as session: _uuid = data["uuid"] if "uuid" in data else None token = (session.query(Token).filter(~Token.blacklisted).filter( Token.token_expire > datetime.utcnow()).filter( Token.token == _uuid).first()) if not token: return { "success": False, "message": "You already used this link, or it's too old.", } # See if there's posted data. If so, validate the token # it should not be blacklisted or expired. if posted_data: # Then it should contain a new password, so set the password # for the user contained in the token. user = session.query(User).get(data["id"]) pw = posted_data["new_password"] if not validate_password(pw): return { "success": False, "message": ("Your password should be eight characters long " "and contain a lowercase, uppercase, number " " and one of these : '#$%&/*+?!-_='") } user.hash_password(pw) token.blacklisted = True return { "success": True, "message": "Cool. Password has been set.", "data": token.get_data() } # If no posted data, stay on the page, and return # json with message to set new password. return { "success": True, "message": "Please fill out a new password.", } # No bad tokens allowed. else: return { "success": False, "message": "Not a valid link to reset password." }
def forgot_password(): content = request.get_json(silent=True) with db.connect() as session: user = (session.query(User).filter_by( username=content["username"]).first()) if user and content["email"] == user.email: data = user.get_data() data["uuid"] = str(uuid4()) # Store token in database expiry_date = datetime.utcnow() + timedelta(seconds=600) token = Token(token=data["uuid"], token_expire=expiry_date, token_type="PW_RESET", blacklisted=False) session.add(token) # Create and send email token = encode_email_token(data) url = url_for("reset_password", token=token, _external=True) send_forgot_email(url, content["email"]) return {"succes": True, "message": "Reset request sent."} return {"success": False, "message": "Nope. Didn't work! :("}
def verify_refresh_auth(value): """ Use basic auth to verify user's refresh token. Returns Boolean """ user = None # Decode the authorization string decoded = base64.b64decode(value.encode("utf-8")) # Unpack decoded string user_id, token = decoded.decode("utf-8").split(":") # Query the user by username with db.connect() as session: user = session.query(User).get(user_id) if user: # Verify the refresh token, just like a password, # however once verified the refresh token will be # set to NULL. if user.verify_refresh_token(token): session.expunge(user) g.user = user return True return False
def register(): """Register new user.""" content = request.get_json(silent=True) username, password = content["username"], content["password"] if ((not (username and password)) or (("username" == "") or ("password" == ""))): return { "success": False, "message": "You should fill out a username and a password." } if not validate_password(content["password"]): return { "success": False, "message": ("Your password should be eight characters long " "and contain a lowercase, uppercase, number " " and one of these : '#$%&/*+?!-_='") } with db.connect() as session: if session.query(User).filter_by(username=content["username"]).first(): return { "success": False, "message": "This username already exists. Somebody beat you." } pw = content.pop("password") user = User(registered_date=datetime.utcnow(), **content) user.hash_password(pw) send_registration_email(content) with db.connect() as session: session.add(user) return { "success": True, "message": "Got it, thanks! Now first verify your email!" }
def generate_refresh_token(self, expire_seconds=3600*24): token = str(uuid4()) try: with db.connect() as session: user = session.query(User).get(self.user_id) user.refresh_token_hashed = hashpw( token.encode("utf-8"), gensalt()) td = timedelta(seconds=expire_seconds) user.refresh_token_expire = datetime.utcnow() + td except Exception: return None return token
def verify_token(token, secret): """Verify JWT""" try: d = jwt.decode(token, secret, algorithms=["HS256"]) except jwt.ExpiredSignatureError: return None except jwt.InvalidSignatureError: return None except jwt.InvalidTokenError: return None with db.connect() as session: user = session.query(User).get(d["id"]) session.expunge(user) return user
def verify_basic_auth(value): """Use basic auth to authenticate user.""" user = None decoded = base64.b64decode(value.encode("utf-8")) username, password = decoded.decode("utf-8").split(":") with db.connect() as session: user = session.query(User).filter_by(username=username).first() if user: if user.verify_password(password): session.expunge(user) g.user = user return True return False
def verify_email(token): try: data = decode_email_token(token) with db.connect() as session: q = session.query(User).filter_by(username=data["username"]) user = q.first() if user and user.confirmed: return redirect(app.config["STATIC_URL"] + "/auth/confirmed", 307) elif user and (user.email == data["email"]): q.update({ "confirmed": True, "confirmed_date": datetime.utcnow() }) return redirect(app.config["STATIC_URL"] + "/auth/confirmed", 307) else: abort(400) except Exception: abort(400)