서로를 모르는 것을 알게 만들게 하기 위한 방법이 인증이다.
인증을 위해서는 어떤 사용자가 요청을 보내는지의 대한 정보를 서버가 알게 해야한다.
사용자의 정보를 서버에게 전달하는 곳은 보통 HTTP request.headers 에 담겨서 보낸다.
하지만 브라우저에서는 개발자 툴을 통해서도 쉽게 정보의 송수신을 확인할 수 있다. 따라서 사용자 정보는 쉽게알아볼 수 없는 방식으로 서버에 전달되어야 한다.
쿠키
는 서버가
사용자 브라우저에 보내는
4kbyte 작은 단위의 정보
이다.
브라우저는 그것을 저장할 수도 있고 다시 후에 동일한 서버에 돌려보낼수도 있다.
따라서 서로 다른 두개의 요청이 동일한 서버에 들어와도 서버는 쿠키를 통해서 누가 누군지 구분할 수 있게 된다.
ℹ️ HTTP로 하여금 원래 stateless한데 stateful한 기능을 해주게 도와주는 놈이라는 뜻.
보통 세가지의 목적으로 사용된다.
Session management
: Logins, shopping carts, game scores, or anything else the server should remember
Personalization
: User preferences, themes, and other settings
Tracking
:Recording and analyzing user behavior
과거에는 물론 현재도 사용하지만 localStorage랑 sessionStorage가 생기기 이전에는 브라우저의 저장소 같은 역활을 했지만 지금은 아니다. 쿠키는 매요청시마다 함께 전송이 되기때문에 성능저하의 요인도 있고 최근에 위에 언급한 다른 StorageAPI나 IndexedDB가 있기 때문이다.
쿠키는 서버가 요청을 받은 다음 Set-Cookie
라는 헤더에 응답과 함께 보낼 수 있다.
세션 ID에는 사용자에 대한 아무런 정보가 담겨있지 않지만 이 세션ID를 통해서 서버는 이 사용자가 누구인지 판단할 수 있다.
ℹ️ 따라서 세션ID를 훔친다면 다른 사람을 흉내내서 로그인을 할 수 있다.
세션
은 서버측
에서 저장하고 있는 데이터
이다. 쿠키기반으로 생성하며 쿠키기반의 생성세션은 로그인상태를 유지하기 위해 많이 사용한다. 로그인 후 유저관한등을 저장하며 api 호출시 세션에 저장된 유저 권한으로 인가를 한다.
express 에서는 보통 express-session이라는 라이브러리를 통해서 세션을 생성할 수 있다. 이 미들웨어를 사용하면 req.session이라는 객체가 생성되고
디폴트로 서버의 메모리에 저장된다.
메모리는 휘발성이라서 서버가 종료되면 세션정보가 다 사라진다.
따라서 redis, mysql, file 등의 형태로 저장한다.
세션데이터를 어떤 데이터로 저장할지 정해야한다.
보통 이메일이나 비밀번호는 DB에 저장하지 세션으로 저장하지 않는다.
보통 이사람이 로그인 했는지여부
, 페이지 접근시 사용자의 닉네임
이나 권한
등을 저장하면 DB에 다시 접속할 필요가 없어서 효율적이다.
💁💁💁💁
node js에서 인증을 위해 사용하는 라이브러리
passport 사용법과 개념의 자세한 설명은 passport번역링크 참조
구현시 개인적으로는 위와 같은 구조로 보통 만든다.
index.js
에는 passport의 serialize, deserialize 로직을 넣어준다. 그리고 전략으로 사용할 인증도구들은 import해서 호출해준다.
local.js
는 이메일 비밀번호등의 형태 인증전략구현
routes/auth.js
는 로그인버튼 클릭시의 백엔드 라우트. 이 안에서 로컬전략을 호출해주고 local.js
에서 구현한 콜백들이 넘어온다. 그럼 콜백에 맞는 대응 res를 구현해주면 된다.
패스포트는 로그인시에 로그인인증을 대행해주는 역할을 한다.
기반엔 OAuth라는 기술이 깔려있음.
사용자:
Resource Owner내서버:
Client구글 페이스북 같은 서버:
Rescource Server, Authorization Server 두가지로 역할에 따라 한번 더 구분 가능하다.사용자입장에서는 사용자의 정보를 내서버에 보관하지 않아도 편리하게 사용할 수 있다.
내 서버 입장에서는 사용자의 정보가 없으니까 정보를 잃는것에 대한 부담을 덜었다.
OAuth
는 access Token
을 통해 구글이나 페이스북 등
의 서버에 사용자가 가지고 있는 특정 권한
을 수행할 수 있는 대행자역할
을 가능하게 해주는 기능이다.
Federated Identity
는 OAuth기반의 기술이다.
Client
가 Authorization Server
에 권한을 대행받기 위해서는 Authorization Server
에 내 서비스 즉 Client
가 등록이 되어있어야 한다. 이때 필요한게 바로
ClientID
: 공개되도 되는 값 -> 내 서비스라는 것의 식별자Client Secret
: 꼭 숨겨야하는 값 -> 내 서비스의 비밀번호같은 값Authorized redirect URIs
: https://client/callback -> 리소스서버가 권한을 부여할 때 코드를 내 서비스에 전달해주는데 코드를 전달받을 주소. 따라서 다른 곳에서 요청이 오더라도 무시하고 이 주소로만 코드를 준다.이러한 ClientID
, Client Secret
는 해당 리소스서버의 앱을 만들면 생성되고 설정같은 곳에서 확인 가능하다. Authorized redirect URIs
는 그 해당 앱에 설정같은 곳에 내서비스의 콜백값(물론 내서비스에 라우트 구현이 필요함)을 등록해주는 공간이 있는데 거기에 등록하면 된다.
ClientID
, ClientSecret
, redirectURL
을 가지고 Authorization Server
에 권한허용을 요청하면(github에 경우는 Clientsecret없이 요청해도 현재 가능함)
Authorization Server
는 Resource Owner
에게 이 권한을 이 client
에게 허용해줘도 되는지 승인 페이지를 띄운다. 이 페이지에 승인허용을 하게 되면 Authorization Server
는 client
에게 허용된 권한을 등록하게 된다.
Resource Owner
에 의해 client
가 특정권한에 대한 승인이 Authorization Server
에 되었다면 Authorization Server
는 Authorization Code
를 callback?code=123123
에 형태로 clinet
에게 줍니다.
client
는 Authorization code
와 clientID
, clientSecret
, Authorized redirect URIs
을 다시 Authorization Server
에 전송하면서 나 허용된 client
맞다고 호소합니다. 그럼 Authorization Server
는 Authorization Code
와 ClientSecret
을 확인하며 최종적으로 해당 client
에게 승인 해주고 access token
과 refresh token
을 줍니다.
client
는 이 Access token
을 통해 Resource Owner
로 부터 승인 받은 권한들을 페이스북이나 깃헙같은 곳에서 제공해준 API
API
를 통해 Resource Server
요청해서 받고 사용할 수 있습니다.
access token하나만으로 계속 client
와 Resource Server
의 통신을 허락해주는건 좀 위험한 방식이다. 따라서 Access token
의 수명은 정해져 있다. 만약 다시 Access token
을 받기위해서 2~3 과정을 반복하는건 비용이 들기 때문에 refresh token
으로 Authorization Server
에 다시 Access token
을 요청하면 새로운 Access token
과 refresh token
을 계속 새로 얻을 수 있다.
공식문서링크에 있던 자료 중 발췌한 자료인데, 위에 이미지는 OAuth 2.0 부분에 동작 방식이다.
A, B 부분이 위에서 설명한 1~4번까지의 과정이다. 이후 access token
을 통해 Resource Server
와 통신을 하면 되는 것이다. 만약 access token
이 만료되면 access token
과 함께 받은 refresh token
을 통해 다시 access token
과 refresh token
을 받고 통신을 반복하면 된다.