TIL-54, Token을 이용한 Login 구현 Flow
Token 방식을 이용한 로그인을 구현하는 흐름을 알아보자.
Login
요청(req)의 body로 userId, password를 받아온다. (로그인 창에서 id, password를 입력했다)
findOne, where를 이용해 DB의 정보와 req.body의 정보를 대조해서 SELECT되지 않으면(로그인 창에서 입력한 id, password를 req의 body로 받아왔는데, 올바르지 않은 id, password를 입력했기에 DB의 정보와 일치하지 않는다)
data에 null, message에 전달한 에러 메시지를 응답(res)에 담아 전달한다.
SELECT가 되면 (올바른 id, password를 입력해 DB의 정보와 일치한다)
이 user 정보를 담은 accessToken를 생성해야 하고,
이 user 정보를 담은 refreshToken도 생성해야 한다.
accessToken을 생성하기 위해선
jwt.sign({유저 정보}, env의 ACCESS SECRET, 옵션)
을 입력해야한다. (이 때, accessToken은 refreshToken보다 유효기간이 짧아야함)
(env를 불러오기 위해선 require('dotenv').config()
를 전역에 입력,
jwt를 사용하기 위해선 const jwt = require('jsonwebtoken')
를 전역에 입력한다.)
이제 만들어진 accessToken과 refreshToken를 사용할건데,
cookie로 응답을 전달해주는데, refreshToken을 담아서 전달한다.
res.cookie('refreshToken', refreshToken, {sameSite: 'none', secure: true, httpOnly: true})
위와 같이 cookie에 전달한다.
(sameSite, secure, httpOnly 옵션을 사용하는 이유
→ sameSite를 None으로 설정시 모든 도메인에서 쿠키를 전송하고 사용할 수 있다.
Lax, Strict 설정도 존재.
secure는 웹브라우저와 웹서버가 HTTPS로 통신하는 경우에만 웹브라우저 → 웹서버로 쿠키를 전송
httpOnly를 사용하면 document.cookie처럼 cookie를 뽑아내는게 불가능.
서버로 요청을 보낼떄만 쿠키를 전송, XSS 공격을 차단. )
이제 본 응답으로 accessToken을 담아서 전달한다.
accessTokenRequest
요청(req)의 headers에 담긴 authorization의 유무
→ accessToken이 있는지 없는지 파악하는것.
(headers객체의 authorization키 값으로 accessToken이 Bearer <토큰> 형식으로 담긴다)토큰>
authorization(accessToken)의 유무를 파악한 뒤,
없을때와 있을때로 조건을 나누어 코드를 작성한다.
없을때
→ 요청의 응답으로 null이 담긴 data, 에러 메시지가 담긴 message를 키로 가진 객체를 전달.
있을때
→ authorization(accessToken)이 있다는것은, 일단은 어떤 엑세스 토큰이 있다는것.
그러면 이 엑세스 토큰이 유효한 토큰인지 확인을 거친 후 유저 정보를 넘겨야한다.
req.headers.authorization은 ‘Bearer <토큰>' 형식으로 돼있기 때문에 split(' ')을 해준 뒤 [1]로 1번째 인덱스를 가져오면 accessToken을 뽑아올 수 있다.토큰>
이 때, 이 accessToken은 akasdkdjsIAHFasdksdlAKDfmvSKd … 등의 이상한 형식이기 때문에,
해독이 필요하다.
jwt.verify(인자1, 인자2)
인자1로 accessToken을 넘기고, 인자2로 env의 access secret을 넘긴다.
(이 때, env를 사용하기 위해선 전역에서 require('dotenv').config()
를 작성,
jwt를 사용하기 위해선 전역에서 const jwt = require('jsonwebtoken')
을 작성 해야 한다)
이렇게 jwt.verify로 나온 값이 유저의 정보이고, 이 유저 정보를 갖고있는 DB와 비교하면 된다.
findOne, where를 이용해 DB의 데이터와 비교하고, 성공적으로 SELECT되면 (일치하면)
응답으로 유저정보를 보내주고,
SELECT가 되지 않으면(일치하는 정보가 없다, 잘못된 토큰이다)
data는 null, message로 전달할 에러 메시지를 보내준다.
refreshTokenRequest
위의 login 단계에서 cookie에 refreshToken을 담아서 전달했으므로,
요청(req)의 cookies에 refreshToken이 담겨있다.
이 refreshToken이 없다 → login 요청이 애초에 오지 않았다,
refreshToken이 있지만 올바르지 않은 토큰이다 → null이 담긴 data와 message로 전달할 메시지를 보낸다.
refreshToken도 있고, 올바른 토큰이다
→ refreshToken토큰을 jwt.verify로 해독해서 user 정보를 얻어낸 뒤, 이 user정보를
DB와 비교해 올바른 정보일때와 아닐 때를 다시 나누어준다.
올바른 정보일 때는 응답으로 data에 새로운 accessToken을 만들어서 전달, userInfo에 유저 정보를 전달, message로 ok를 보내준다.
만약 올바른 정보가 아닐 때는 data에 null, message에 원하는 에러 메시지를 담아서 응답한다. (end)