Skip to content

Commit 70fa7c8

Browse files
committed
resolved comments
1 parent 9fafa79 commit 70fa7c8

File tree

5 files changed

+36
-30
lines changed
  • module4-authentication-and-security

5 files changed

+36
-30
lines changed

module4-authentication-and-security/r1-securing-backend-app/README.md

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ Now, suppose another user comes to your app: how will your app decide what to sh
3434

3535
That's why almost everywhere online, you need to register or log in to an account in order to use an application, so the data can be related to you and you only.
3636

37-
## Let's add some security
37+
## Let's add some authentication
3838

3939
To secure our wishlist above, we can add a new column to the lists table to attach it to an identity (a user). We can name that column `user_email` for example, and use this query to get the user wishlist:
4040

@@ -63,17 +63,18 @@ You can change the column `user_email` to `token` and every time a user comes in
6363

6464
Bingo! You've just created your first, very adequate authentication layer! You've secured your app and **slimmed the chances** of brute-forcing user data! Many apps today use this pattern to secure data. However, keep in mind that you usually need other features to track, like user email, name, age, etc. So such a simplistic approach wouldn't suffice. That's when this token is moved into another table and tracked with a `user_id` instead.
6565

66-
## Why do we need passwords
66+
## Why do we need passwords?
6767

68-
The token system developed above is very robust, but it isn't always an acceptable security measure (at least not alone). That's because, if a user loses the token, it is next to impossible (especially if it was generated with CSPRNGs with reasonable size) to gain access back to their lists using today's technologies.
68+
The token system developed above is very robust, but it isn't always an acceptable security measure (at least not alone). That's because, if a user loses the token, it is next to impossible (especially if it was generated with CSPRNGs with reasonable size) to gain access back to their lists using today's computing powers.
6969

7070
So, maybe instead of a long random token, use a password? We can ask the user when they land on our page for a passcode (aka password). And we check the database if we can find a list where `password = USER_SUBMITTED_PASSCODE` then display them. If not, that means they are a new user.
7171

7272
Indeed this works, passwords are okay and a perfectly viable and widespread approach. Keeping in mind that users tend to use easy to remember words, dates, phone numbers, and the like. This makes passwords vulnerable to brute-force attacks. It would be relatively harder than brute-forcing emails, but still easy to guess, and very easy for computers to break by checking every possible combination of words, dates, numbers, and even relatively harder passwords using a technology called **rainbow tables**.
7373

7474
Hence, there are two things to remember about passwords:
75-
They require validation to prevent brute force attacks (thus preventing easy to guess passwords)
76-
Use salt and hash to prevent rainbow attacks -- point to a code example here or include your own, and then this needs an in-depth explanation because this is probably the most important section that new people will forget about writing passwords
75+
76+
- They require validation to prevent brute force attacks (thus preventing easy to guess passwords)
77+
- Use salt and hash to prevent rainbow attacks
7778

7879
## Security Checklist
7980

@@ -95,14 +96,18 @@ Federated identity management is a configuration that can be made between two or
9596
An example of this is to offer people to sign in with Google, or Github. Here, Google is an identity provider (IdP).
9697

9798
Many benefits come with this:
98-
User convenience, they don't have to remember lots of passwords and fill preliminary registration forms.
99-
Delegate account and password management overhead to the identity provider.
100-
Sometimes, you can even skip email validation logic since that has been already done.
101-
Avoid privacy compliance burden.
99+
100+
- User convenience, they don't have to remember lots of passwords and fill preliminary registration forms.
101+
- Delegate account and password management overhead to the identity provider.
102+
- Sometimes, you can even skip email validation logic since that has been already done.
103+
- Avoid privacy compliance burden.
104+
102105
There are three protocols for federated identity:
103-
SAML
104-
OpenID
105-
OAuth
106+
107+
- SAML
108+
- OpenID
109+
- OAuth
110+
106111
We will cover OID and OAuth later in this module.
107112

108113
### Database security
@@ -125,10 +130,11 @@ The process is usually done by obtaining a certificate from a Certificate Author
125130
Testing the code correctly to ensure it achieves its intended purpose around normal and abnormal scenarios.
126131

