ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Nest.js] 11 - Authentification - JWT
    Nest.js 2021. 9. 14. 10:59

    Contents
    1. JWT?
    2. JWT Structure
    3. JWT Flow
    4. Why use JWT?
    5. What to consider about JWT
    6. Passport?
    7. Module installation
    8. Generate JWT


    1. JWT(JSON Web Token)

    - JWT is a proposed internet standard for creating data with optional Signature and/and/or optional encryption whose payload holds JSON that asserts some number of claims. The tokens are signed either using a private secret or a public/private key.

    - In short, JWT helps us send information safely and validate a user's authetification.


    2. JWT Structure

    1. Header
    - Signature or encryption algorithm

    {
      "alg": "HS256",
      "typ": "JWT"
    }

     

    2. Payload
    - Data( issuer, expiration time, subject....)

    {
      "sub": "1234567890",
      "name": "John Doe",
      "iat": 1516239022
    }

     

    3. Verify Signature
    - Header + Payload + Signature algorithm + public/private key.
    - It would use to validate a signature, which is sent from a sender. Also, it checks whether it is changed or not.


    3. JWT Flow

    - Log in 

     

    - Boards for "Admin"

    1. when admin user wants to see the boards, which are allowed to "Admin only"
    2. In Client, the user sends a request together with Token in Header

     

      3. In Server, a server takes headers and payload from the request,
          and it makes another Signature using those two and Secret text, which is saved in server.

      4. now, it checks the request's signature and the new signature(made at #3) 

      5. If validated OK, the admin user sees boards for "Admin".

     

    - JWT Entire Flow 

    https://www.vaadata.com/blog/jwt-tokens-and-security-working-principles-and-use-cases/

     


    4. Why use JWT?

    • JWT is based on a token authentification, it doesn't need a session to save user's information,
         so it helps lighten Load on server side. 
    • JWT is used on Microservice, where JWT is used for Authentification and Authorization.
    • JWT is helpful to manage access authentifications.
    • JWT is great for Scalable Web Architectures
    • JWT has all information, which is necessary for authentification,
         so it doesn't need any authentification repository, such as Database table.
    • JWT is Server Resource-Economizing and Effective way on reducing server load.

    5. What to consider about JWT

    • Compromised Secret Key 
      JWT relies on just one key, which is "secret key". Therefore, if the key handled poorly by a developer/administrator, it would lead to severe consequences that can compromise sensitive information
    • Data Overhead
      If a developer adds more information in the token, it will impact on the overall loading speed.
    • Shorter Lifespan
      Short-lived JWT are harder for users to work with. These tokens require frequent reauthorizztion, which can be annoying at times, especially for the clients. One of reason why JWT's lifespan is short is that we cannot manually expire a token after it has been created. Thus, we set a reasonable expiration time on tokens.
    • Payload Encoding
      One of the segment where saves data is Payload after the data encodes Base64. The problem might be occurred when Payload is captured during the token is available. It is easily decoded and taken user's data.
      Therefore, Payload should be contained any important inforamtion.

    6. Passport?

    - Passport is the most popular node.js authentication library, well-known by the community and successfully used in many production applications. It's straightforward to integrate this library with a Nest application using the @nestjs/passport module.

    - Passport executes a series of steps to:

    • Authenticate a user by verifying their "credentials" (such as username/password, JSON Web Token (JWT), or identity token from an Identity Provider)
    • Manage authenticated state (by issuing a portable token, such as a JWT, or creating an Express session)
    • Attach information about the authenticated user to the Request object for further use in route handlers.

    - Passport supports JWT authentification process much easier.


    7. Module Installation

    - @nestjs/jwt, @nestjs/passport, passport, passport-jwt

    $ npm install @nestjs/jwt @nestjs/passport passport passport-jwt --save

    8. Generate JWT

    - src/auth/auth.module.ts

    ...
    import { JwtModule } from '@nestjs/jwt';
    import { PassportModule } from '@nestjs/passport';
    ...
    
    @Module({
      imports: [
        PassportModule.register({ defaultStrategy: 'jwt' }), // 1
        JwtModule.register({ // 1
          secret: 'Secret1234', // 2
          signOptions: {
            expiresIn: 3600, // 3
          },
        }),
        TypeOrmModule.forFeature([UserRepository]),
      ],
      controllers: [AuthController],
      providers: [AuthService],
    })
    export class AuthModule {}

    // 1. register the installed module in the AuthModule

    // 2. secret: 'XXX'  - set up a Secret text

    // 3. expriesIn: 3600 - 60 * 60, means that a token would last for an hour.

     

    - src/auth/auth.service.ts

    ...
    import { JwtService } from '@nestjs/jwt';
    
    @Injectable()
    export class AuthService {
      constructor(
        @InjectRepository(UserRepository)
        private userRepository: UserRepository,
        private jwtService: JwtService, // 1
      ) {}
    
      async signUp(authCredentialsDto: AuthCredentialsDto): Promise<void> {
        return this.userRepository.createUser(authCredentialsDto);
      }
    
      async signIn(
        authCredentialsDto: AuthCredentialsDto,
      ): Promise<{ accessToken: string }> { // 2
        const { username, password } = authCredentialsDto;
        const user = await this.userRepository.findOne({ username });
    
        if (user && (await bcrypt.compare(password, user.password))) {
          // log in success
          const payload = { username }; // 3
          const accessToken = await this.jwtService.sign(payload); // 4 
          return { accessToken };
        } else {
          throw new UnauthorizedException('login failed');
        }
      }
    }

    // 1. Dependency Injection of JwtService

    // 2. changed the return type to Object.

    // 3. payload :  Don't put a crucial information in payload

    // 4. await this.jwtService.sign(payload); this method makes an initiative token with Secret text + payload.

     

    - src/auth/auth.controller.ts

    import { Body, Controller, Post } from '@nestjs/common';
    import { AuthService } from './auth.service';
    import { AuthCredentialsDto } from './dto/auth-credential.dto';
    
    @Controller('auth')
    export class AuthController {
      constructor(private authService: AuthService) {}
    
      ...
    
      @Post('/signin')
      signIn(
        @Body() authCredentialsDto: AuthCredentialsDto,
      ): Promise<{ accessToken: string }> { // 1
        return this.authService.signIn(authCredentialsDto);
      }
    }

    // 1. return type changed to what its service method returns

     

    - Request and Response

    // Once a user logged in successfully, the server provides the JWT to the client.

     

    - JWT Decoding at https://jwt.io

    // Signature is omitted because there is no information.

Designed by Tistory.