[Web] 로그인 인증 방식

dee·2023년 1월 9일
2

web

목록 보기
1/2
post-thumbnail

🤔로그인 인증 왜 하는 거지?

맨 처음 로그인 기능을 구현했었을 때 단순히 사용자가 정보를 입력하고 이를 서버에서만 확인하는 것이라고만 생각했었다. 하지만 프론트 개발을 점차 공부하면서 어떻게 사용자 세션을 유지할 것인지가 중요하다는 것을 알았다. 왜냐 HTTP 통신으로 요청하면 응답이 한 후 종료되는 stateless 특징때문에 연결이 끊어어지므로 누가 로그인 중인지를 기억해야 하기 때문이다. 개발 공부 초반에 정리하지 못했던 이 방식들에 대해 정리하고자 한다.

  1. Cookie
  2. Session
  3. JWT (Access Token + Refresh Token)
  4. OAuth 2.0

  • Key/Value 쌍으로 이루어진 문자열.
  • 사용자 브라우저에 저장.
  • 4KB 이하의 한정적인 저장 공간으로 용량이 제한됨.
  • 브라우저마다 쿠키 지원 형태가 달라 브라우저간 공유가 불가능.
  • 보안에 취약하다는 단점(요청시 쿠키의 값을 그대로 보내기 때문).
  • httpOnly flag로 클라이언트 단에서의 접근으로부터는 보호 가능.
  • 요청마다 쿠키를 담아 보내므로 쿠키 사이즈가 커지면 네트워크 부하가 심해짐.

📍 쿠키 인증 방식

  1. 맨 처음에 클라이언트는 쿠키없이 요청을 보낸다.
  2. 서버는 이에 대한 응답을 할 때 클라이언트에 저장하고 싶은 정보를 응답 헤더의 Set-Cookie에 담는다.
  3. 이후 클라이언트는 요청을 보낼 때마다 요청 헤더의 Cookie에 저장된 쿠키를 담아 보낸다.
  4. 서버는 쿠키에 담긴 정보를 통해 클라인언트가 누군지 식별하거나 정보를 바탕으로 광고를 띄운다.

2. 세션

  • Key/Value 쌍으로 이루어짐.
  • 쿠키가 보안에 취약하기에 비밀번호같은 민감한 인증 정보를 브라우저가 아닌 서버 측에 저장하고 관리하는 것.
  • 서버 메모리나 서버 로컬 파일 또는 데이터 베이스에 저장(세션 저장소에 저장, 추가적인 저장 공간이 필요).
  • 사용자 식별자인 session id를 저장과 정보를 저장.
  • 사용자가 많아지면 정보를 찾는 데이터 매칭에 오랜 시간이 걸리면서 부하가 가해짐.
  • 쿠키에 session id를 저장.
  • 위의 쿠키가 노출되더라도 session id가 개인정보를 가지지 않아 1번째 쿠키 인증보다는 안전하지만 해커가 세션 ID 자체를 탈취하여 위장하여 접근할 수 있다는 한계가 있다.(하이재킹 공격)

📍 세션 인증 방식

  1. 사용자가 로그인한다.
  2. 서버는 회원 확인 후 세션 저장소에 Session ID를 저장한다.
  3. 로그인에 대한 응답으로 Cookie에 Session ID를 담아 전달한다.
  4. 사용자가 요청할 때마다 Session ID가 담긴 Cookie와 함께 보낸다.
  5. 서버는 세션 저장소에 Session ID와 일치하는 지 확인한다.
  6. Session ID가 일치하면 응답을 보낸다.

3. JWT(JSON Web Token)란?

  • 사용자를 인증하고 식별하기 위한 정보들을 암호화시킨 토큰.
  • JSON 데이터를 URL로 이용할 수 있는 문자(Base64 URL-safe Encode)로 인코딩하여 직렬화한 것.
  • 전자 서명도 있어 JSON의 변조를 체크할 수 있음.
  • 쿠키를 통해 클라이언트에 저장.
  • 단순히 HTTP 요청시 헤더에 토큰을 첨부하는 것만으로 데이터를 요청하고 응답을 받아올 수 있음.
  • '.'을 기준으로 Header, Payload, Signature 나누어짐.