127132
For instance, if you define an endpoint is only intended for admins, you need to test that it:
128-
Rejects gracefully any request from non-admin users
129-
Rejects requests from unauthenticated clients
130-
When if a token has expired, it redirects the request correctly
131-
These are some examples of test cases. You need to account for edge cases in your logic as well.
133+
134+
- Rejects gracefully any request from non-admin users
135+
- Rejects requests from unauthenticated clients
136+
- When if a token has expired, it redirects the request correctly
137+
- These are some examples of test cases. You need to account for edge cases in your logic as well.
132138

133139
### Update your code and libraries
134140

module4-authentication-and-security/r1.1-defining-authentication-layer/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ If any email or phone number validation is required, it is usually in this step
196196

197197
One thing to emphasize in the code above is the introduction of hashing function. BCrypt was used to salt and **hash the password before saving in the database**. Some password validation was also used to make sure any password we store in the database is strong enough against brute-force and rainbow-table attacks.
198198

199-
### **Password management**
199+
### Password management
200200

201201
Let's imagine this, we have 2 users Bob and Alice. They are using a form to register and out of coincidence they use the same password `c00k1eD0ugh`. Your app would hash this password before storing, and hash functions when given the same input, they always return the same hash. It is due to the deterministic nature of hashing functions. Your table would look like this:
202202

@@ -219,7 +219,7 @@ Fortunately, though, for Alice and Bob, while using the same password, it is not
219219
220220
Thus, Jane is at high risk of being breached through a dictionary attack. Alice and Bob are not so different, it might take some more time, but with some tools that can replace letters with similar characters like numbers or special characters. And once cracked, the attacker will have 2 user accounts simultaneously.
221221

222-
### **Mitigating the damage with salts**
222+
### Mitigating the damage with salts
223223

224224
To mitigate the damage introduced by this user vulnerability, we salt the passwords. A **salt** is a value generated by a [cryptographically secure function](https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html) that is added to the input of hash functions to create unique hashes for every input, regardless of the input not being unique. Salt makes a hash function look non-deterministic, which is good as we don't want to reveal duplicate passwords through our hashing.
225225

module4-authentication-and-security/r1.1.1-authentication-persistence/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ In this lesson, we will tackle how to persist user login, or registration betwee
66
- Implementing stateful persistence using express-sessions
77
- Implementing stateless identifiers using JSON Web Tokens (JWT)
88

9-
## **Stateful Session Storage**
9+
## Stateful Session Storage
1010

1111
In web servers, sessions are server-side temporary storage tools. They are used for a variety of use cases to store temporary data between requests. They use different storage adapters, like RAM, disk, databases, in-memory cache, etc. to save the temporary data.
1212

