[Node.js] JWT 적용하기

이예빈·2022년 4월 28일
0

authorization을 구현할 수 있는 방법으로 Session과 Token을 포스팅 한 적이 있습니다.
( https://velog.io/@yebb/Authorization-Session-vs-Token)

오늘은 프로젝트에서 어떻게 JWT를 사용해볼 수 있을지 정리해보려 합니다..

Step 1 - Token 만들기

아래 명령어로 프로젝트에 jsonwebtoken을 설치합시다 :

npm install jsonwebtoken

token을 sign하려면 3가지 정보가 필요합니다.
1. secret key
2. token으로 해싱할 data
3. token 만료시간

주의 :
secret key가 너무 심플하면 token verification 프로세스를 분해하는데 너무 쉬워질 위험이 있다.
따라서,

이제, secret key를 프로젝트의 .env파일에 저장합시다. :

TOKEN_SECRET=09f26e402586e2faa8da4c98a35f1b20d6b033c60... //예시를 위한 임의의 secret key값

주의 :
secret key가 노출되면 안되므로 .env파일은 깃헙에 올라가지 않도록
.gitignore파일에도 추가해주자.

Node.js파일에 token을 가져와 사용하기 위해선 dotenv를 사용해야 합니다..
dotenv도 설치해주자

npm install dotenv

그 다음 아래와 같이 파일에 import 해주자 :

import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';

//get config vars
dotenv.config();

// access config var
process.env.TOKEN_SECRET;

token에 해싱할 데이터는 user ID 나 username 또는 더 복잡한 object같은 것이 될 수도 있으나 어떤 경우이든 해싱할 데이터는 특정 user를 식별할 수 있는 식별자여야 합니다.

주의 : 디코딩하면 노출되므로 사용자의 민감한 정보는 담지 말아야!

token 만료시간은 string으로 1800초(30분) 같은 값이 들어가는데 여기에 얼마나 token을 유효하게 할 것인지 지정합니다.

function generateAccessToken(username) {
  return jwt.sign(username, process.env.TOKEN_SECRET, { expiresIn: '1800s' });
}

이는 user의 회원가입이나 로그인 요청에서 쓰일 수 있습니다. :

app.post('/api/createNewUser', (req,res) => {
  //...
  
  //token생성하여 응답으로 보내기
  const token = generateAccessToken({username:req.body.username});
  res.json(token);
  //...
});

위 예시에서 requestusername을 받아 token을 만들어 response를 보냈습니다.

Step 2 - Token 인증하기

Express.js 어플리케이션에서 JWT authentication을 구현하는 방법은 매우 다양합니다.

한가지 방법은 Express.js의 middleware기능을 활용하는 것입니다.

특정 route에 request가 왔을 때 app.get((req,res)=>{})에 지정된 것보다 먼저 중개 역할을 하는 function에서 req,res변수를 전달할 수 있습니다.

middleware는 function으로 (req,res,next) parameters를 가집니다.

  • req : GET, POST, PUT, DELETE 등으로 보내진 request.
  • res : 다양한 방식으로 user에게 다시 보내질 response.
    (e.g) res.sendStatus(200), res.json() 등)
  • next : next는 middleware의 실행을 지나 실제 app.get서버 응답으로 전해지도록 호출되는 function입니다.

여기 authentication을 위한 middleware의 예시 입니다. :

import jwt from 'jsonwebtoken';

function authenticateToken(req, res, next) {
  const authHeader = req.headers['authorization'];
  const token = authHeader && authHeader.split(' ')[1];

  if (token == null) return res.sendStatus(401)

  //token 검증
  jwt.verify(token, process.env.TOKEN_SECRET as string, (err: any, user: any) => {
    console.log(err)

    if (err) return res.sendStatus(403)

    req.user = user

    next()
  })
}

이 middleware function을 사용하는 request의 예시는 다음과 같은 형태입니다. :

GET https://example.com:4000/api/userOrders
Authorization: Bearer JWT_ACCESS_TOKEN

그리고 middleware를 사용하는 request의 예는 다음과 같습니다.

app.get('/api/userOrders', authenticateToken, (req, res) => {
  // executes after authenticateToken
  // ...
});

이 코드는 client가 전달한 token을 인증하는 코드입니다.
만약 token이 유효하다면, request를 계속할 수 있고
그렇지 않다면, error로 처리될 것입니다.

Step 3 - 클라이언트 측에서 Token 다루기

client가 token을 받게 되었을 때, 미래의 request에서 user 정보를 수집하기 위해 token을 저장해두기도 합니다.

auth token을 저장하는 가장 대중적인 방법은 HttpOnly cookie에 저장하는 것 입니다.

client측 js code를 사용해 cookie 저장을 구현해 보았습니다. :

// get token from fetch request
const token = await res.json();

// set token in cookie
document.cookie = `token=${token}`

이는 미래에 서버로 request를 보낼 수 있도록 참조할 수 있는 곳에 local하게 response를 저장해두는 방식입니다.

참고
https://www.digitalocean.com/community/tutorials/nodejs-jwt-expressjs

0개의 댓글