인증 관련 라이브러리를 잘 활용하기 위해 인증 기능을 구현하는 방법에 대한 기본적인 원리를 알아보자!
HTTP 쿠키
- 쿠키는 HTTP 프로토콜에 포함되어 있는 웹브라우저 기술.
- HTTP 쿠키(웹 쿠키, 브라우저 쿠키)는 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각
- 라우터는 그 데이터 조각들을 저장해 놓았다가, 동일한 서버에 재 요청 시 저장된 데이터를 함께 전송.
- 웹서버의 정보를 웹브라우저에 저장해서 개인화, 인증, 사용자 추적 등의 기능을 구현할 수 있도록 함.
- 쿠키는 두 요청이 동일한 브라우저에서 들어왔는지 아닌지를 판단할 때 주로 사용.
- 이를 이용하면 사용자의 로그인 상태를 유지할 수 있음.
- 상태가 없는 HTTP 프로토콜에서 상태 정보를 기억시켜주기 때문.
용도
- Session management : 서버에 저장해야 할 로그인, 장바구니, 게임 스코어 등의 정보 관리.
- Personalization : 사용자 선호, 테마 등의 세팅.
- Tracking : 사용자 행동을 기록하고 분석하는 용도.
쿠키로 로그인 기능을 만들어도 될까?
정답은 NO!
- 과거엔 클라이언트 측에 정보를 저장할 때 쿠키를 주로 사용했지만, 보안이 약하며 모든 요청마다 쿠키가 함께 전송되기 때문에 성능이 떨어질 수 있음.
- 정보를 클라이언트 측에 저장하려면 Modern APIs의 종류인 웹 스토리지 API (localStorage와 sessionStorage) 와 IndexedDB를 사용하기.
쿠키 만들기
Set-Cookie
Set-Cookie: <cookie-name>=<cookie-value>
Cookie 헤더
var http = require('http'); var cookie = require('cookie'); http.createServer(function(request, response){ var cookies = {}; if(request.headers.cookie !== undefined){ cookies = cookie.parse(request.headers.cookie); } response.writeHead(200, { 'Set-Cookie':['yummy_cookie=choco', 'tasty_cookie=strawberry'] }); response.end('Cookie!!'); }).listen(3000);


Cookie 헤더
- Session cookie : 웹브라우저를 끄면 사라지는 휘발성 쿠키. 상단 쿠키 예시만큼 쓰면 세션 쿠키.
- Permanent cookie :
- 브라우저 재시작 시 세션을 복원해 세션 쿠키가 무기한 존재할 수 있음.
- 웹브라우저를 꺼도 사라지지 않는 쿠키.
- 단
Expires
속성에 명시된 날짜에 삭제되거나,Max-Age
속성에 명시된 기간 이후에 삭제됨.
Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
var http = require('http'); var cookie = require('cookie'); http.createServer(function(request, response){ var cookies = {}; if(request.headers.cookie !== undefined){ cookies = cookie.parse(request.headers.cookie); } response.writeHead(200, { 'Set-Cookie':[ 'yummy_cookie=choco', 'tasty_cookie=strawberry', `Permanent=cookies; Max-Age=${60*60*24*30}` ] }); response.end('Cookie!!'); }).listen(3000);

Secure과 HttpOnly 쿠키
- Secure : 웹브라우저와 웹서버가 https로 통신하는 경우만 웹브라우저가 쿠키를 서버로 전송하는 옵션.
- HttpOnly : XSS(크로스 사이트 스크립팅) 공격을 방지하기 위해, JS의 document.cookie를 이용해서 쿠키에 접속하는 것을 막는 옵션.
- 쿠키를 훔쳐가는 행위를 막기 위한 방법.
- 하지만
Secure
일지라도 실질적인 보안은 제공하지 않기 때문에 민감한 정보는 절대 쿠키에 저장되면 안됨.
var http = require('http'); var cookie = require('cookie'); http.createServer(function(request, response){ var cookies = {}; if(request.headers.cookie !== undefined){ cookies = cookie.parse(request.headers.cookie); } response.writeHead(200, { 'Set-Cookie':[ 'yummy_cookie=choco', 'tasty_cookie=strawberry', `Permanent=cookies; Max-Age=${60*60*24*30}` 'Secure=Secure; Secure', 'HttpOnly=HttpOnly; HttpOnly' ] }); response.end('Cookie!!'); }).listen(3000);

