HTTP 와 인증 그리고 passport, OAuth 2.0

broccoli·2021년 4월 17일
0

Authentication

목록 보기
1/3

인증

  • HTTP는 connectionless, stateless 방식의 프로토콜
    : 즉 정보를 주고 받는 양방의 end point는 요청 및 응답 중에만 서로를 알고 있고 이후의 요청과 이전의 요청은 동일한 endpoint끼리간의 송수인이어도 전혀 새로운 요청이다. 서로를 모른다.

서로를 모르는 것을 알게 만들게 하기 위한 방법이 인증이다.

인증을 위해서는 어떤 사용자가 요청을 보내는지의 대한 정보를 서버가 알게 해야한다.

사용자의 정보를 서버에게 전달하는 곳은 보통 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 라는 헤더에 응답과 함께 보낼 수 있다.

쿠키의 등록시 옵션 (express 기준)

  • expires, max-age같은 옵션을 사용하면 permanent 쿠키가 생성된다. 이말은 쿠키가 브라우저가 종료되도 특정시점까지는 살아있다는 의미. 디폴트는 session인데 session 쿠키는 브라우저가 닫히면 사라진다.
  • secure는 https를 사용시에만 브라우저가 웹서버에게 쿠키를 전송한다는 의미이다. 운영시 필수!!! 왜냐면 쿠키는 소중하니깐!!!
  • httpOnly는 브라우저가 웹서버와 통신할때에만 쿠키를 전송한다는 의미이다. 자바스크립트를 통해서 쿠키를 제어할 수 있다. 이것을 방지하기 위한 옵션 운영시 필수!!! 왜냐면 쿠키는 소중하니깐!!!
  • path는 특정경로 포함 및 하위경로에서만 브라우저가 웹서버에게 쿠키를 전송한다는 의미이다.
  • domain 을 지정하면 해당 domain에서만 브라우저가 웹서버에게 쿠키를 전송한다. 이때는 서브도메인까지 포함한다.
    ℹ️ 다른 도메인의 쿠키값은 저장할 수 없다. 단지 동일한 사이트의 서브도메인쿠키를 이용할 수 있을 뿐이다.(참고링크)

쿠키로 세션 ID를 저장시

세션 ID에는 사용자에 대한 아무런 정보가 담겨있지 않지만 이 세션ID를 통해서 서버는 이 사용자가 누구인지 판단할 수 있다.
ℹ️ 따라서 세션ID를 훔친다면 다른 사람을 흉내내서 로그인을 할 수 있다.

세션

세션서버측에서 저장하고 있는 데이터이다. 쿠키기반으로 생성하며 쿠키기반의 생성세션은 로그인상태를 유지하기 위해 많이 사용한다. 로그인 후 유저관한등을 저장하며 api 호출시 세션에 저장된 유저 권한으로 인가를 한다.

express 에서는 보통 express-session이라는 라이브러리를 통해서 세션을 생성할 수 있다. 이 미들웨어를 사용하면 req.session이라는 객체가 생성되고
디폴트로 서버의 메모리에 저장된다.

메모리는 휘발성이라서 서버가 종료되면 세션정보가 다 사라진다.

따라서 redis, mysql, file 등의 형태로 저장한다.

세션데이터를 어떤 데이터로 저장할지 정해야한다.
보통 이메일이나 비밀번호는 DB에 저장하지 세션으로 저장하지 않는다.
보통 이사람이 로그인 했는지여부, 페이지 접근시 사용자의 닉네임이나 권한등을 저장하면 DB에 다시 접속할 필요가 없어서 효율적이다.

동작원리

💁💁💁💁

  1. 세션 미들웨어가 사용되면 세션이 생성된다.
  2. 사용자가 세션 ID를 가지고 있는 상태에서 서버에 접속하면 서버는 사용자의 request.headers에 있는 쿠키의 세션 ID (connect.sid)를 통해 세션 ID를 전달 받는다.
  3. 세션미들웨어는 저 ID값을 가지고 세션스토어에서 ID에 대응되는 세션파일을 읽고 request.session 에 해당 세션객체를 추가한다.

세션옵션

  • secret: session ID cookie를 만들때 필요한 필수 옵션값. 반드시 dotenv 사용해야함.
  • resave:
    • false 세션데이터가 변경되지 않으면 저장소에 값을 저장하지 않는다.
    • true이면 세션데이터가 변경되든 안되든 저장소에 값을 새로 저장한다.
  • saveUninitialized:
    • false: empty session이 쌓이는걸 방지해 서버 스토리지를 아낄 수 있다.
    • true: uninitialized상태의 session을 강제로 저장한다. 즉 아무내용 없는 세션이 계속 저장될 수 있다. 클라이언트의 서버 방문횟수에 따라 등급을 달리하고싶을 때 사용할 수 있음. 왜냐면 세션이 계속 저장되니깐

참고링크 :

passport

node js에서 인증을 위해 사용하는 라이브러리

passport 사용법과 개념의 자세한 설명은 passport번역링크 참조

