[Node.js] 로그인 Access Token, Refresh Token

2022. 8. 16. 18:08·개발/node.js
728x90
반응형

1. Access Token

(1) 이용자가 로그인 시도

(2) 서버에서 이용자를 확인하고 입장권 (토큰)발급 하는데 JWT토큰 인증정보를 payload에 할당하고 생성

(3) 생성한 토큰을 클라이언트에 반환해주고 클라이언트가 이 토큰을 가지고 있는다.

(4) 클라이언트에서 권한을 인증 요청할때 이 토큰을 같이 보낸다.

(5) 서버는 토큰을 확인하고 payload의 인코딩되어 있는 값을 디코딩해서 사용자의 권한을 확인하고 

(입장권이 맞는지) 데이터를 반환한다.

(6) 만약에 토큰이 정상적인지 확인하고 (토큰이 썩었는지 입장권 시간이 지났는지)

(7) 날짜가 지난 토큰이면 새로 로그인 시킨다. 토큰 재발급

 

2. Refresh Token

Access token만 쓰면 인증보안에 취약할수 있고 다른사람이 악의적으로 토큰을 취득하면 토큰의 유효기간이

끝나기 전까지는 막을수 없다. (이미 입장권 보여주고 입장함)

 

Access token의 유효기간을 짧게 하고 유효기간이 짧으니까 로그인을 자주 해야하는 문제가 생기는데

이는 사용자가 이용하기 힘들다.

 

그부분을 Refresh token으로 해결할수 있다.

Refresh token과 Access token은 둘다 JWT토큰이고 Refresh token은 유효기간을 길게주고 Access token이 유효기간이 끝났을때 발급해주는 역할만 한다.

 

보통 Access token의 유효기간을 30분만 주면 Refresh token의 유효기간을 하루 주고 Access token의 유효기간이 끝나면 

Refresh token의 유효기간을 확인하고 Access token을 재발급 해준다.

 

3. Access token과 Refresh token

(1) 이용자가 로그인

(2) 서버에서 사용자를 확인하고 입장권 권한 인증 정보를 payload에 할당해서 생성

(3) Refresh token도 생성해서 서버에 저장하고 두 토큰 모두 클라이언트에 반환한다.

(4) 클라이언트도 두 토큰을 모두 저장한다.

(5) 클라이언트가 권한인증이 필요해서 요청하면 Access token을 전달해서 요청한다.

(6) 서버는 전달받은 토큰을 확인하고 payload의 인코딩된 값을 디코딩해서 사용자의 권한을 확인한다.

(7) 토큰이 정상적인지 확인을 한다.

(8) 날짜가 지난 토큰이면 새로 로그인 시켜서 토큰을 발급받게 한다.

(9) 서버는 Access token과 Refresh token을 확인하고 Refresh token이 만료되지 않았으며

새로운 Access token을 발급해서 클라이언트에 전달한다.

 

4. Access token의 유효기간이 짧은 이유

해커가 악의적으로 access token을 얻었을때 로그인이 이미 되어있는 상태라 막기가 힘들다.

그렇기 때문에 access token의 유효기간을 짧게 하고 refresh token의 유효기간을 길게해서

refresh token을 다시 확인시켜서  사용자가 로그인을 자주하는 불편함을 보완해준다.

또한 refresh token으로 악의적으로 탈취된 access token을 갱신해주는 역할도 해준다.

 

5. 해보기

const express = require("express");
//서버 객체 생성
const app = express();
const dot = require("dotenv");
const cookie = require("cookie-parser");
const jwt = require("jsonwebtoken");
const fs = require("fs");

// .env파일을 사용하기 위해 설정
dot.config();

// bodyparser 필요없이 바로 body객체를 이용할수 있다.
app.use(express.urlencoded({ extended: false }));

//헤더에 쿠키를 추가하기 위해서 사용
app.use(cookie());

//사용자 정보 객체 하나 더미
const user = {
  id: "taesk",
  password: "123",
};

app.get("/", (req, res) => {
  fs.readFile("view/index.html", "utf-8", (err, data) => {
    console.log(err);
    res.send(data);
  });
});

