develop

Http, Session, JWT, OAuth

crab. 2023. 1. 20. 16:14

들어가는 글

  • 항해99를 할 때 나 나름의 도전과제가 있었다.
  • 그것은 바로 refresh token!
  • 반에서 잘하시는 분이 이것을 도전해서 어찌저찌 성공하셨고 그 후에 나도 어찌저찌 성공했었지만 너무 얼렁뚱땅이었다..
  • 이번에 다시 도전하게될 기회가 생겨 구현해봤고 전보다는 나 나름대로 만족할만한(적어도 이해는 되는)코드가 나왔기에 포스팅을 해본다.
  • 그전에 배경지식으로 http와 인증의 세가지 방식을 먼저 들어간다.

인증의 구현의 세 가지 방식

  • 인증 구현은 크게 세션, JWT, OAuth가 있다.
  • 전에 항해할때는 백엔드리더가 우리 세션으로 한번 해보죠! 라고 해서 해봤는데 이해가 잘 안됐어서인지 백엔드에서 문제가 생겨서 인지 잘되지는 않았고 JWT 방식으로 돌아왔던 경험이 있었다.
  • 그 경험때문인지 이번에 세션도 잘 읽어봤고
  • 덕분에 세션에 대해 좀 이해할 수 있게 되었다.
  • (그 시절로 돌아간다면 세션을 좀 더 잘 구현했을텐데 하는 아쉬움이 있다.)
  • 아래에는 이 인증과 관련하여 아주 좋은 글이 있어서 한번 가져와봤다.
  • 출처 : https://patrick-f.tistory.com/13

HTTP통신

  • 현재 모바일이나 웹 서비스에서 가장 많이 사용되는 통신방식이라고 하면 HTTP 통신이라고 할 수 있다.
  • HTTP통신은 stateless라고 하여 응답 후 연결이 끊기게 되며 과거에 대한 정보를 전혀 담지 않는다.
  • 즉, 지금 보내는 HTTP 요청은 지난번에 내가 정보를 담아서 보냈던 HTTP 요청과는 전혀 관계가 없다는 뜻이다.
  • 서버에 요청을 보내는 작업은 HTTP 메세지를 보내는 것이라고 할 수 있다.
  • HTTP 메세지의 구조는 아래와 같다.

  • 일반적으로 HEADER와 BODY 두 가지로 구성되며, 공백 부분은 Header와 Body 부분을 구분짓는 역할을 하게 된다.
  • 여기서 Header에는 기본적으로 요청에 대한 정보들이 들어가며, Body는 서버로 보내야할 데이터가 들어간다.
  • 자, 이 정도의 지식은 가지고 이제 제대로 인증 구현 방식에 대해서 알아보자!
  • 우선 Session 즉, session based authentication에 대해서 알아보려고 한다.
  • 물론 그냥 ID, PW 정보를 그대로 보내도 된다!
  • 하지만 이는 보안에 매우 취약하다는 단점이 있다.
  • 그렇게 하여 나온 것이 바로 Session 방식이다.

session 방식

  • 어떤 사람이 로그인을 하면 서버는 쿠키라는 것을 발행하게 된다.
  • 이 쿠키는 브라우저에 저장 할 수 있는 session ID가 적힌 긴 문자열이라고 볼 수 있을 것이다.
  • 서버 쪽의 메모리에 이 사람이 로그인 했다는 것 고유한 ID 값을 부여하여 저장해놓고, session이 저장 되었다는 정보를 쿠키로 만들어서 브라우저에게 보내게 된다.
  • 그러면 브라우저는 이 쿠키를 저장하게 되면서 로그인 한 상태가 되는 것이다.
  • 즉, 유저는 서버에서 해당 세션 ID를 받아서 쿠키에 저장하고 인증이 필요한 요청마다 쿠키를 Header에 실어보내게 된다.
  • 이렇게 로그인을 했으면 "OO페이지를 보여주세요" 라는 의미에서 클릭을 하게 될 것이다.
  • 그러면 쿠키 데이터가 서버에게 자동으로 전송되며, 쿠키에 있는 session 정보와 server의 메모리에 있는 session data store에서 가지고 있는 정보와 쿠키로 보내진 정보가 같은 것임을 확인 한 후 원하는 페이지를 유저에게 전달하게 된다.
  • 이는 서버 메모리에 유저의 로그인 정보를 저장해놓는다는 특징이 있다고 할 수 있다.
  • 기본적으로 쿠키를 매개로 인증을 거치는데, 쿠키는 어떤 정보를 가지고 있다기 보다는 정보를 보여줄 수 있는 열쇠 같은 것이라고 한다.
  • 그러니 쿠키에 담긴 HTTP 요청이 도중에 노출되더라도 쿠키 자체는 유의미한 값을 가지지 않으니 계정정보를 담아서 그대로 인증을 거치는 것보다는 안전하다고 할 수 있다.
  • 그러나 만약 쿠키를 탈취당했다면?
  • 해커는 훔친 쿠키를 이용해서 HTTP 요청을 보내면서 서버의 세션 저장소에서는 사용자 본인으로 잘못 정보를 부려주게 될 수 있다.
  • 그렇기 때문에 HTTPS를 사용해 요청자체를 탈취해도 안의 정보를 읽기 힘들게 하거나, 세션에 유효기간을 더 넣어주는 방식으로 해결 할 수 있을 것이다.

