# JWT strategy

We can now proceed to the **JWT** part in order to conclude authentication.

> If you are not familiar with the concept of JWT (JSON Web Token), I recommend [this article](https://jwt.io/introduction).

Let's go back to the <mark style="color:blue;">`AuthService`</mark> and inject there the <mark style="color:blue;">`JwtService`</mark>. It allows for signing the token. Then, add the <mark style="color:blue;">`login()`</mark> method, responsible for returning the JWT from the user data.

```typescript
login(user: RequestUser) {
  const payload = { sub: user.id };
  return this.jwtService.sign(payload);
}
```

{% hint style="info" %}
The identification field in the payload is called <mark style="color:blue;">`sub`</mark> to keep consistency with JWT standards.
{% endhint %}

However, with this current solution, we'll soon face the same situation of the <mark style="color:blue;">`user`</mark> extracted from the <mark style="color:blue;">`request`</mark>. That is, the lack of typing. Let's then already solve this. Create the file <mark style="color:purple;">auth</mark>/<mark style="color:purple;">interfaces</mark>/<mark style="color:purple;">jwt-payload.interface</mark>.

```typescript
export interface JwtPayload {
  readonly sub: number;
}
```

And apply the type of this interface to the <mark style="color:blue;">`payload`</mark>.

```typescript
const payload: JwtPayload = { sub: user.id };
```

Now, we should create environment variables for the JWT: **SECRET** and **TTL** (time-to-live). We'll perform that entire process related to creating, typing and using environment variables:

* In the <mark style="color:purple;">.env</mark> file, create the variables <mark style="color:blue;">`JWT_SECRET`</mark> and <mark style="color:blue;">`JWT_TTL`</mark>

{% hint style="info" %}
Some notes:

* It is recommended to use a **long** and **unique** secret, like a password from [GRC generator](https://www.grc.com/passwords.htm)

* The TTL may be in [ms](https://www.npmjs.com/package/ms) format, like <mark style="color:blue;">`7d`</mark> (seven days)
  {% endhint %}

* Update the <mark style="color:purple;">.env.example</mark> file accordingly

* Require the existence of these variables in the <mark style="color:blue;">`ENV_VALIDATION_SCHEMA`</mark>

* Create a namespace in the file <mark style="color:purple;">auth</mark>/<mark style="color:purple;">config</mark>/<mark style="color:purple;">jwt.config</mark>

```typescript
export default registerAs('jwt', () => {
  const config = {
    secret: process.env.JWT_SECRET,
    signOptions: {
      expiresIn: process.env.JWT_TTL,
    },
  } as const satisfies JwtModuleOptions;
  return config;
});
```

* In the <mark style="color:blue;">`AuthModule`</mark>, add to the <mark style="color:blue;">`imports`</mark> the <mark style="color:blue;">`JwtModule`</mark>, configuring it with the <mark style="color:blue;">`jwtConfig`</mark>

```typescript
JwtModule.registerAsync(jwtConfig.asProvider()),
```

What is being done here, is to set the **secret**, which is needed to **sign the token**. We're also setting the token's **expiration time**. And of course, using the <mark style="color:blue;">`JwtService`</mark> to create this **signature**.

In the <mark style="color:blue;">`AuthController`</mark>, we can then return the JWT in the <mark style="color:blue;">`login()`</mark> route.

```typescript
return this.authService.login(user);
```

Let's just alter this route to return the JWT as a **cookie**, as it is considered a good practice for better safety. The options passed to the <mark style="color:blue;">`cookie`</mark> below increase the security of this process:

* <mark style="color:blue;">`secure`</mark>: Is sent only over **HTTPS**
* <mark style="color:blue;">`httpOnly`</mark>: Cannot be accessed by JavaScript code, preventing **XSS** attacks
* <mark style="color:blue;">`sameSite`</mark>: Is sent only for same domain, preventing **CSRF** attacks (<mark style="color:red;">not</mark> to be used if Frontend and Backend are in different domains)

```typescript
@Post('login')
login(
  @User() user: RequestUser,
  @Res({ passthrough: true }) response: Response,
) {
  const token = this.authService.login(user);
  response.cookie('token', token, {
    secure: true,
    httpOnly: true,
    sameSite: true,
  });
}
```

{% hint style="info" %}
Some notes:

* The <mark style="color:blue;">`Response`</mark> type is from <mark style="color:blue;">`express`</mark>
* The <mark style="color:blue;">`passthrough`</mark> option allows Nest to keep control of the <mark style="color:blue;">`response`</mark> in its pipeline
* In a real-world system, you may need to configure some CORS options to be able to successfully use cookies with those options
  {% endhint %}

Excellent, we're receiving a JWT when sending correct credentials. It is what will be used to verify whether or not we have permission to access a route. In the <mark style="color:blue;">`JwtModule`</mark> configuration, we use the <mark style="color:blue;">`secret`</mark> to generate the signature of the <mark style="color:blue;">`token`</mark> that is returned. In the next step, we'll once again need the <mark style="color:blue;">`secret`</mark>, but this time to verify if the <mark style="color:blue;">`token`</mark> is valid when accessing protected routes. Let's then add one more item to the <mark style="color:blue;">`imports`</mark> of the <mark style="color:blue;">`AuthModule`</mark>.

```typescript
ConfigModule.forFeature(jwtConfig),
```

Now, create the file <mark style="color:purple;">strategies</mark>/<mark style="color:purple;">jwt.strategy</mark> with following contents. We're performing the same process we did earlier of injecting a configuration namespace, but now, instead of doing this inside a dynamic module, we're doing it in a provider.

```typescript
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy) {
  constructor(
    @Inject(jwtConfig.KEY)
    private readonly jwtConfiguration: ConfigType<typeof jwtConfig>,
  ) {
    super({
      jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
      secretOrKey: jwtConfiguration.secret,
    });
  }

  validate(payload: JwtPayload) {
    const requestUser: RequestUser = { id: payload.sub };
    return requestUser;
  }
}
```

{% hint style="info" %} <mark style="color:blue;">`Strategy`</mark> should be imported from <mark style="color:blue;">`passport-jwt`</mark>.
{% endhint %}

Here, we're stating that, when a user tries to access a route that requires authentication, their JWT will be extracted as a **Bearer Token**, which is a recommended form to send it. And the <mark style="color:blue;">`secret`</mark> to be used in the token validation is the same we've already defined. The <mark style="color:blue;">`validate()`</mark> method has basically the same return as the one in the <mark style="color:blue;">`LocalStrategy`</mark>, because Passport's strategies always append the return of this method to the <mark style="color:blue;">`request`</mark> as the <mark style="color:blue;">`user`</mark> field.

{% hint style="info" %}
Remember to add the <mark style="color:blue;">`JwtStrategy`</mark> to the <mark style="color:blue;">`providers`</mark> of the <mark style="color:blue;">`AuthModule`</mark>.
{% endhint %}

However, there is a situation that may appear as a security vulnerability. Imagine that a user account has been deleted. If the <mark style="color:blue;">`token`</mark> has not expired yet, it will still be possible to access routes with it. So, let's go back to the <mark style="color:blue;">`AuthService`</mark> and create the method <mark style="color:blue;">`validateJwt()`</mark>, which checks the existence of the <mark style="color:blue;">`user`</mark> to whom a <mark style="color:blue;">`token`</mark> is associated.

```typescript
async validateJwt(payload: JwtPayload) {
  const user = await this.usersRepository.findOneBy({ id: payload.sub });
  if (!user) {
    throw new UnauthorizedException('Invalid token');
  }

  const requestUser: RequestUser = { id: payload.sub };
  return requestUser;
}
```

After that, back in the <mark style="color:blue;">`JwtStrategy`</mark>, call <mark style="color:blue;">`validateJwt()`</mark> inside the <mark style="color:blue;">`validate()`</mark> method. Now, a <mark style="color:blue;">`token`</mark> is valid only if its respective <mark style="color:blue;">`user`</mark> still exists in the database.

```typescript
validate(payload: JwtPayload) {
  return this.authService.validateJwt(payload);
}
```

In the next step, we'll use the <mark style="color:blue;">`AuthGuard`</mark> of type <mark style="color:blue;">`jwt`</mark>. So, let's already create another guard to represent it due to the reason already discussed of avoiding magic strings.

```sh
nest g gu auth/guards/jwt-auth
```

```typescript
@Injectable()
export class JwtAuthGuard extends AuthGuard('jwt') {}
```

Then, in the <mark style="color:blue;">`AuthController`</mark>, let's create the route <mark style="color:blue;">`getProfile()`</mark>, which returns the <mark style="color:blue;">`user`</mark> that has the same <mark style="color:blue;">`id`</mark> of the <mark style="color:blue;">`user`</mark> appended to the <mark style="color:blue;">`request`</mark>. We shall also protect it with our newly-created guard.

```typescript
@UseGuards(JwtAuthGuard)
@Get('profile')
getProfile(@User() { id }: RequestUser) {
  return this.authService.getProfile(id);
}
```

And now, create the namesake method in the <mark style="color:blue;">`AuthService`</mark>.

```typescript
getProfile(id: number) {
  return this.usersRepository.findOneBy({ id });
}
```

Great! Authentication is now functional. However, before proceeding to authorization, there's still one pending issue we should give attention to. Not all routes should require authentication, so we must learn how to have **public** routes.

<mark style="color:green;">**Commit**</mark> - Jwt strategy