app.post("/login", (req, res) => {
  //아이디 비밀번호
  const { userId, userPw } = req.body;
  //아이디 비밀번호 검증
  if (userId === user.id && userPw === user.password) {
    // access token 발급
    const accessToken = jwt.sign(
      {
        id: user.id,
      },
      process.env.ACCESS_TOKEN_KEY,
      {
        expiresIn: "5m",
      }
    );
    // refresh token 발급
    const refreshToken = jwt.sign(
      {
        id: user.id,
      },
      process.env.REFRESH_TOKEN_KEY,
      {
        expiresIn: "1d",
      }
    );
    //쿠키의 이름은 refresh 유효 시간은 하루
    res.cookie("refresh", refreshToken, { maxAge: 24 * 60 * 60 * 1000 });
    // fs에 readFile함수를 사용해서 join.html을 불러온다. res의 send함수로 응ㄷㅂ
    fs.readFile("view/join.html", "utf-8", (err, data) => {
      res.send(accessToken, data);
    });
    return res.send(accessToken);
  } else {
    return res.send("아이디 비밀번호 오류");
  }
});

app.post("/refresh", (req, res) => {
  //?. 뒤에 오는 키값이 있으면 먼저 확인하고 값 반환
  // 키값이 없어도 크래쉬 방지
  if (req.cookies?.refresh) {
    const refreshtoken = req.cookies.refresh;
    // refresh token이 정상인지 확인
    jwt.verify(refreshtoken, process.env.REFRESH_TOKEN_KEY, (err, decode) => {
      //에러가 있으면 refresh token이 썩었기 때문에 다시 로그인 시킨다.
      if (err) {
        res.send("로그인을 다시 하세요");
      } else {
        //err가 없고 정상적인 토큰이면 다시 access token발급
        // jwt에 sign함수로 토큰 다시 생성
        const accessToken = jwt.sign(
          {
            //token의 payload값
            id: user.id,
          },
          //토큰을 암호화시킬 key값
          process.env.ACCESS_TOKEN_KEY,
          {
            expiresIn: "10m",
          }
        );
        res.send(accessToken);
      }
    });
  } else {
    res.send("다시 로그인 해주세요");
  }
});

app.listen(3000, () => {
  console.log("서버열림");
});
728x90
반응형

'개발 > node.js' 카테고리의 다른 글

[Node.js] crypto, bcrypto  (0) 2022.08.17
[Node.js] access token, refresh token 을 활용하여 로그인 유지시키기  (0) 2022.08.16
[Node.js] exports router  (0) 2022.08.10
[Node.js] 로그인시 jwt과 session  (0) 2022.08.09
[Node.js] 로그인시 JWT생성  (0) 2022.08.09
'개발/node.js' 카테고리의 다른 글
  • [Node.js] crypto, bcrypto
  • [Node.js] access token, refresh token 을 활용하여 로그인 유지시키기
  • [Node.js] exports router
  • [Node.js] 로그인시 jwt과 session
TeTedo.
TeTedo.
  • TeTedo.
    TeTedo 개발 일기
    TeTedo.
  • 전체
    오늘
    어제
    • 분류 전체보기 (319)
      • 개발 (274)
        • Article (4)
        • 정리 (21)
        • Spring Boot (17)
        • JPA (2)
        • JAVA (6)
        • Database (4)
        • 자료구조 (11)
        • 알고리즘 (32)
        • React (20)
        • Docker (10)
        • node.js (18)
        • Devops (11)
        • Linux (4)
        • TypeScript (3)
        • Go (10)
        • HyperLedger (4)
        • BlockChain (43)
        • html, css, js (48)
        • CS (3)
        • AWS (3)
      • 모아두고 나중에 쓰기 (3)
      • 팀프로젝트 (18)
        • SNS(키보드워리어) (9)
        • close_sea (9)
      • 개인프로젝트 (1)
        • Around Flavor (1)
        • CHAM (13)
        • ethFruitShop (5)
      • 독서 (0)
        • 스프링부트와 AWS로 혼자 구현하는 웹 서비스 (0)
  • 블로그 메뉴

    • 홈
    • 개발일기
    • CS
    • 실습
    • 코딩테스트
    • 웹
    • Go
    • node.js
    • 팀플
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    30일 챌린지
    erc20
    node.js
    mysql
    node
    도커
    하이퍼레저
    React
    html
    js
    블록체인
    30일챌린지
    명령어
    go언어
    go
    컨테이너
    ERC721
    nodejs
    CSS
    프로그래머스
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
TeTedo.
[Node.js] 로그인 Access Token, Refresh Token
상단으로

티스토리툴바