JWT 방식

  • 내가 제일 많이 사용했고 지금도 사용하고 있는 방식이다.
  • JWT 즉, Token based authentication을 말한다.
  • JSON WEB TOKEN 줄여서 JWT라고 부르는 이것은 어떤 방식으로 인증이 구현 될까?
  • 우선 JWT의 TOKEN을 만들기 위해서는 Header, Payload, Verify Signature 이렇게 세 가지가 필요하다.
  • Header : 이 세 가지 정보를 암호화 할 방식, 타입 등이 들어간다.
  • Payload : 서버에서 보낼 데이터가 들어간다. 일반적으로 유저의 고유 ID 값, 유효기간 등이 들어간다.
  • Verify Signature : Base64 방식으로 인코딩한 Header, Payload 그리고 SECRET KEY를 더한 후 서명된다.
  • 그래서 최종적으로는 : Encoded Header + "." + Encoded Payload + "." + Verify Signature가 된다.
  • 자, 어떻게 인증에 사용 될까?
  • 우선 사용자가 로그인을 하면 서버에 전송이 될 것이다.
  • 서버는 올바른 ID & Password 인지 확인을 하고, 맞는 경우 클라이언트에게 JSON Web Token이라는 긴 문자열을 브라우저에 전송해준다.
  • 브라우저는 이를 쿠키나 로컬스토리지 등에 저장하게 된다.
  • 로그인 한 유저가 어떠한 페이지 접속을 원해서 클릭으로 요청을 하게 되면 자동으로 Web Token을 위에서 말했던 Header에 포함해서 함께 전송하게 된다.
  • 서버에서는 Web Token이 있는지 확인하고, 유통기한 등을 검사한 후 그에 맞는 필요한 정보를 전달해주게 된다.
  • 이는 페이지 요청을 할 때 마다 로그인 했다는 정보가 Web Token으로 Header에 담겨서 오기 때문에 굳이 서버가 로그인 상태를 저장하고 있을 필요가 없다는 특징이 있다.
  • 또한 RESTful api의 특징 중 하나인 stateless!
  • 이 JWT를 이용하면 조금 더 RESTful한 서버를 만들 수 있다고 할 수 있다.
  • 다만, 이미 발급 된 JWT는 돌이킬 수 없다.
  • Session의 경우 쿠키가 악의적으로 이용된다면 해당하는 세션을 지워버리면 되지만 JWT는 한번 발급되면 유효기간이 완료 될때 까지는 계속 사용이 가능하다.
  • 그러니 악의적인 사용자는 유효기간 안에서 신나게 정보를 털어낼 수 있는 것이다.
  • 이를 방지하기 위해서 기존 Access Token 유효기간을 짧게 설정하고 Refresh Token이라는 새로운 토큰을 발급한다.
  • 그러면 Access Token을 탈취당해도 상대적으로 피해를 줄일 수 있을 것이다.

OAuth

  • OAuth 즉, Open Authentication은 다른 사이트의 인증정보를 가져와서 사용하는 것을 말한다.
  • 이는 우리가 흔히 볼 수 있는 방식으로 주로 구글, 카카오, 네이버 등의 아이디 연결을 사용한다.
  • 동의/비동의 확인 메세지가 뜨는데 이를 Allow 하고 나면 소셜 ID, NAME, GENDER 등이 서버로 넘어가서 계정만들기, 세션만들기, JWT 발급 등을 할 수 있게 된다.
  • 이는 인증인데 비밀번호 같은 것을 다루지 않아도 된다는 특징이 있다.
  • 하지만 적당한 소셜사이트가 없다면 사용이 불편할 것이라는 단점도 보인다.
  • 이 OAuth란 방식도 항해에서 구현해봤었는데 그때의 기억으로는 프론트에서는 크게 할건없었고 서버로부터 리다이렉트 받은 사이트의 쿼리스트링으로 받은 JWT를 로컬스토리지에 넣은게 끝이었다.
  • 즉, 서버가 조금 많이 힘들었던 것 같다.
  • 생각해보면 카카오톡 로그인도 이런 방식이었고 실전에서도 했었다.
  • 리다이렉트가 핵심 키워드였고 프론트입장에서 뭘 해야 하는지는 알지만 전체적인 그림은 이해를 잘 못했기에 다음에 기회가 된다면 잘 정리해보고 싶다.

출처

https://patrick-f.tistory.com/13