민규의 개발블로그
passport + jwt 로 로그인 구현하기(AccessToken,RefreshToken) 본문
과거 나는 Next 환경에서 jwt 인증 방식으로 프로젝트 로그인 전략을 짠 적이 있다.
그러나 그때는 내 역할은 프론트엔드 였기 때문에 jwt 토큰(accessToken, refreshToken)이 어떤 식으로 이동하고 인증을 해주는지 흐름만 알았을 뿐 직접 구현하지는 않았다.
그래서 지금 리팩토링 하는 개인 프로젝트에서 직접 구현해 보았다.
npm i passport passport-local passport-jwt jsonwebtoken
- passport. passport 주로 로그인 기능 구현쪽에서 많이 사용되는 node JS 미들웨어
- passport-local. passport 전략 중 전통 아이디, 비밀번호로 인증
- passport-jwt. passport-local로 생성한 토큰을 식별
- jsonwebtoken. jwt 토큰 생성 라이브러리
로그인 기능 구현
back/passport/index.js
const passport = require('passport');
const { Strategy: LocalStrategy } = require('passport-local');
const bcrypt = require('bcrypt');
const { User } = require("../models") // sequelize의 user 모델
다음과 같이 사용할 모듈들을 불러온다. passport미들웨어를 등록하기 위한 passport모듈과 사용자 인증을 구현할 Strategy, 그리고 해쉬된 비밀번호를 비교하기 위한 bcrypt모듈을 불러왔다. 추가로 sequelize로 정의한 User모델을 불러와 User의 데이터를 조회할 수 있도록 했다.
usernameField, passwordField는 passport가 읽을 사용자의 아이디와 비밀번호를 확인하는 옵션이다. 즉 클라이언트가 서버로 사용자의 아이디와 비밀번호가 담긴 Form 데이터를 보내면 passport에서는 등록된 프로퍼티 이름으로 아이디와 비밀번호를 인식한다.
그리고 사용자의 인증정보를 확인하는 함수를 구현했다. 이 함수는 매개변수로 3개를 받는데 사용자의 아이디, 비밀번호, 그리고 인증의 결과를 호출할 done이라는 함수를 받는다. done은 인자를 3개까지 받는데 첫 번째 인자는 서버에서 발생한 에러를 넣고 두 번째 인자는 성공했을 때 반환할 값을 넣어준다. 그리고 마지막 세 번째 인자는 사용자가 임의로 인증 실패를 만들고 싶을 때 사용하며 인증 실패한 이유를 함께 넣어줄 수 있다.
다음 코드는 처음에 유저 아이디로 일치하는 유저 데이터를 검색한 후 검색된 유저 데이터가 없다면 임의로 인증을 실패하도록 설정했고 검색된 유저 데이터가 있다면 받아온 비밀번호와 DB에 저장된 유저의 해쉬된 비밀번호를 비교해 같을 경우에만 done함수의 두 번째 인자로 유저 데이터를 넣어줘서 인증을 성공했다.
로그인 시 토큰 발행
back/routes/user.js
로그인이 문제없이 성공하면 db에서 비밀번호 정보를 제외한 나머지를 가져온다. 그리고 accessToken과 refreshToken을 만들어 준다음 전자는 json으로 후자는 db에 저장하고 cookie에 넣어준다.
passport 세팅 후 LocalStrategy 호출이 안되는 에러가 있었는데
back/app.js
passport 설정 호출을 안해줘서 일어나는 에러였다
...
const passportConfig = require("./passport");
passportConfig();
참고링크
Passport js와 그럴듯한 refresh, access token 만들기
Express + passport (+jwt) 이용하여 로그인, 회원가입, 인증 구현하기