2. JWT와 로그인
인증(Authentication)은 사이트에 가입된(등록된) 사용자임을 증명하는 것이다.
인가(Authorization)은 인증이 확인된 유저가 리소스에 엑세스 할 수 있는 권한을 부여하는 것이다.
1). 로그인을 하면 인증(Authentication)을 통해 TOKEN을 발행 받는다.
2). 인증을 받은 사용자는 리소스에 접근할 때 request Header에 Authorization에 token정보를 같이 보낸다.
3). 토큰을 통해 권한이 있는지 없는지 확인한다.
로그인 시 서버가 정보를 쿠키 안에 넣어서 전달한다.
유저가 로그인이 필요한 시점에(리소스에 접근 시) 쿠키를 보여준다.
서버가 저장하는 것이 아니기 때문에 저장 공간이 좋으며 RESTful하다
= 서버가 상태를 저장하지 않음 ; Stateless
중요한 정보는 세션에 저장하고 그 정보의 위치를 쿠키에 적는다.
로그인 시 서버가 중요한 정보를 저장해 번호를 전달한다. 클라이언트와 서버는 번호를 이용해서만 대화한다.
보안이 비교적 강해지지만 서버의 저장공간을 사용한다 ; Not Stateless
보안이 강하고 Staeless하며 서버 부담을 줄여준다.
구조
Header.Payload.VerifySignature
Header: 토큰을 암호화하는 알고리즘 + 토큰의 형태(타입)
Payload: 사용자 정보, 중요한 정보는 입력하지 않음
Verify Signature: 페이로드 값이 바뀌면 서명 값도 바뀌기 때문에 인증 가능(JWT가 원본임을 확인)
절차

app.post('/prac/users/login', (req,res)=>{
const {email, password} = req.body;
const sql = `SELECT * FROM users WHERE users.email = ?`
const val = [email]
conn.query(sql,val,(err,results)=>{
if(err){
console.log('로그인 conn.query 오류 : ', err);
res.status(400).json(err);
} else {
let user = results[0];
let thisPwd = user.password;
let salt = user.salt;
let hashReceivedPwd = crypto.pbkdf2Sync(password,salt,10000,10,'sha512').toString('base64');
...**token**
})
**token**
if(user && thisPwd == hashReceivedPwd){//비밀번호가 일치하면 토큰 발행
const accessToken = jwt.sign(
{email: email, username: user.username},
'accessPrivateKey',
{expiresIn : "1 min",
issuer : "estie"
}
)
res.cookie('accessToken',accessToken,{httpOnly:true});
res.json({
message : `${user.username}님 로그인되셨습니다.`,
token : accessToken
});
})
jwt.sign 을 이용해 토큰 발행 후res.cookie로 쿠키에 담아 토큰을 보내준다.하지만 토큰의 유효기간이 길면 중간에 정보를 탈취당하는 문제가 생길 수 있다.
그럼 토큰의 유효기간을 짧게 할 수 있지만 1분마다 로그인하면 사용자 입장에서 매우 불편할 것이다. 따라서 등장한 것이 Refresh Token!
Access Token이 만료되었을 때 Refresh Token으로 확인 후 재발행해주는 방법이다.
기존 코드에서 많이 변경되기 때문에 3장에서 Refresh Token을 구현하고 특정 라우터에서 인가를 받는 코드까지 작성해보겠다.