JWT를 통해 로그인을 구현해왔다. 자동 로그인을 구현하기 위해 JWT의 만료기간을 최대한 늘리려고 했다.
그러나, JWT의 만료기간을 길게 잡으면 보안에 취약하여 만료기간을 길게 잡으면 안된다.
payload에는 _id값만 넣었다. (이것으로 다 조회 가능하니)
db에 저장하니 stateless한 JWT의 장점이 사라진다는 말이 있지만, 만료기간이 긴 Refresh Token을 그대로 노출시킬 수 없었다.
나는 token collection을 따로 생성하여 userId와 함께 저장했다.
function testVerify(toekn) {
try {
return jwt.verify(token, config.jwt.secretKey);
} catch(err) {
return err.message;
}
}
위 코드로 jwt의 기한이 지났을 겨웅와 키 값이 다른 경우 에러 메세지를 추출해봤다.
나는 네이티브 앱 API를 만드는 과정이라 Cookie를 사용할 수 없어 Header로 받았다.
Restful한건 {Authorization: Bearer ~} 와 같이 보내야 하지만 편의상 일단 이렇게 진행하였다.
export async function autoLogin(req, res) {
try {
var userId = tokenparsing(req.get('Accesstoken'));
var findrefreshToken = await authRepository.findRefreshToken(userId);
} catch {
return res.status(404).json({"status": "404"});
}
const accessToken = verifytoken(req.get('Accesstoken'));
const refreshToken = verifytoken(findrefreshToken);
const newAccessToken = createAccessJwt(userId);
const newRefreshToken = createRefeshJwt(userId);
if (accessToken === 'invalid') {
return res.status(401).json({"status": "401"});
}
// access token, refresh token 만료
if ((accessToken === null) && (refreshToken === null)) {
return res.status(401).json({"status": "401"});
}
await authRepository.updateRefreshToken(userId, newRefreshToken);
return res.status(200).json({"status": "200", "Accesstoken": newAccessToken});
}
function verifytoken(token) {
try {
return jwt.verify(token, config.jwt.secretKey);
} catch (err) {
if (err.message === 'invalid signature') {
return 'invalid';
}
return null;
}
}
추가적으로 보안을 위해 Cookie에 tokendb의 index번호만을 넣어서 보낼 수 있다고 한다.