<style> .present { text-align: left; } </style> --- ###### tags: `Week 12` `W12D4` --- # Week 12 Day 4: Scopes, JWT's, & Passwords --- ## Review from yesterday... - CORS - Cross-Origin Resource Sharing - Protect against with CORS - XSS - Cross-Site Scripting - React will take care of (escaping HTML) - CSRF - Cross-Site resource Forgery - Cookies to verify request came from the server --- # Scopes Scopes are additional attributes that we can add to our model definition. They allow us to dry up our code by pre-defining commonly used queries. This makes it easier for us to include or exclude specific information. https://sequelize.org/docs/v6/other-topics/scopes/ --- ## There are a couple of ways to add scopes to our models. The first is a default scope. This will *always* be applied to any query on the model. We can define a default scope by adding a `defaultScope` key to the options object in our model. This will be the last object in our `Model.init` method. --- ## Default scope to model In last object in init: ```javascript { // options object in User.init sequelize, modelName: "User", defaultScope: { attributes: { exclude: ['createdAt', 'updatedAt'] } } } ``` --- ## Scopes Property We can add non-default scopes by using the `scopes` property. The `scopes` property points to an object who's key is the name of the scope, and the value is the object to be passed to the query ```javascript { // options object in User.init sequelize, modelName: "User", defaultScope: { attributes: { exclude: ['createdAt', 'updatedAt'] } }, scopes: { onlyUserNameAndId: { attributes: ['id', 'username'] } } } ``` --- ## When applying a non-default scope, we have to adjust our query We have to add .scope() to our query like so: ```javascript <model>.scope(<scopes>).<query method>() ``` If we add a named scope to a query, then the defaultScope will not be applied automatically We would need to specify it in the .scopes() --- ## We can also add a function scope ```javascript { // options object in User.init scopes: { includePostBy(postId) { const { Post } = require('../models') return { include: { model: Post, where: { id: postId } } } } } } ``` Function scopes get passed in as another object with the key of method and a value of an array: `[<func scope name>, <args>]` Function scopes return a filter to be applied to the query --- # 30 mins for Scopes SP --- # JWT - JSON Web Token This is how we handle User Auth - If we want to log a user in, we create a token. - If we want to log a user out, we delete that token --- ### Some ways that we keep data safe as we transport it across the web: - Encode - Encrypt - Hash --- # Encode Not very secure. Can easily be decoded. `http://localhost:5000/users?name=Bloo%20Q.%20Kazoo` Here we are using the "%20" URL encoding to make the string "Bloo Q. Kazoo" interpretable to the browser despite having spaces. --- # Encrypt More secure. Once data is encrypted, it can't be descrypted unless they have the password/secret key If a bad user gets that secret key, we are in trouble --- # Hash - Cannot be reverse-engineered - Hashing is deterministic - There is a problem here: - There is a possibility that multiple strings could end up hashing to the same value - This is called a hash collision - We would use a salt to prevent/protect against this --- # Rainbow Tables - These are tables of exposed emails/usernames as well as common passwords with their hashed version - Malicious users will use these Rainbow Tables to brute force logins - We can use something called a Salt to avoid this hash collision issue --- # JWTs Consists of 3 parts: - Header - Payload - Signature --- # Header - Contains the type of token - Indicator for the algo that we use for the hash - JWT will automatically set this --- # Payload - The data we are transmitting - Can add claims - such as an expiration - ONLY encoded --- # Signature - Hash of the header, payload, and a secret key - Allows us to validate that our token hasn't been tampered with --- ### To create a Token: ```javascript // Must require jswonwebtoken const jwt = require('jsonwebtoken') const createToken = (payload) => { const token = jwt.sign(payload, secretKey) return token; }; ``` Docs link: https://www.npmjs.com/package/jsonwebtoken --- ### To verify a token: ```javascript const verifyToken = (token) => { const verified = jwt.verify(token, secretKey) // jwt.verify also can take in a 3rd arg, which is a callback function return verified }; ``` We can also decode a JWT to get the payload info if we need to... ```javascript! const decoded = jwt.decode(token) ``` --- ## 30 mins for JWT SP --- ## Bcrypt The `bcrypt.hashSync` function allows us to increase the security of our hash by passing in a cost argument. ```javascript const bcrypt = require('bcryptjs'); const hashPass = (password) => { const hash = bcrypt.hashSync(password, 12) return hash; }; ``` The hash provided consists of algo, cost, salt (22 char), and hash ```bash // $2a$12$2q9fQ2so8M67u7IAoR8zZe0XtqG0oXkDm53RzjuA6vb0OwH3nm1tC // \_/\_/\____________________/\_____________________________/ // / | | | //algo cost salt hash ``` --- # Cost Factor The cost factor tells `bcrypt` how many times to hash the password Graph to demo cost in `bcrypt` about halfway down this link: <a href='https://stytch.com/blog/what-is-password-hashing/#:~:text=The%20default%20cost%20(rounds)%20of%20bcrypt%20is%2010.%20When%20this%20algorithm%20was%20conceived%2C%20the%20cost%20of%2010%20was%20secure%20enough.%20However%2C%20depending%20on%20the%20hardware%2C%20this%20now%20can%20take%20milliseconds.%20So%2C%20you%20can%20increase%20the%20cost%20of%20rounds%20to%2015%20or%20more%20to%20make%20the%20hashing%20process%20take%20several%20seconds%20instead.%C2%A0%C2%A0'>Hashing Article</a> --- ## Note We don't want to set the cost too high Setting the cost factor to around 12-13 is the recommendation --- ## Comparing Hashes We can easily compare our stored hash to an incoming hash using `bcrypt.compareSync`; ```javascript const testPass = (password, hash) => { const isPass = bcrypt.compareSync(password, hash) return isPass; } ``` --- ## Auth Demo... - Make a Signup route - Make a Login route - Make a Logout route --- ## Break out for Auth Me Phases 3-5 - if you finish before EOD, start on the PA - tomorrow is a study day --- # Instructor ** Post in Discord: - You can create your own Google form to gather this info @here Howdy folks. When you have a quick moment, we need to know which of the two projects you'll be pursuing, and we need your git repo links. Please submit this Google form: `<add form url>` If you're on the fence about which project to pursue, AirBnB tends to be a little easier, but it's also one of the most commonly cloned websites on the internet at this point. Meetup will be a bit harder, there are a few more endpoints to complete and it requires a solid understanding of our user auth flow.
{"title":"Week 12 Day 4:","description":"Scopes and JSON Web Tokens","contributors":"[{\"id\":\"bbda4bdc-50a5-429e-9073-d74141f277f3\",\"add\":7247,\"del\":257},{\"id\":\"dafd1858-850b-4d12-9d53-a1ac5e891cf8\",\"add\":804,\"del\":305}]"}
    209 views
   Owned this note