-
express middleware review (global vs local).
-
mongoose middleware (lifecycle hooks).
-
hashing user passwords for database storage.
-
extending mongoose models with custom
methods
. -
persisting state across requests using sessions (in-memory and persisted in mongo).
-
authenticating users using cookies/sessions.
-
protecting resources from unauthenticated users.
-
authenticating users using JSON Web Tokens (JWTs, pronounced JOT).
-
persisting tokens on the front-end to keep users authenticated across sessions.
-
security good practices.
- express middleware review (global vs local).
- implementing
register
endpoint. - hashing user passwords for database storage.
- mongoose middleware (lifecycle hooks).
client > request > [ (middleware) api ({middleware queue} mongoose) ] > db
- password storage
- brute-force attack mitigation
- password strength - The haystack
- it's a two way process
- plain text password + private key => encrypted password
- encrypted password + private key => original plain text password
- it's a one way process
- parameters + password => hash
- to slow down production of hashes we add cost/time.
- hash + time = key derivation function === bcrypt
- what is the difference between global and local express middleware?
- what is another name for mongoose middleware?
- is it better to encrypt or hash passwords? why?
- which middleware hook is useful for encrypting/hashing passwords when creating users?
- which npm package did we use to do the password encryption/hashing? which method did we call on it?
- why do we add time/cost to our encryption/hashing algorithm? what is a good number of rounds?
- is it better to require uppercase + numbers + special characters or a minimum length to make passwords more secure? why?
- implementing
login
. - extending mongoose models with custom
methods
. - using sessions.
- protect a resource to only allow access for logged in users
- implementing
logout
.
- sessions are a way to persist data across requests.
- each user/device has a unique session.
const session = require('express-session');
server.use(
session({
secret: 'nobody tosses a dwarf!',
cookie: { maxAge: 1 * 24 * 60 * 60 * 1000 }, // 1 day in milliseconds
httpOnly: true,
secure: true,
})
);
Now we can store session data in one route handler and read it in another.
app.get('/', (req, res) => {
req.session.name = 'Luis';
res.send('got it');
});
app.get('/greet', (req, res) => {
const name = req.session.name;
res.send(`hello ${req.session.name}`);
});
- memory
- cookie
- memory cache (like Redis and Memcached)
- database
- data stored in memory is wiped when the server restarts.
- causes memory leaks as more and more memory is used as the application continues to store data in session for different clients.
- good for development due to its simplicity.
- a cookie is a small key/value pair data structure that is passed back and forth between client and server and stored in the browser.
- the server use it to store information about a particular client/user.
- workflow for using cookies as session storage:
- the server issues a cookie with an expiration time and sends it with the response.
- browsers automatically store the cookie and send it on every request to the same domain.
- the server can read the information contained in the cookie (like the username).
- the server can make changes to the cookie before sending it back on the response.
- rinse and repeat.
express-session uses cookies for session management.
Drawbacks when using cookies
- small size, around 4KB.
- sent in every request, increasing the size of the request if too much information is stored in them.
- if an attacker gets a hold of the private key used to encrypt the cookie they could read the cookie data.
- stored as key-value pair data in a separate server.
- the server still uses a cookie, but it only contains the session id.
- the memory cache server uses that session id to find the session data.
Advantages
- quick lookups.
- decoupled from the api server.
- a single memory cache server can serve may applications.
- automatically remove old session data.
Downsides
- another server to set up and manage.
- extra complexity for small applications.
- hard to reset the cache without losing all session data.
- similar to storing data in a memory store.
- the session cookie still holds the session id.
- the server uses the session id to find the session data in the database.
- retrieving data from a database is slower than reading from a memory cache.
- causes chatter between the server an the database.
- need to manage/remove old sessions manually or the database will be filled with unused session data. connect-mongo manages that for you.