@@ -62,7 +62,7 @@ And when requesting protected resources, we can check if the request session tha
6262
6363
> 💡 **Tip**: `express-session` comes with lots of adapters to store sessions as plug-in libraries. Check out [this list](https://github.com/expressjs/session#compatible-session-stores).
6464
65-
## **Stateless Session Storage**
65+
## Stateless Session Storage
6666

6767
In stateless session storage, we don't store any temporary data on the server. Thus, the server is state-less. Instead, we issue a session payload in a token that encapsulates the data and sends it to the client for future use in subsequent requests. JWT is often, the way to carry out this process.
6868

@@ -101,7 +101,7 @@ To make an authenticated request by the client, it needs to pass this token to t
101101

102102
![JWT Diagram](../assets/use-of-jwt.webp)
103103

104-
### **JWT Validation**
104+
### JWT Validation
105105

106106
A middleware library like [express-jwt](https://www.npmjs.com/package/express-jwt) can be used on the server to validate JWTs.
107107

@@ -137,7 +137,7 @@ Then e can simply access the user object in the request as follows:
137137
const user = req.user;
138138
```
139139

140-
### **Issuing JWT**
140+
### Issuing JWT
141141

142142
To issue JWT, your authentication server can use a library [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken) to issue the token as follows:
143143

@@ -155,7 +155,7 @@ router.post('/login', async (req, res) => {
155155

156156
const user = await User.login(username, password);
157157

158-
if(user) {
158+
if (user) {
159159
// User is valid, issue JWT
160160
const claims = {
161161
sub: user.id,
@@ -178,15 +178,15 @@ router.post('/login', async (req, res) => {
178178
179179
> 💡 **TIP**: Always keep your tokens short-lived as they are, by design, harder to revoke. The token by default will stay functional until it expires.
180180
181-
### **JWT Signature**
181+
### JWT Signature
182182

183183
You're probably wondering: if JWTs can be easily decoded and their payload can be seen, how do we make sure that someone doesn't pass any payload to authenticate a request? The signature is the answer.
184184

185185
When issuing JWTs, we take the claims and encrypt them using the `app-secret` key. Then attach that signature to the JWT as a `base64` encoded string. Remember that the `app-secret` is only known by your app.
186186

187187
When the JWT is passed back to the server in the header, we check the claims, and sign them again using our `app-secret`, then compare this signature with the signature provided by the token. If they match, that means the JWT is indeed issued by this app. Otherwise, it is fake.
188188

189-
## **Pros and Cons of JSON Web Tokens**
189+
## Pros and Cons of JSON Web Tokens
190190

191191
JWTs are becoming more and more ubiquitous. Customer identity and access management (CIAM) providers everywhere are pushing JWTs as the silver bullet for everything. JWTs are pretty cool, but let’s talk about some of the downsides of JWTs and some of their strong benefits.
192192

module4-authentication-and-security/r1.2-adding-authorization-layer/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ With authorization, we introduce another level of app security. In this lesson,
2222
- Authentication by a client usually involves the server giving a certificate to the client in which a trusted third party such as Verisign or Thawte states that the server belongs to the entity (such as a bank) that the client expects it to. This is required to initiate secure communication (HTTPs) between client and server.
2323
- Authentication does not determine what tasks the individual can do or what files the individual can see (aka scopes). Authentication merely identifies and verifies who the person or system is.
2424

25-
## **Role-based authorization**
25+
## Role-based authorization
2626

2727
By role-based authorization, we assign a role or roles to the user either when we register them, or by some other mechanism that happens later to elevate a user access level.
2828

module4-authentication-and-security/r1.2.1-authorization-through-middleware/README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ We've seen middleware in previous lessons when we used the `express-session` and
5353
- Append the created or read `session` to `req`.
5454
- Call `next()` to let the app continue its req-res cycle.
5555

56-
### **Middleware precedence**
56+
### Middleware precedence
5757

5858
In Express.js middleware are applied in their order of use. Remember that every function that has `req` and `res` is a middleware function. And the middleware stack is established when you use `app.use` or `router.use`.
5959

@@ -68,7 +68,7 @@ So it is important whenever you define your middleware that you make sure the re
6868

6969
For example, in your `onlyAuthenticated` middleware, you will need to check `req.session.user` (or `req.user` if you use `express-jwt`). Hence, it is important that the session middleware is applied before your middleware. Otherwise, you won't have `session` inside `req`.
7070

71-
### **Middleware mount-path**
71+
### Middleware mount-path
7272

7373
Middleware can be scoped as well. It can be for every request, or for specific endpoints, or even specific HTTP methods:
7474

@@ -102,7 +102,7 @@ router.use(function (req, res, next) {
102102
});
103103
```
104104

105-
### **Error-handling middlware**
105+
### Error-handling middlware
106106

107107
All the middleware we've seen so far take only **three** arguments, `req`, `res`, and `next`. You can define an error-handling middleware by providing **four** arguments: `err`, `req`, `res`, and `next`. These middleware are important to handle errors that are thrown in your app and provide a safe fallback response to clients without exposing your app's security.
108108

@@ -117,7 +117,7 @@ Usually, an error logging service like [sentry](https://sentry.io/) is also cont
117117

118118
> ⚠️ **Warning**: Error-handling middleware always takes **four** arguments. You must provide four arguments to identify it as an error-handling middleware function. Even if you don’t need to use the next object, you must specify it to maintain the signature. Otherwise, the next object will be interpreted as regular middleware and will fail to handle errors.
119119
120-
## **Auth guard middleware**
120+
## Auth guard middleware
121121

122122
To implement `onlyAdmins`, `onlyModerators`, and `onlyAuthenticated` middleware, we create a new middleware containing source file:
123123

0 commit comments

Comments
 (0)