블로그 이전했습니다~
링크(https://steemit.com/@cicada0014)
로그인을 구현하는데 있어서 크게 세션과 쿠키 방식이 있다고 한다.
세션도 크게보면 쿠키의 일종이며, 서버의 메모리를 쓴다는 점이 특징이다.
쿠키보다 세션이 보안적인 측면에서 더 좋다고 생각해서 코딩을 하고 있었는데,
서버를 업데이트하고 배포를 할때마다 서버가 재시작되는 점이 있었다.
그렇게 되니 서버의 세션이 자동으로 종료되는 점이 있었다. (실제 사용자가 있다면 큰 불편함이 발생)
물론 세션을 쓰면서도 서버의 재부팅과 관계없이 유지하는 방법이 있겠지만
회사 대표님께서 말씀해주신 JWT (JSON WEB TOKEN) 방식을 사용해보았다.
JWT 에 대한 자세한 설명은 다른 블로그에서 자세히 해주고 있으니 참고하기 바란다
실제로 typescript + express 환경에서 어떻게 구현할 수 있는지 초점을 맞출 것이며,
로그인에 많이 쓰이고 있는 passport js도 곁들일 생각이다.
요즘에는 자체 로그인 구현을 잘 하지 않는 편이니까.
가장 대중적인 플랫폼인 페이스북과 연동해본다.(Facebook Login API 문서가 잘 되어있다)
프로젝트를 만들며 시작 하자
해당 리포지토리는 다음 깃헙주소로 클론하실수 있습니다 .
https://github.com/cicada0014/jwt-practice.git
일단 inversify를 이용해서 컨테이너를 사용한 express 앱을 구현한다
inversify+express 서버 구축의 자세한 내용은 이곳을 눌러 확인하자
위 프로젝트와 더불어 추가해줄 명령어는 다음과 같다
npm i -S passport passport-facebook jsonwebtoken @types/jsonwebtoken @types/passport @types/passport-facebook
이제 모듈들이 다 준비가 되었고, 링크에 있는 대로 진행했다면 다음과 같은 파일들이 생성되어 있어야 한다.
app.ts , controller.ts, model.ts
추가적으로 우리는 JWT 를 통해 인증 서비스를 만들것이므로 auth.ts를 추가한다.
하나하나 설명하자면,
constructor( @inject(Model.name) private model: Model) {
};
이 생성자는 컨테이너로부터 model을 의존 주입받는다. 실제 서비스에서는 데이터베이스에 회원의 정보가 있을 것이고 우리는 페이스북으로부터 받은 유저 정보와 비교해서 우리의 회원인지 비교할 수 있다.
다음은 model.ts 의 일부 메소드이다.
실제 데이터베이스와 연동하게되면 Promise 객체를 반환하게 된다. 페이스북으로부터 받은 정보와 회원 데이터베이스 정보가 동일하다면 회원 정보를 반환하게 할 것이다.
실제 토큰을 생성하는 메소드이다.
파라미터로 페이스북의 프로필정보를 받고, 그 정보를 토대로 토큰을 생성한다.
init 메소드는 어떤 플랫폼을 쓸것인지와 실제 우리가 가동시킬 어플리케이션을 파라미터로 받는다.
페이스북이 맞다면 패스포트의 페이스북 strategy를 사용한다.
옵션값으로는 자신의 페이스북 앱의 아이디와 시크릿정보 그리고 인증결과를 받을 callback url을 등록해야 한다.
이 passport를 쓸때 위에서 보았던 model 의 getAuthWithFaceBook() 를 사용한다.
인증으로부터 성공하면 profile 정보를 얻을 수 있다.
데이터베이스에 해당 정보가 있다면 row 가 1 인 배열값을 얻을 수 가 있을 것이다.
만약 배열의 길이가 0 이라면 해당 유저가 없는 것이며
2 이상이라면 유저가 중복된 것으로 판단할 수 있다.
init 메소드 중 일부인데 사용자가 auth/facebook 으로 요청을 보내면 패스포트전략에 따라 페이스북 앱으로 인증을 요청한다.
페이스북 앱쪽에서 인증절차를 거치고 결과를 auth/facebook/callback url로 되돌려주며
페이스북 인증절차가 성공적이라면 토큰을 사용자에게 보내준다
res에 header 값을 설정해준다. 'Set-Cookie' 헤더 정보를 만들어주면 된다 .
잘 요청이 되었다면 사용자는 토큰이 잘 생성되었다는 메세지를 받을 것이다.
app.get('/auth/facebook', passport.authenticate(authProvider, { session: false }));
app.get(
'/auth/facebook/callback',
passport.authenticate(authProvider, {
failureRedirect: '/'
}),
(req: any, res, next) => {
// passport
let token = req.user.token
// res.setHeader('Set-Cookie', `token=${token};Max-Age=21474836;Path=/;Secure;HttpOnly`)
res.setHeader('Set-Cookie', `token=${token};Max-Age=21474836;Path=/;HttpOnly`)
res.send("토큰이 잘 생성되었음")
}
);
로그인 구현을 위해서 모든 요청에 대해서 토큰 인증절차를 진행한다.
req 에 decoded 정보를 심어줄 것이다.
위 내용을 마무리했다면 app container에 등록한다.
app.ts
container에 등록을 했으면 컨테이너로부터 Auth 객체를 가져와서 init 시킨다.
여기서 check url을 통해서 실제로 decoded 된 토큰값이 나오는지 확인해볼 수 있다.
tsc ; node ./build/app.js
를 실행하면 서버가 가동된다 .
http://localhost:3000/check 로 접속해본다.
와 같이 뜬다.
아직 토큰이 생성되지 않았기 때문이다 .
http:// localhost:3000/auth/facebook 으로 접속을 하면 페이스북으로 인증절차를 요청하게 될 것이고
인증이 성공했다면 토큰을 생성했다는 메세지를 보내오는 것으로 짰다.
토큰이 생성되었다면 chrome 개발자 도구 > Applicaition 탭에서 쿠키를 확인해볼 수 있다.
다시 http://localhost:3000/check 으로 이동해보면 decoding된 토큰 정보를 확인할 수 있다.
해당 리포지토리는 다음 깃헙주소로 클론하실수 있습니다 .
https://github.com/cicada0014/jwt-practice.git
사랑해요... 덕분에 해결했습니다:)
답글삭제