path & domain
- 쿠키의 유효범위를 정의함 → 어떤 URL을 쿠키가 보내야 하는지를 정의.
- 만약
Path=/docs
이 설정되면, 다음의 경로들은 모두 매치됨. /docs
/docs/Web/
/docs/Web/HTTP
- 만약
Domain=mozilla.org
이 설정되면, 쿠키들은developer.mozilla.org
와 같은 서브도메인 상에 포함함.
var http = require('http'); var cookie = require('cookie'); http.createServer(function(request, response){ var cookies = {}; if(request.headers.cookie !== undefined){ cookies = cookie.parse(request.headers.cookie); } response.writeHead(200, { 'Set-Cookie':[ 'yummy_cookie=choco', 'tasty_cookie=strawberry', `Permanent=cookies; Max-Age=${60*60*24*30}` 'Secure=Secure; Secure', 'HttpOnly=HttpOnly; HttpOnly' 'Path=Path; Path=/cookie', 'Doamin=Domain; Domain=test.o2.org' ] }); response.end('Cookie!!'); }).listen(3000);
OAuth 2.0
- 사용자가 가입된 서비스의 API에 접근하기 위해서는 사용자로부터 권한을 위임 받아야 함.
- 이 때 사용자의 패스워드 없이도 권한을 위임 받을 수 있는 방법이 필요.
- 이를 위해서 고안된 기술이 OAuth임.
- 오늘날 카카오, 구글, 페북 등 많은 API들이 OAuth를 통해서 상호 연동을 지원하고 있음.
왜 OAuth를 이용해야 할까?
- SNS 로그인을 시도할 때 불안요소가 존재함.
- 유저(Resource Owner) : 내 SNS 계정 통채로 줄 수 없는걸...?
- 서비스(Client) : SNS 계정 가져갔다가 뺏기면 어떻게 책임지지..ㅜ
- SNS(Resource Server) : 우리 고객의 소중한 정보인데!?
- 이때 인증을 전담하는 Authorization Server와 자원의 제공자인 Resource Sever로 나뉨.
- 이에 따라 SNS가 유저의 요청에 따라
accessToken
을 발급해줌으로써 필요한 인증 기능만 제공할 수 있게 됨.
OAuth를 통해 accessToken을 발급하는 원리를 파악해보자!
등록
- Resource Server에 도메인 주소 등 정보를 입력하면 다음과 같은 정보를 받음.
Client ID
: 어플리케이션 식별자.Client Secret
: 이에 대한 비밀번호(유출 X).Authorized redirect URIs
: Resource Server가 해당된 주소만 정보를 전달함.
인증 과정

Owner와 Server가 진행
- Owner가 Client로 접속 시 Server를 사용해야 함. ex) 댓글을 남김
- Server가 로그인을 요구함. ex) 구글로 로그인하기.
- 클릭시 다음과 같은 링크를 전달.
https://resource.server/?client_id=1&scope=B,C&redirect_uri=https://client/callback
- 로그인을 하면 Server가 전달된 링크의 client와 uri 그리고 자신의 정보를 확인함.
- 같다면 Owner에게 scope에 대한 권한을 Client에게 부여할 것인지 메시지를 전달.

- Sever는 접속을 허락한 Owner의
user id
와scope
를 서버에 저장함.
Server와 Client가 진행

Server는 바로 accessToken을 발급하지 않고 인증과정을 한번 더 함. 3자 간의 거래니까!
- Server는 임시 비밀번호인 authorization code를 발급하고,
- 이를 Owner에게 전송함.
Location
은 해당 주소로 이동하란 뜻임.
Location:https://client/callback?code=3
- Owner는 Server가 제공한 주소로 이동함.
- Client는 authorization code를 갖게 됨.
- Client는 Server에 다음의 주소를 가지고 접근함. 이때 secret도 전송하는 것임.
//이 외에도 4가지 방법이 더 있음. https://resource.server/token?grant_type=authorization_code&code=3&redirect_uri=https://client/callback&client_id=1&client_secret=2
- Server는 Client가 전송한 값과 일치하는지 확인함.
- Server는 authorization code를 삭제하고 accessToken을 발급함.
- Client는 내부적인 곳에 accessToken을 저장함.
- Server는 accessToken, user Id를 비교하고 scope에 대해 접근을 허용함.
로그인뿐만 아니라 개인화된 정보를 지급하는 api에도 accessToken이 사용됨.
Refresh token


- Access token은 수명이 있음.
- Access token의 수명이 다했을 때 새로운 access token을 발급 받는 방법이 refresh token임.
참고자료 :