Contrary to popular belief, hashing passwords before storage is not (always) enough to keep them secure. Some reasons for this are:
Sophisticated hash cracking techniques: reverse lookup tables (an online tool called CrackStation makes this approach very accessible), and rainbow tables
Computation-driven password guessing techniques: dictionary attacks and brute force attacks
improper user password complexity
re-use of passwords by users across sites
It is possible to prevent hash-cracking by using a technique called 'salting'. This method involves modifying the password by adding a random string of data before hashing it.
It is possible to decrease the effectiveness of computation-driven password-breaking techniques using a process called 'key-stretching'. This method makes the hash function slow enough that (even with custom hardware and modern GPU), dictionary and brute-force attacks are too slow to be worth the adversary’s effort.
Intro to JSON Web Tokens
These tokens are NOT recommended to be stored in LocalStorage. Use SessionStorage instead.
Also, there are signature requirements that can be added to the JWT for higher levels of security
JWT's should never contain secret information because they will be exposed to access by other parties.
JWT's are usually passed in the header of HTTP communications to allow a user to continue working seamlessly across the pages of a web site without having to continually re-enter their password.
OWASP auth cheatsheet
Authentication is the process of verifying that an individual, entity or website is who it claims to be.
Authentication in the context of web applications is commonly performed by submitting a username or ID and one or more items of private information (like a password) that only a given user should know.
Session Management is a process by which a server maintains the state of an entity interacting with it. This is required for a server to remember how to react to subsequent requests throughout a transaction.
Sessions are maintained on the server by a session identifier which can be passed back and forward between the client and server when transmitting and receiving requests.
Sessions should be unique per user and computationally very difficult to predict.