티스토리 뷰
🐱👤 애플리케이션에서 유저 특정하고, 각기 다른 권한을 주기 위해 필요한 작업 순서 🦥
1. 회원가입
2. 로그인 (authentication = 인증)
3. 로그인 이후의 요청과 응답 (authorization = 인가)
이미 로그인한, 권한있는 유저의 요청인지 체크
(1) 쿠키에 유저 정보 담는 방식 (원시적)
(2) 세션 방식
근데 세션 방식의 단점은 스케일이 커졌을 때 발생한다. (효율성 문제...)
서버를 여러대 두게 되었을 때
(3) 토큰 방식
토큰 구현 방식에는 몇가지 선택지가 있는 것 같다.
- 토큰 타입 : JSON (= JWT ) / XML ( = SAML)
- 토큰을 어디에 담아 보낼지 : 쿠키 / Authorization Header
(참고)
If the token is sent in the Authorization header, Cross-Origin Resource Sharing (CORS) won't be an issue as it doesn't use cookies. - 출처 : jwt.io 소개 페이지
Authorization header에 담으면 쿠키에 담을 때 와 다르게 cors 이슈가 발생하지 않는 차이점이 있나보다.
찾다 보니 이런 글도 있었다. (Access Token 저장 위치에 대한 고찰)
(참고 끝)
이 중에서 쿠키에 담아 보내는 JWT (json web token) 방식으로 예를 들어보려 한다.
내가 이해한 바로는 서버는 DB에 토큰을 저장하고 있을 필요가 없는 것 같다.
(그리고 그게 세션 대신 토큰 방식을 이용하는 이유지 않나....?)
시크릿키 빼고는 쿠키에서 꺼낸 토큰에 SIGN과 비교할 해시함수 통과한 값을 만들 준비물이 다 들어있다.
유저한테 토큰 보내줄 때 SIGN 만든 방식으로 똑같이 만들어 보고 결과물이 같은지 비교한다.
- 해시 알고리즘 : HEADER에 어떤 알고리즘 썼는지 적혀있음
- 헤더, 페이로드 : 토큰 일부분
여기서 authorization(인가)의 주된 목표는 유저로부터 정보를 얻는게 아니라, 이미 로그인한 권한을 가진 유저라는 것을 확인하는 것이니까 굳이 payload에 패스워드 같은 민감정보를 담을 필요가 없다.
혹시 유저 정보가 더 필요하다면 페이로드에서는 id같은 유저 식별 가능한 값 하나 정도를 얻고 이걸로 DB에서 가져오면 된다.
(근데...)
오늘 여기서 JWT 토큰을 사용하는 걸 처음 보고 JWT 토큰이 뭔지 찾아보게 된건데
여기서는 서버에서 생성한 토큰을 DB에 저장하시길래 뭐 내가 이해한게 맞는지 좀 헷갈린다.
그리고 약간 뉘앙스가 jsonwebtoken모듈의 verify 함수가 시크릿키로 토큰을 복호화하는 거라는 느낌을 받았는데
실은 여기서의 decoded는 그냥 base64디코딩 된 payload 아닌가....? (해시는 복호화가 안되고 그저 해시함수 통과한 두 값이 일치하는지 보는 것으로 함수 통과전 두 값이 같음을 증명한다고 알고 있다)
The callback is called with the decoded payload if the signature is valid and optional expiration, audience, or issuer are valid. If not, it will be called with the error. - npm jsonwebtoken 페이지
+ 토큰을 DB에 저장하신건 로그아웃 때문인 것 같다.
(토큰 방식의 로그아웃 방법에 대한 stack-overflow 답변들)
한번 발행된 토큰은 서버측에서 임의로 만료되게 할 수 없어서 세션방식과는 다른 로그아웃 방법을 취해야 한다고 함.
요약해보자면 크게
1) 클라이언트측에서 토큰 지우는 방식 (여기에만 의존하기엔 허술하다)
2) 블랙리스트 db를 두어서 로그아웃된, 아직 기한 만료전인 토큰 정보를 저장해두고 요청마다 확인해서 거르는 방법
3) 토큰 만료기한을 짧게 잡은 뒤 로그인 유지하는 동안에는 클라이언트에게 계속 새 토큰 발행해주기+ 1번 방법 혼합.
정도로 말하는 것 같다.
그래서 로그아웃이 까다로워서 그냥 간단하게 구현하려고 로그인때 DB에 토큰 저장하고 로그아웃때 삭제하고 그런식으로 구현하신게 아닐까 싶다.
( 😧 )
+ passport.js
위의 세가지 중 세션 방식으로 유저를 인증, 인가한다.
express-session모듈과 passport 모듈이 이 밑의 과정 중 상당 부분을 대신 처리해주므로
(특히 세션에 저장하고 불러오기, 쿠키 심고 해석하기 등)
이 모듈 사용하는 개발자는 1) 미들웨어 사용하겠다는 코드, 2) 원하는 방식으로 strategy, redirect할 장소 등을 config,
3) 그리고 해당하는 인증 요청의 라우팅 처리에서 passport.authenticate() 함수 호출하기만 하면된다
+ OAuth2.0
제3자가 대신 유저 인증해주고, 이때 서버가 발급받은 access token으로 제3자(구글, 페이스북)에게 인가를 받아 유저에 대한 리소스도 받을 수 있다.
It works by delegating user authentication to the service that hosts the user account,
and authorizing third-party applications to access the user account.
passport.js의 oauth2.0은 세션 방식 (유저 - 서버) , 토큰 방식 ( 서버 - 구글 access token ) 혼합인 것 같다...
참고한 설명
인증 인가 차이, 그리고 인증,인가의 여러가지 방식 비교한 영상
'시리즈 > Web' 카테고리의 다른 글
passport.js의 OAuth2.0 (0) | 2021.04.30 |
---|---|
쿠키, 세션, passport.js (0) | 2021.04.30 |
proxy와 CORS 2편 (0) | 2021.04.22 |
proxy와 CORS 1편 (1) | 2021.04.22 |
Real Time Web 선택지 비교 (0) | 2021.02.16 |