Skip to content

Commit 64d53dc

Browse files
docs(): add security category
1 parent b86cec7 commit 64d53dc

File tree

17 files changed

+327
-128
lines changed

17 files changed

+327
-128
lines changed
File renamed without changes.

content/security/cors.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
### CORS
2+
3+
Cross-origin resource sharing (CORS) is a mechanism that allows resources to be requested from another domain. Under the hood, Nest makes use of the Express [cors](https://github.com/expressjs/cors) package. This package provides various options that you can customize based on your requirements.
4+
5+
#### Getting started
6+
7+
To enable CORS, call the `enableCors()` method on the Nest application object.
8+
9+
```typescript
10+
const app = await NestFactory.create(AppModule);
11+
app.enableCors();
12+
await app.listen(3000);
13+
```
14+
15+
The `enableCors()` method takes an optional configuration object argument. The available properties of this object are described in the official [CORS](https://github.com/expressjs/cors#configuration-options) documentation.
16+
17+
Alternatively, enable CORS via the `create()` method's options object. Set the `cors` property to `true` to enable CORS with default settings. Alternatively, pass a [CORS configuration object](https://github.com/expressjs/cors#configuration-options) as the `cors` property value to customize its behavior.
18+
19+
```typescript
20+
const app = await NestFactory.create(AppModule, { cors: true });
21+
await app.listen(3000);
22+
```

content/security/csrf.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
### CSRF Protection
2+
3+
Cross-site request forgery (also known as CSRF or XSRF) is a type of malicious exploit of a website where **unauthorized** commands are transmitted from a user that the web application trusts. To mitigate this kind of attack you can use the [csurf](https://github.com/expressjs/csurf) package.
4+
5+
#### Use with Express (default)
6+
7+
Start by installing the required package:
8+
9+
```bash
10+
$ npm i --save csurf
11+
```
12+
13+
> warning **Warning** As explained on the [csurf middleware page](https://github.com/expressjs/csurf#csurf), the csurf module requires either session middleware or a cookie-parser to be initialized first. Please see that documentation for further instructions.
14+
15+
Once the installation is complete, apply the csurf middleware as global middleware.
16+
17+
```typescript
18+
import * as csurf from 'csurf';
19+
// somewhere in your initialization file
20+
app.use(csurf());
21+
```
22+
23+
#### Use with Fastify
24+
25+
Start by installing the required package:
26+
27+
```bash
28+
$ npm i --save fastify-csrf
29+
```
30+
31+
Once the installation is complete, register the `fastify-csrf` pluign, as follows:
32+
33+
```typescript
34+
import fastifyCsrf from 'fastify-csrf';
35+
// somewhere in your initialization file
36+
app.register(fastifyCsrf);
37+
```
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
### Encryption and Hashing
2+
3+
**Encryption** is the process of encoding information. This process converts the original representation of the information, known as plaintext, into an alternative form known as ciphertext. Ideally, only authorized parties can decipher a ciphertext back to plaintext and access the original information. Encryption does not itself prevent interference but denies the intelligible content to a would-be interceptor. Encryption is a two-way function; what is encrypted can be decrypted with the proper key.
4+
5+
**Hashing** is the process of converting a given key into another value. A hash function is used to generate the new value according to a mathematical algorithm. Once hashing has been done, it should be impossible to go from the output to the input.
6+
7+
#### Encryption
8+
9+
Node.js provides a built-in [crypto module](https://nodejs.org/api/crypto.html) that you can use to encrypt and decrypt strings, numbers, buffers, streams, and more. Nest itself does not provide any additional package on top of this module to avoid introducing unnecessary abstractions.
10+
11+
As an example, let's use AES (Advanced Encryption System) `'aes-256-ctr'` algorithm CTR encryption mode.
12+
13+
```typescript
14+
import { createCipheriv, randomBytes } from 'crypto';
15+
16+
const iv = randomBytes(16);
17+
const cipher = createCipheriv('aes-256-ctr', 'secretKey', iv);
18+
19+
const textToEncrypt = 'Nest';
20+
const encryptedText = Buffer.concat([
21+
cipher.update(textToEncrypt),
22+
cipher.final(),
23+
]);
24+
```
25+
26+
Now to decrypt `encryptedText` value:
27+
28+
```typescript
29+
import { createDecipheriv } from 'crypto';
30+
31+
const decipher = createDecipheriv('aes-256-ctr', 'secretKey', iv);
32+
const decryptedText = Buffer.concat([
33+
decipher.update(encryptedText),
34+
decipher.final(),
35+
]);
36+
```
37+
38+
#### Hashing
39+
40+
For hashing, we recommed using either the [bcrypt](https://www.npmjs.com/package/bcrypt) or [argon2](https://www.npmjs.com/package/argon2) packages. Nest itself does not provide any additional wrappers on top of these modules to avoid introducing unnecessary abstractions (making the learning curve short).
41+
42+
As an example, let's use `bcrypt` to hash a random pasword.
43+
44+
First install required packages:
45+
46+
```shell
47+
$ npm i bcrypt
48+
$ npm i -D @types/bcrypt
49+
```
50+
51+
Once the installation is complete, you can use the `hash` function, as follows:
52+
53+
```typescript
54+
import * as bcrypt from 'bcrypt';
55+
56+
const saltOrRounds = 10;
57+
const password = 'random_password';
58+
const hash = await bcrypt.hash(password, saltOrRounds);
59+
```
60+
61+
To generate a salt, use the `genSalt` function:
62+
63+
```typescript
64+
const salt = await bcrypt.genSalt();
65+
```
66+
67+
To compare/check a password, use the `compare` function:
68+
69+
```typescript
70+
const isMatch = await bcrypt.compare(password, hash);
71+
```
72+
73+
You can read more about available functions [here](https://www.npmjs.com/package/bcrypt).

content/security/helmet.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
### Helmet
2+
3+
[Helmet](https://github.com/helmetjs/helmet) can help protect your app from some well-known web vulnerabilities by setting HTTP headers appropriately. Generally, Helmet is just a collection of 14 smaller middleware functions that set security-related HTTP headers (read [more](https://github.com/helmetjs/helmet#how-it-works)).
4+
5+
> info **Hint** Note that applying `helmet` as global or registering it must come before other calls to `app.use()` or setup functions that may call `app.use()`). This is due to the way the underlying platform (i.e., Express or Fastify) works, where the order that middleware/routes are defined matters. If you use middleware like `helmet` or `cors` after you define a route, then that middleware will not apply to that route, it will only apply to middleware defined after the route.
6+
7+
#### Use with Express (default)
8+
9+
Start by installing the required package.
10+
11+
```bash
12+
$ npm i --save helmet
13+
```
14+
15+
Once the installation is complete, apply it as a global middleware.
16+
17+
```typescript
18+
import * as helmet from 'helmet';
19+
// somewhere in your initialization file
20+
app.use(helmet());
21+
```
22+
23+
#### Use with Fastify
24+
25+
If you are using the `FastifyAdapter`, install the [fastify-helmet](https://github.com/fastify/fastify-helmet) package:
26+
27+
```bash
28+
$ npm i --save fastify-helmet
29+
```
30+
31+
[fastify-helmet](https://github.com/fastify/fastify-helmet) should not be used as a middleware, but as a [Fastify plugin](https://www.fastify.io/docs/latest/Plugins/), i.e., by using `app.register()`:
32+
33+
```typescript
34+
import * as helmet from 'fastify-helmet';
35+
// somewhere in your initialization file
36+
app.register(helmet);
37+
```

content/security/rate-limiting.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
### Rate limiting
2+
3+
A common technique to protect applications from brute-force attacks is **rate-limiting**. Many Express packages exist to provide a rate-limiting feature. A popular one is [express-rate-limit](https://github.com/nfriedly/express-rate-limit).
4+
5+
#### Getting started
6+
7+
Start by installing the required package:
8+
9+
```bash
10+
$ npm i --save express-rate-limit
11+
```
12+
13+
Once the installation is complete, apply the rate-limiter as global middleware.
14+
15+
```typescript
16+
import * as rateLimit from 'express-rate-limit';
17+
// somewhere in your initialization file
18+
app.use(
19+
rateLimit({
20+
windowMs: 15 * 60 * 1000, // 15 minutes
21+
max: 100, // limit each IP to 100 requests per windowMs
22+
}),
23+
);
24+
```
25+
26+
When there is a load balancer or reverse proxy between the server and the internet, Express may need to be configured to trust the headers set by the proxy in order to get the correct IP for the end user. To do so, first use the `NestExpressApplication` platform [interface](https://docs.nestjs.com/first-steps#platform) when creating your `app` instance, then enable the [trust proxy](https://expressjs.com/en/guide/behind-proxies.html) setting:
27+
28+
```typescript
29+
const app = await NestFactory.create<NestExpressApplication>(AppModule);
30+
// see https://expressjs.com/en/guide/behind-proxies.html
31+
app.set('trust proxy', 1);
32+
```
33+
34+
> info **Hint** If you use the `FastifyAdapter`, use the [fastify-rate-limit](https://github.com/fastify/fastify-rate-limit) package instead.

content/techniques/security.md

Lines changed: 0 additions & 111 deletions
This file was deleted.

src/app/app-routing.module.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,13 @@ const routes: Routes = [
140140
(m) => m.TechniquesModule,
141141
),
142142
},
143+
{
144+
path: 'security',
145+
loadChildren: () =>
146+
import('./homepage/pages/security/security.module').then(
147+
(m) => m.SecurityModule,
148+
),
149+
},
143150
{
144151
path: 'graphql',
145152
loadChildren: () =>

src/app/homepage/menu/menu.component.ts

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,18 +82,17 @@ export class MenuComponent implements OnInit {
8282
title: 'Techniques',
8383
isOpened: false,
8484
children: [
85-
{ title: 'Authentication', path: '/techniques/authentication' },
8685
{ title: 'Database', path: '/techniques/database' },
8786
{ title: 'Mongo', path: '/techniques/mongodb' },
8887
{ title: 'Configuration', path: '/techniques/configuration' },
8988
{ title: 'Validation', path: '/techniques/validation' },
9089
{ title: 'Caching', path: '/techniques/caching' },
9190
{ title: 'Serialization', path: '/techniques/serialization' },
9291
{ title: 'Task scheduling', path: '/techniques/task-scheduling' },
93-
{ title: 'Security', path: '/techniques/security' },
9492
{ title: 'Queues', path: '/techniques/queues' },
95-
{ title: 'Logger', path: '/techniques/logger' },
93+
{ title: 'Logging', path: '/techniques/logger' },
9694
{ title: 'Cookies', path: '/techniques/cookies' },
95+
// { title: 'Events', path: '/techniques/#' },
9796
{ title: 'Compression', path: '/techniques/compression' },
9897
{ title: 'File upload', path: '/techniques/file-upload' },
9998
{ title: 'HTTP module', path: '/techniques/http-module' },
@@ -102,6 +101,21 @@ export class MenuComponent implements OnInit {
102101
{ title: 'Server-Sent Events', path: '/techniques/server-sent-events' },
103102
],
104103
},
104+
{
105+
title: 'Security',
106+
isOpened: false,
107+
children: [
108+
{ title: 'Authentication', path: '/security/authentication' },
109+
{
110+
title: 'Encryption and Hashing',
111+
path: '/security/encryption-and-hashing',
112+
},
113+
{ title: 'Helmet', path: '/security/helmet' },
114+
{ title: 'CORS', path: '/security/cors' },
115+
{ title: 'CSRF Protection', path: '/security/csrf' },
116+
{ title: 'Rate limiting', path: '/security/rate-limiting' },
117+
],
118+
},
105119
{
106120
title: 'GraphQL',
107121
isOpened: false,
@@ -201,12 +215,12 @@ export class MenuComponent implements OnInit {
201215
{ title: 'TypeORM', path: '/recipes/sql-typeorm' },
202216
{ title: 'Mongoose', path: '/recipes/mongodb' },
203217
{ title: 'Sequelize', path: '/recipes/sql-sequelize' },
218+
{ title: 'CRUD generator', path: '/recipes/crud-generator' },
219+
{ title: 'Health checks (Terminus)', path: '/recipes/terminus' },
220+
{ title: 'Documentation', path: '/recipes/documentation' },
204221
{ title: 'OpenAPI (Swagger)', path: '/recipes/swagger' },
205222
{ title: 'CQRS', path: '/recipes/cqrs' },
206223
{ title: 'Prisma', path: '/recipes/prisma' },
207-
{ title: 'Health checks (Terminus)', path: '/recipes/terminus' },
208-
{ title: 'Documentation', path: '/recipes/documentation' },
209-
{ title: 'CRUD generator', path: '/recipes/crud-generator' },
210224
{ title: 'Hot reload', path: '/recipes/hot-reload' },
211225
{ title: 'Serve static', path: '/recipes/serve-static' },
212226
],

0 commit comments

Comments
 (0)