A login form is only the visible part of password authentication. The application must check a submitted password against a user account, manage the resulting session, and protect account data if its database is exposed. section 8.2.1
A typical email-and-password login follows these steps:
- The browser requests the login page with GET, then submits the completed form with POST. section 8.2.1
- The application uses its user model and storage system to find a matching email and password. section 8.2.1
- After a successful match, the user goes to the home page or the page they originally wanted to visit. section 8.2.1
Never store user passwords as plain text. Store cryptographic hashes instead: bcrypt makes hashing computationally expensive to resist brute-force attacks. Users who forget their passwords must reset them rather than retrieve them. Flask-Login supplies session management, login and logout tools, and protection for endpoints that require authentication. section 8.2.1
The application may also need its own password to authenticate to another service, such as an SMTP email server. Keep that credential out of source code and public repositories. A separate runtime-accessible file can hold private information, with different versions for development, staging, and production. section 7.6.2
class User(UserMixin, db.Model): #1
__tablename__ = "user" #2
user_uid = db.Column(db.String, primary_key=True, default=get_uuid) #3
first_name = db.Column(db.String, nullable=False) #4
last_name = db.Column(db.String, nullable=False) #4
email = db.Column(db.String, nullable=False, #4
unique=True, index=True) #4
hashed_password = db.Column("password", #4
db.String, nullable=False) #4
active = db.Column(db.Boolean, nullable=False, default=False) #4
created = db.Column(db.DateTime, nullable=False, #5
default=datetime.utcnow) #5
updated = db.Column(db.DateTime, nullable=False, #5
default=datetime.utcnow, onupdate=datetime.utcnow) #5
def get_id(self):
return self.user_uid
@property
def password(self):
raise AttributeError("user password can’t be read")
@password.setter
def password(self, password):
self.hashed_password = generate_password_hash(password)
def verify_password(self, password):
return check_password_hash(self.hashed_password, password)
def __repr__(self):
return f"""
user_uid: {self.user_uid}
name: {self.first_name} {self.last_name}
email: {self.email}
active: {'True' if self.active else 'False'}
"""
The User model gives email a unique, indexed field and stores a hashed_password value in the database password column. section 8.2.1








