오늘은 JWT(Json Web Token)와 세션관리에 대해서 정리해 보도록 하겠습니다.
1. JSON Web Token(JWT)
JWT는 토큰 정보와, 해당 토큰이 유효함을 증명할 수 있는 signature가 포함되어 있는 토큰인데요.
JWT는 Header, Payload, 그리고 Signature로 구성되어 있는데요.
Header는 signing algorithm과 어떤 타입의 토큰인가로 구성할 수 있는데요.
비대칭인 RS256과 같은 알고리즘을 쓸 수도 있고, HS256을 쓸 수도 있겠지요.
{
"alg": "HS256",
"typ": "JWT"
}
Payload에는 유저에 대한 상태나 정보등을 담을 수 있는데요.
아래와 같은 정보들을 담을 수 있습니다.
{
"sub": "77823323",
"name": "Big Park",
"iat": 1516239122
}
마지막은 signature는 아래와 같이 구성할 수 있습니다.
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
https://jwt.io/ 에 가면 아래와 같이 실제로 인코딩된 값을 볼 수 있습니다.
2. JWT 구현
2-1. JWT라이브러리 설치
JWT라이브러리는 www.jwt.io/를 참고하면 알 수 있는데요.
Nodejs에서는 jsonwebtoken 모듈을 사용할 수 있습니다.
아래 npm명령어로 jsonwebtoken을 설치해 줍니다.
npm install --save jsonwebtoken
해당 패키지에 대한 공식git허브 페이지는 아래와 같습니다.
https://github.com/auth0/node-jsonwebtoken
그럼 이제 본격적으로 JWT를 구현해 보도록 하겠습니다.
로그인과 로그아웃의 UI 및 컨트롤러가 구현된 상태라고 가정하고,
JWT를 발행하고 검증하는 단계에 대해서 정리해 보도록 하겠습니다.
먼저 jwt모듈을 require 합니다.
const jwt = require('jsonwebtoken');
2-2. 토큰 발행하기
토큰을 발행하기 위해서는 아래와 같은 형식을 따르는데요.
payload는 객체나 string형태로 모두 전달 가능하구요.
secret는 signature를 만들 때 사용하는 문자열을 넣어줍니다.
이것을 실수로 클라이언트에 넘겨주면, 바꾸고 전체토큰을 무효화 시켜주어야 겠지요.
jwt.sign(payload, secret, options, [callback])
아래와 같이 토큰을 발행 할 수 있습니다.
위에서 본 인자 순서대로 값을 넣어 줍니다.
여기에서 expiresIn는 유효기간인데,
"2 days", "10h", "7d" 같이 시간, 일 등의 단위를 사용할 수 있습니다.
만약 단위를 사용하지 않는다면 ms단위로 처리가 됩니다.
jwt.sign(
{ nickname: 'ladida'},
'secret',
{ expiresIn: '1h' }
);
이렇게 발행된 토큰을 서버에서 HTTP의 Response 헤더에 넣어서 클라이언트에게 전달해 주면 되겠지요.
access token의 경우는 x-access-token (사용자 정의라는 의미에서 붙이는 x를 추가함)과 x-refresh-token과 같은 이름으로 넣어줄 수 있겠습니다.
2-3. 토큰 검증하기
토큰 발행하는 것처럼 토큰을 검증하는 로직도 복잡하지 않습니다.
jwt.verify(token, 'wrong-secret', function(err, decoded) {
if(err) console.log(err);
console.log("decoded payload", decoded);
});
이렇게 해서 토큰을 발행하고 검증하는 것에 대해 알아보았구요.
이러한 토큰을 좀 더 안전하게 사용하는 방법으로서의
액세스 토큰과 리프레쉬 토큰에 대해서 알아보겠습니다.
3. 세션관리와 JWT토큰
위에서 세션관리에 사용할 JWT토큰에 대해서 정리해 보았는데요.
세션관리에 대해서 좀 더 보도록 하겠습니다.
사용자들은 크롬이나 익스플로러 같은 브라우저를 가지고 접속을 하게 되는데요.
접속후에 로그인이라는 과정을 거쳐 해당사이트의 컨텐츠를 사용하거나 특정 요청을 할 수 있습니다.
그러나 계속 로그인을 하게 하는 것은 매우 불편한 일이므로 보통은 사용자의 세션에 그 상태를 저장하는데요.
3-1. 서버에 세션을 저장하는 방법
세션은, 서버의 메모리에 저장하기도 하고, 데이터베이스에 넣을 수도 있습니다.
사용자가 많을수록, 메모리든 데이터베이스든 부하를 받게 되는 부분이 있지만,
언제든 문제가 생기면 무효화 할 수 있으므로 대응이 빠르다고 할 수 있습니다.
3-2. 클라이언트에 세션을 저장하는 방법
세션을 클라이언트에 저장할 경우, 암호화된 JWT토큰을 사용해 저장할 수 있는데요.
유저의 로그인정보를 서버에 담지 않을 수 있다는 점에서 부하를 덜 수 있지만,
혹여 탈취되었을 때의 문제가 있으므로 세심한 주의가 필요합니다.
유저가 로그인인증을 하면 서버에서 사인된 토큰을 발급받구요.
클라이언트에서 이 토큰을 저장한 다음,
헤더값에 토큰값을 전송해서 서버에서 검증받는 방식입니다.
서버에 상태를 저장하지 않으므로,
서버부하를 상당히 줄여준다는 면에서는 아주 좋습니다.
하지만 반대로 서버가 컨트롤 할 수가 없으므로,
클라이언트의 컴퓨터가 탈취당한 경우 유효시간까지는,
강제로 개별 클라이언트에 해당토큰을 무효화 할 방법이 존재하지 않습니다.
유저가 비밀번호를 변경한 경우에도,
이전 비밀번호로 유효했던 토큰에 대해 서버가 개별적으로 무효화 시킬 수 없으므로,
유효기간이 다 되기까지 계속 유효한 상태가 되버릴 수 있구요.
여기에 대한 대안으로, 액세스 토큰과 리프레쉬 토큰을 나누어서 사용하는 방법이 있는데요.
아래에서 보도록 하겠습니다.
4. 액세스 토큰과 리프레쉬 토큰
매번 사용자가 로그인 인증을 하게 할 수는 없고, 토큰의 유효기간을 길게 주면,
사용자의 컴퓨터가 탈취당할 경우, 유효기간까지 아이디/패스워드가 빼앗긴거나 다름이 없는 상태가 되는데요.
이에 대한 대응을 하기 위해서 액세스 토큰과 리프레쉬 토큰을 사용할 수 있습니다.
방법은 다음과 같은데요.
유효기간이 짧은(예를 들면 1시간 정도) 액세스 토큰과 유효기간이 긴 리프레쉬 토큰을 발행합니다.
액세스 토큰은 아이디/패스워드와 같으므로 많은 일들을 하고 탈취당할 경우 아주 위험해 집니다.
따라서 유효기간을 짧게 해주고, 유효기간이 다 되면,
유저에게 아이디/패스워드를 물어보는 것이 아니고,
유효기간이 긴 리프레쉬 토큰을 이용해서 서버에서 액세스 토큰을 다시 재 발행해서 사용하도록 합니다.
그럼 유저는 굳이 인증을 하지 않으면서도, 서버는 유효성을 계속 검증할 수 있습니다.
액세스 토큰의 유효기간이 지나고, 리프레쉬 토큰으로 액세스 토큰을 재 발행받으려고 할 때,
해당 클라이언트가 탈취당한 사실을 서버에서 알고 있을 경우,
해당 id로 액세스 토큰을 발급받지 목하도록 막을 수 있겠지요.
이 방법의 단점은, 리프레쉬 토큰을 이용해 액세스 토큰을 발급 받을 때,
매번 서버에 검증을 위해 서버에 접속하므로 부하가 생길 수 있다는 점과,
액세스 토큰의 유효기간동안에는 역시 무방비 상태가 될 수 있다는 점 입니다.
'NodeJS, NPM, Koa' 카테고리의 다른 글
NodeJS 에서 CSV 읽어들이기 # JS (0) | 2022.05.05 |
---|---|
Pug (구 Jade) 설치 및 기본 문법들 정리 # NodeJS (0) | 2021.11.25 |
Cheerio 와 Bent 이용한 HTML 파싱과 Scraping (0) | 2021.10.15 |
Dotenv 로 관리하는 환경변수 # NodeJS (0) | 2021.05.01 |
Koa JS FrameWork을 이용한 RestAPI 만들기 # NodeJS (0) | 2021.05.01 |
WebStorm NodeJS Coding Assistance 활성화 방법 (0) | 2021.04.29 |
NodeJS Get 과 Post 의 Parameter 와 QueryString 전달 방법 (0) | 2021.04.28 |
Babel 을 Webstorm 과 터미널 에 적용하는 방법 # Compiler ES6 (0) | 2021.04.28 |
A Record와 CNAME Record의 차이를 알아보자 (0) | 2020.04.02 |
NPM 의 package.json 을 이용한 효율적 설치 방법 #NodeJS (0) | 2020.03.21 |
댓글