로그인 성공시 JWT를 이용하여 Token 전송
JWT
JWT 설명 내용
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
JSON Web Token(JWT)는 JSON 객체로 당사자간에 안전하게 정보를 전송할수 있는 작고 독립적인 방법을 정의하는 공개 표준(RFC 7519)입니다. 이 정보는 디지털 서명되기 때문에 검증되고 신뢰할 수 있습니다. JWT는 RSA/ECDSA를 이용한 공개키/개인키 또는 암호화(HMAC 알고리즘)를 이용하여 서명할 수 있습니다.
JWT 사용 예시
로그인 후속 처리
가장 많이 사용되는 방법으로 사용자가 로그인 하면 후속 요청에 JWT가 포함되어 사용자가 해당 토큰으로 허용되는 경로, 서비스 및 리소스 액세스 할 수 있게 한다. 또한 JWT를 이용한 SSO(Single Sign On)은 오버헤드가 적고 다른 도메인에서 쉽게 사용할 수 있다.
정보 교환
JSON 웹 토큰은 당사자간에 정보를 안전하게 전송하는 좋은 방법이다. JWT는 서명을 할 수 있기 때문에 발신자에 대한 확인과 내용의 변조 여부를 확인 할 수 있다.
JSON 구조
JSON은 dots(.)을 기준으로 3가지로 나뉜다.
- Header
- Payload
- Signature
다음과 같은 형태로 되어 있다.
aaaaaa.zzzzzz.yyyyyy
______.______.______
Header.Payload.Signature
Header는 타입과 알고리즘 두가지 정보를 가지고 있다.
Payload는 클레임(claim)이라고 명칭되는 name/value 한쌍으로 이루어 져 있다.
클레임은 세 분류로 나눈다.
- 등록된(registred) 클레임 : iss(발급자), exp(만료시간), sub(주제), aud(잠재고객) 등이다.
- 공개(public) 클레임 : 자유롭게 정의할수 있다. 충돌을 방지하기 위해 URI 형식을 권장한다.
- 비공개(private) 클레임: 보통 클라이언트와 서버간 협의하에 사용되는 클레임 이름이다.
JWT의 등록된 클레임 이름의 길이는 3자이다. 또한 서명된 토큰의 경우 변조되지 않도록 보호는 되지만 모든 사람이 읽을 수 있다. 암호화되지 않은 JWT의 페이로드 또는 헤더 요소에 비밀 정보를 넣으면 안된다.
Signature는 Header와 Payload의 인코딩 값을 합친후 주어진 비밀키로 해쉬를 생성 한다.
JWT 구현 하기
기존 프로젝트 코드에서 jsonwebtoken을 설치한다.
$> npm install --save jsonwebtoken
이후 router/index.js파일에서 해당 모듈을 이용해서 로그인 성공시 Token을 전달하고, isAdmin 토큰을 검증하고 ROLE_TEST1을 가지고 있을 경우만 통과 하도록 수정한다.
...모듈 추가...
const jwt = require('jsonwebtoken');
...로그인 성공시...
const token = jwt.sign(userInfo, secretKey, { expiresIn: '5m' });
res.json({ status: 'success', token });
...isAdmin...
const isAdmin = (req, res, next) => {
try {
const decoded = jwt.verify(req.header('X-token'), secretKey);
if (decoded.role.includes(roleAdmin)) {
next();
}
else {
res.json({ status: 403, message: 'Login failed' });
}
}
catch (error) {
res.json({ status: 500, message: `token Error: ${error.message}` });
}
};
다음시간에는 사용자 암호에 대한 해쉬알고리즘을 이용한 암호화 처리를 진행하자.