Token

세션 기반 인증은 서버 혹은 데이터베이스에 유저 정보를 담아두는 방식이다. 때문에 어떤 요청이 있을 때 마다 인증된 사용자인지를 확인해야 하는 부담이 있다. 이 부담을 클라이언트에 넘기는 방식이 토큰 기반 인증이다.
대표적인 토큰 기반 인증에는 JWT(JSON Web Token)가 있다.

Token이란

클라이언트에서 인증 정보를 보관하는 방법으로 토큰 기반 인증이 고안되었고 클라이언트가 토큰을 가지고 있다면 서버에서 제공하는 다양한 기능을 요청할 수 있다.
인증 정보를 암호화한 상태로 담기 때문에 클라이언트에 담을 수 있다.

JWT (JSON Web Token)

JSON 포맷으로 사용자에 대한 속성을 저장하는 웹 토큰이다.
Header, Payload, Signature로 구성되어있다.
1. Header
어떤 종류의 토큰인지와 어떤 알고리즘으로 암호화할지가 젹혀있다. JSON Web Token이라는 이름에 맞게 JSON 형태로 볼 수 있고 이 JSON 객체를 base64 방식으로 인코딩하면 JWT의 첫 번째 부분이 완성된다.

{
  "alg": "HS256",
  "typ": "JWT"
}
  1. Payload
{
  "sub": "someInformation",
  "name": "kimcoding",
  "iat": 151623391
}

정보가 담겨있는 부분이다. 어떤 정보에 접근 가능한지에 대한 권한을 담을 수도 있고 사용자의 유저 이름 등 필요한 데이터를 담아 암호화 시킨다. 헤더에서 정의한대로 암호화가 될 정보지만 민감한 정보는 되도록 담지 않는 것이 좋다. 마찬가지로 JSON 객체를 base64로 인코딩하면 JWT의 두 번째 블록이 완성된다.
3. Signature

HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret);

원하는 비밀 키(salt)를 사용하여 암호화한다. base64 인코딩을 한 값은 누구나 쉽게 디코딩할 수 있지만 서버에서 사용하고 있는 비밀 키를 보유한게 아니라면 해독해내는데 엄청난 시간과 노력이 필요하다.


토큰 사용해보기

클라이언트로부터 로그인 요청이 온다.

로그인 정보(아이디, 비밀번호)를 확인하고 유효한 정보라면 토큰을 생성해 클라이언트에게 보내준다. 이때 토큰은 access 토큰과 refresh 토큰을 각각 만든다. 보통은 refresh 토큰의 수명이 더 길다.

const jwt = require("jsonwebtoken");
// 예시
const token = jwt.sign(payload, ACCESS_SECRET, { algorithm: "HS256", expiresIn: "1h" });

response의 body에 토큰을 담아서 보내주면 클라이언트는 이를 state나 쿠키 등에 담아서 보관한다. 이번 실습에서 access 토큰은 state에, refresh 토큰은 쿠키에 담아 보관했다.

클라이언트는 토큰을 잘 보관하고 있다가 무언가 서버에 요청이 필요할 때 헤더에 담아 함께 보낸다.

서버에서는 요청의 헤더를 열어 토큰이 있는지를 확인하고 없다면 에러를, 있다면 이를 복호화해서 내용을 확인한다.

또 복호화가 제대로되지 않거나 기한이 지난 토큰이라면 유효하지 않은 토큰이므로 에러를, 제대로 복호화가 되고 권한을 갖고 있다면 그에 알맞은 응답을 보내주게 된다.

const data = jwt.verify(
    token,
    ACCESS_SECRET,
    (error, decoded) => {
      if (error) {
        //console.log(error);
      } else {
        return decoded;
      }
    }
  );

비밀 키는 당연히 .env 파일에 적어 환경변수로 관리한다.
만약 access 토큰이 만료되어 클라이언트 측에서 refresh를 요청한다면 서버에서는 클라이언트의 쿠키에 refresh 토큰이 들어있는지를 확인하고 이를 통해 유효한, 권한이 있는 사용자임이 확인된다면 access 토큰을 재발급해주게 된다.

코드도 코드지만 흐름을 잘 파악해야 써먹을 때 혼란이 없을 것 같다.

좋은 웹페이지 즐겨찾기