구현시 개인적으로는 위와 같은 구조로 보통 만든다.

  • index.js 에는 passport의 serialize, deserialize 로직을 넣어준다. 그리고 전략으로 사용할 인증도구들은 import해서 호출해준다.

  • local.js 는 이메일 비밀번호등의 형태 인증전략구현

  • routes/auth.js 는 로그인버튼 클릭시의 백엔드 라우트. 이 안에서 로컬전략을 호출해주고 local.js에서 구현한 콜백들이 넘어온다. 그럼 콜백에 맞는 대응 res를 구현해주면 된다.

패스포트는 로그인시에 로그인인증을 대행해주는 역할을 한다.

Federated Identity

기반엔 OAuth라는 기술이 깔려있음.

  • 사용자: Resource Owner
  • 내서버: Client
  • 구글 페이스북 같은 서버: Rescource Server, Authorization Server 두가지로 역할에 따라 한번 더 구분 가능하다.

사용자입장에서는 사용자의 정보를 내서버에 보관하지 않아도 편리하게 사용할 수 있다.

내 서버 입장에서는 사용자의 정보가 없으니까 정보를 잃는것에 대한 부담을 덜었다.

OAuth 2.0

OAuthaccess Token을 통해 구글이나 페이스북 등의 서버에 사용자가 가지고 있는 특정 권한을 수행할 수 있는 대행자역할을 가능하게 해주는 기능이다.

  • 사용자: Resource Owner
  • 우리가 만든 서비스: Client
  • 원래 사용자의 자원을 가지고 있는 서버: Resource Server
  • 인증과 관련된 일을 전담하는 서버: Authorization Server

Federated Identity는 OAuth기반의 기술이다.

사용방법

1. 등록

ClientAuthorization Server에 권한을 대행받기 위해서는 Authorization Server에 내 서비스 즉 Client가 등록이 되어있어야 한다. 이때 필요한게 바로

  • ClientID: 공개되도 되는 값 -> 내 서비스라는 것의 식별자
  • Client Secret: 꼭 숨겨야하는 값 -> 내 서비스의 비밀번호같은 값
  • Authorized redirect URIs: https://client/callback -> 리소스서버가 권한을 부여할 때 코드를 내 서비스에 전달해주는데 코드를 전달받을 주소. 따라서 다른 곳에서 요청이 오더라도 무시하고 이 주소로만 코드를 준다.

이러한 ClientID, Client Secret는 해당 리소스서버의 앱을 만들면 생성되고 설정같은 곳에서 확인 가능하다. Authorized redirect URIs는 그 해당 앱에 설정같은 곳에 내서비스의 콜백값(물론 내서비스에 라우트 구현이 필요함)을 등록해주는 공간이 있는데 거기에 등록하면 된다.

2. Resource Owner의 승인

ClientID, ClientSecret, redirectURL을 가지고 Authorization Server에 권한허용을 요청하면(github에 경우는 Clientsecret없이 요청해도 현재 가능함)

깃헙 OAuth 관련 링크

Authorization ServerResource Owner에게 이 권한을 이 client에게 허용해줘도 되는지 승인 페이지를 띄운다. 이 페이지에 승인허용을 하게 되면 Authorization Serverclient에게 허용된 권한을 등록하게 된다.

3. Authorization Server의 승인

Resource Owner에 의해 client가 특정권한에 대한 승인이 Authorization Server에 되었다면 Authorization ServerAuthorization Codecallback?code=123123에 형태로 clinet에게 줍니다.

clientAuthorization codeclientID, clientSecret, Authorized redirect URIs 을 다시 Authorization Server에 전송하면서 나 허용된 client 맞다고 호소합니다. 그럼 Authorization ServerAuthorization CodeClientSecret을 확인하며 최종적으로 해당 client에게 승인 해주고 access tokenrefresh token을 줍니다.

4. Access Token 와 Refresh Token(안 줄수도 있음)

client는 이 Access token을 통해 Resource Owner로 부터 승인 받은 권한들을 페이스북이나 깃헙같은 곳에서 제공해준 API API를 통해 Resource Server 요청해서 받고 사용할 수 있습니다.

5. Refresh token

access token하나만으로 계속 clientResource Server의 통신을 허락해주는건 좀 위험한 방식이다. 따라서 Access token의 수명은 정해져 있다. 만약 다시 Access token을 받기위해서 2~3 과정을 반복하는건 비용이 들기 때문에 refresh token으로 Authorization Server에 다시 Access token을 요청하면 새로운 Access tokenrefresh token을 계속 새로 얻을 수 있다.

OAuth 2.0 공식문서

공식문서링크에 있던 자료 중 발췌한 자료인데, 위에 이미지는 OAuth 2.0 부분에 동작 방식이다.

A, B 부분이 위에서 설명한 1~4번까지의 과정이다. 이후 access token을 통해 Resource Server와 통신을 하면 되는 것이다. 만약 access token이 만료되면 access token 과 함께 받은 refresh token을 통해 다시 access tokenrefresh token 을 받고 통신을 반복하면 된다.

참고링크

profile
🌃브로콜리한 개발자🌟

0개의 댓글