파트설명
Header토큰의 타입과 해시 암호화알고리즘 구성.
첫째는 토큰의 유형(JWT)를 나타내고 두번째는 HMAC, SHA256 or RSA와 같은 해시 알고리즘을 나타냄.
Payload토큰에 담을 클레임 정보를 포함함.
payload에 담는 정보의 한 조각을 클레임. 이는 name/value의 한 쌍으로 이루어짐. 토큰에는 여러 개의 클레임을 넣을 수 있음.
클레임 정보는 등록된 클레임, 공개 클레임, 비공개 클레임으로 세 종류가 있음.
- iss (Issuer) : 토큰 발급자
- sub (Subject) : 토큰 제목, 토큰에서 사용자에 대한 식별값이 됨
- aud(Audience) : 토큰 대상자
- exp (Expiration Time) : 토큰 만료 시간
- nbf (Not Before) : 토큰 활성 날짜 (이 날짜 이전의 토큰은 활성화 되지 않음을 보장)
- iat (Issued At) : 토큰 발급 시간
- ti (JWT Id) : JWT 토큰 식별자 (issuer가 여러명일 때 이를 구분하기 위한 값)
Signature                    secret key를 포함하여 암호화.
signature는 사용자 정보를 기반으로 암호화되었기 때문에 해커가 payload 값을 변경하여 요청해도 유효하지 않은 토큰으로 인식한다.

📍 JWT 인증 방식.

JWT는 Access Token만으로도 인증 방식을 구현할 수 있다. 하지만 한 번 발급되면 유효기간이 만료될 때까지 삭제를 할 수 없어 만료 전에 해커에게 정보가 털린다면 대처할 방법이 없다. 그렇다고 유효기간을 짧게 하면 자주 인증해야된 불편함이 생긴다. 이에 Refresh Token을 같이 발급하여 이 문제를 해결하고 있다.

  • Refresh Token : Access Token보다 긴 유효기간을 가지고 Access Token이 만료됐을 때 새로 발급해주는 열쇠이다.

🧐 Refresh Token이 탈취될 수도 있지 않을까??
Access Token처럼 똑같이 탈취당할 때의 취약점이 있다. 하지만 다른 점이 있다면 매 요청마다 HTTP 통신으로 노출이되는 Access Token과 달리, Access Token이 만료됐을 경우에만 네트워크 통신으로 Refresh Token을 서버로 보내기 때문에 탈취될 위험이 적다는 보안의 이점이 있다.

  • 진행 순서
  1. 사용자가 로그인한다.
  2. 서버는 회원 확인 후 서명된 JWT 생성하여 클라이언트에 응답한다.
    이때 Access Token과 Refresh Token을 같이 전달한다.
  3. 사용자가 요청할 때마다 Access Token와 함께 보낸다.
  4. 서버에서 Access Token을 검증한다.
  5. 검증이 완료되면 응답을 보낸다.
  6. 🚨 Access Token 만료되었다.
  7. 사용자가 Access Token과 함께 데이터를 요청한다.
  8. 서버에서 Access Token이 만료된 것을 확인한다.
  9. 만료되었다는 것을 알려주는 응답을 보낸다.
  10. 사용자는 만료 응답을 받고 Access Token과 Refresh Token을 같이 담아 발급 요청을 보낸다.
  11. Refresh Token을 확인한 후 Access Token을 발급한다.
  12. Access Token과 함께 응답을 보낸다.

4. OAuth(Open Authorization)란?

  • 별도의 회원가입 없이 외부 서비스에서도 인증을 가능하게 하고 해당 서비스의 API를 이용하게 해주는 프로토콜로 현재는 2.0.이다.
  • 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준.
  • OAuth는 여러 곳에 개인정보를 제공하고 싶지 않은 점으로 생긴 이유가 큼. 여러 곳에 제공하게 되면 피싱에 둔감해지고 무엇보다 안전하다는 보장이 없기 때문.

OAuth 1.0 vs 2.0?

  • 기능의 단순화, 기능과 규모의 확장성 등을 지원하기 위해 만들어짐.
  • 1.0는 만들어진 다음 표준이 된 반면 2.0은 처음부터 표준 프로세스로 만들어짐.
  • https가 필수여서 간단해짐.
  • 암호화는 https에 맡김.
  • 1.0는 인증방식이 한 가지였지만 2는 다양한 인증방식을 지원.
  • api서버에서 인증서버를 분리 할 수 있도록 해 놓았다.
OAuth 1.0OAuth 2.0
참여자이용자, 소비자, 서비스 제공자자원 소유자, 클라이언트, 권한 서버, 자원 서버
토큰요청 토큰(Request Token), 접근 토큰(Access Token)접근 토큰(Access Token), 재발급 토큰(Refresh Token)
유효기간접근 토큰의 유효기간 없음접근 토큰 유효기간 부여, 만료시 재발급 토큰 이용
클라이언트웹 서비스웹, 앱 등

OAuth 2.0에 대해 자세히 알아보자

  • 자원 서버(Resource Server) : Client가 제어하고자 하는 자원 보유하고 있는 서버
  • 자원 소유자(Resource Owner) : 자원의 소유자 (로그인하는 실제 사용자)
  • 클라이언트(Client): 자원 서버에 접속해서 정보를 가져오고자 하는 클라이언트.(웹 어플리케이션)
  • 권한 서버(Authorization Server) : 클라이언트가 자원 서버의 서비스를 이용할 수 있게 인증하고 토큰을 발생해주는 서버(인증 서버)
    ex. 구글, 페이스북 등
  • Access Token: 자원 서버에 자원을 요청할 수 있는 토큰
  • Refresh Token : 권한 서버에 접근 토큰을 요청할 수 있는 토큰

📍 OAuth 인증 방식

먼저 클라이언트가 자원 서버를 이용하기 위해 사전 승인을 받아야한다. 보통 자원 서버 홈페이지에 도메인을 등록하면 된다. 등록 절차를 완료하면 자원 서버와 연결하기 위한 정보를 얻을 수 있다. 구글을 기준으로 살펴보면 클라이언트 ID와 클라이언트 보안 비밀번호를 알 수 있고 이를 통해 OAuth에 접근할 수 있다.

  1. 자원 소유자(사용자)가 구글 로그인을 요청한다.
  2. 클라이언트는 인증 서버에 로그인 페이지를 요청한다.
  3. 인증 서버가 로그인 페이지를 제공한다.
  4. 제공받은 로그인 페이지에 ID와 비밀번호를 입력한다.
  5. 입력받은 값으로 인증 서버에 요청한다.
  6. 인증 서버에 Authorization code를 발급한다.
  7. 이 code로 인증 서버에 Access Token를 요청한다.
  8. 인증 서버에서 Access Token을 발급해준다.
  9. 인증이 완료되었다.
  10. 자원 서버에 Access Token을 담아 데이터를 요청한다.
  11. Access Token을 검증 후 응답을 준다.
  • 만일 Access Token이 만료됐거나 위조되었다면, Client는 Authorization Server에 Refresh Token을 보내 Access Token을 재발급 받습니다.

참고 자료
https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-JWTjson-web-token-%EB%9E%80-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC
https://velog.io/@gusdnr814/%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%9D%B8%EC%A6%9D-4%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95
https://pronist.dev/143
https://showerbugs.github.io/2017-11-16/OAuth-%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C
https://tecoble.techcourse.co.kr/post/2021-07-10-understanding-oauth/
https://doqtqu.tistory.com/295

profile
웹 프론트엔드 개발자

1개의 댓글

comment-user-thumbnail
2023년 3월 30일

덕분에 좋은 내용 잘 보고 갑니다
감사합니다.

답글 달기