Bin's Blog

session과 JWT 그리고 OAuth 본문

Web

session과 JWT 그리고 OAuth

hotIce 2023. 9. 25. 16:21
728x90

글의 시작

오늘 다루는 주제는 로그인할 때 사용자 인증 방식에 대한 내용이다. 

이 내용은 내가 실제 면접 때 질문을 받아봤던 내용이다. 

쿠키와 세션만 알고 있었지, JWT와 OAuth 방식에 대해서는 잘 몰랐다.

그래서 이번 포스팅을 통해서 3가지 방법을 비교해 보면서 어떤 장단점들이 존재하는지 동작 방식에 대해서 파헤쳐 본다. 

 

회원기능 동작 방식

 

예를 들어 게시물들을 로그인한 사람만 볼 수 있게 만든다면 회원기능이 필요한데 어떤 식으로 회원기능을 만들면 될까?

 

회원기능 동작방식

회원가입

유저가 가입하면 아이디/비밀번호를 DB에 저장해 놓는다.

 

로그인

유저가 로그인시 아이디/비밀번호를 서버로 보낸다.

서버는 DB에 있는 아이디/비밀번호와 유저가 보낸 아이디/비밀번호가 일치하는 경우 입장권을 발급해준다.

 

로그인이 필요한 서버기능

유저는 서버에 GET/POST로 데이터 요청시 입장권도 함께 제시한다.

서버는 입장권 확인 후 데이터나 페이지를 보내준다. 

 

 

그래서 오늘은 입장권을 어떤 식으로 만드는지 알아보자.

 

입장권

입장권

입장권은 위의 그림처럼 그냥 유저 정보가 써있는 간단한 문자자료이다.

로그인 완료시 서버가 "이 사람은 누구고 언제 로그인했는지"이런 문자를 만들고 유저에게 보내서 사용하게 만들면 그것이 입장권일 뿐이다.

 

일반 유저들에게 입장권을 직접 사용하면 귀찮으니까 유저도 모르게 입장권을 제시하게 만들 수 있는 방법이 존재한다. 

브라우저의 쿠키 저장소를 이용하면 된다. 

크롬 개발자도구를 켜면 Application 탭에 Cookies라고 있다. 

쿠키

쿠키 저장소에 저장해놓은 쿠키는 서버로 GET/POST 요청시 자동으로 함께 전송된다. 

그래서 서버는 유저의 브라우저의 쿠키라는 공간에 서버의 권한으로 입장권을 강제로 저장시킨다.

 

로그인시 입장권을 만들어서 유저 브라우저 쿠키에 넣어두면 되는데

입장권을 만들 때 대표적으로 session, JWT(token)방식 2개가 있다.  

 

Session

 

session

session이란?

 

유저가 로그인하면 DB or 서버 메모리에 { 유저의 아이디, 로그인 날짜, 유효기간, session id }를 기록해두고 유저에게 입장권을 발급해줄 때 입장권에 session id 하나만 달랑 적어 보낸다.

그러면 유저가 GET/POST 요청을 하면 입장권을 제출하고 입장권을 열어보면 session id가 존재할 것이고 이걸 가지고 DB의 session id에 해당하는 문서를 찾는다. 유효기간이나 별 문제 없으면 통과시켜준다

 

장점/단점

장점은 유저의 GET/POST 요청 할때마다 DB를 조회해보기 때문에 하나하나의 요청마다 엄격하게 로그인상태를 체크한다.

단점은 엄격하게 하는만큼 DB가 부담이 심해진다. 단점을 보완하기 위해서 유저가 많은 사이트들은 입출력 빠른 redis(session id 보관용 DB)를 사용한다. 

 

 

JWT

JWT

JWT이란?

JSON Web Token 방식이다. 

유저가 로그인하면 유저에게 입장권을 발급해줄 때 입장권에 { 유저의 아이디, 로그인 날짜, 유효기간 }을 적어두고 암호화해서 보낸다.

DB에 저장하지 않는 방식으로, 유저가 GET/POST 요청시 입장권을 제출하면 서버에서 확인해보고 별 이상이 없으면 통과시켜 준다. 

암호화해서 보내기 때문에 유저가 위조하면 위조여부를 쉽게 파악할 수 있다. 

 

장점/단점

장점은 GET/POST 요청할 때마다 DB를 조회하지 않아도 되니 DB의 부담이 적다. 그래서 유저가 많거나 마이크로서비스 운영중이면 편하다.

단점은 유저의 JWT를 나쁜 사람이 훔쳐가면 그 사람의 로그인을 막거나 할 수 있는 방법이 없다. 다른 컴퓨터를 강제로 로그아웃 시킬 수도 없다. 나쁜 입장권을 모아서 DB에 저장하면 되는데 그러면 session 방식이랑 차이가 없어진다. 

 

 

JWT구조 

JWT는 Header, Payload, Signature 3 부분으로 이루어진다. 

각각의 부분은 Base64 인코딩되어 표현되고 각각의 부분을 이어주기 위해 구분자를 사용하여 구분한다. 

 

JWT 구조

Header

JWT를 어떻게 검증하는가에 대한 내용을 담고 있다.

토큰의 헤더에 두 가지가 존재한다. 

 

1. typ - 토큰의 타입을 지정한다.

2. alg - 서명시 사용하는 알고리즘이다. 

 

PayLoad

토큰에 저장된 정보들인 클레임이 담겨 있다. 클레임은 세 가지 종류로 나누어지며, JSON 형태로 다수의 정보를 넣을 수 있다.

 

등록된 클레임

등록된 클레임은 토큰 정보를 표현하기 위해 이미 정해진 종류의 데이터들이며 정해진 것들 중 선택적으로 골라 작성한다.

  • iss - 토큰 발급자
  • sub - 토큰 제목
  • aud - 토큰 대상자
  • exp - 토큰 만료 시간
  • nbf - 토큰 활성 날짜
  • iat - 토큰 발급 시간
  • jti - JWT 토큰 식별자

 

공개 클레임

공개 클레임은 사용자 정의 클레임으로, 공개용 정보를 위해 사용된다. 충돌 방지를 위해 URI 포맷을 사용한다.

{
    "https://hobin49.tistory.com/" : true
}

 

비공개 클레임

비공개 클레임은 사용자 정의 클레임으로, 서버와 클라이언트 사이에 임의로 지정한 정보를 저장한다.

{
    "token_type" : "access"
}

 

Signature

토큰을 인코딩하거나 유효성 검증을 할 때 사용되는 고유한 암호화 코드이다. 

Header와 Payload의 값을 각각 Base64로 인코딩한 후 인코딩 된 값을 Secret Key를 이용해 헤더에서 정의한 알고리즘으로 암호화하고 다시 Base64로 인코딩하여 생성한다

{
    "Authorization": "Bearer {Token}"
}

{Token} 자리에 생성된 토큰 값이 저장된다. 

 

 

OAuth 

OAuth

OAuth란?

오늘날 실제로 대부분 사이트에서 카카오, 네이버, 페이스북 등으로 로그인 할 수 있는데 이것을 소셜 로그인이라고 부른다.  

OAuth(Open Authorization)은 인증을 위한 개방형 표준 프로토콜이다. 

현재는 OAuth 2.0를 사용한다. 

 

유저의 A 사이트의 사용권한을 B사이트를 운영하는 내가 잠깐 빌릴 수 있는데(회원정보 대여) 그 과정을 정의하는 규칙이다.

예를 들어, 내가 Google에 로그인을 하면 이용하려는 사이트에 정보를 제공할 것인지 동의 여부를 물어본다. 

동의하면 구글에서 해당 사이트로 유저 정보 {이름, 이메일, access token, 유효기간}를 보낸다. 이걸로 회원기능 구현하면 된다.  

 

OAuth 2.0 개념

 

OAuth 2.0에서 사용하는 주요 용어와 개념들에서 살펴보자.

용어 설명
Authentication 인증, 접근 자격이 있는지 검증
Authorization 인가, 자원에 접근할 권한 부여 인가 완료 후 Access Token 획득
Access Token 리소스 서버에게서 자원을 획득할 때 사용되는 만료 기간이 존재하는
Token
Refresh Token Access Token 만료시 갱신하기 위한 Token

 

역할 설명
Resource Owner 보호된 자원에 접근할 수 있는 자격을 부여해 주는 주체
(실제로 애플리케이션을 활용하는 사용자)
Client 보호된 자원을 사용하려고 접근 요청 하는 애플리케이션
Resource Server 사용자의 자원을 호스팅하는 서버
(구글, 카카오, 네이버, 깃허브 등)
Authorization Server 인증/인가를 수행하여 접근 자격을 확인하고 Access Token을 발급하여 권한을 부여 

 

OAuth 2.0 동작과정

가장 보편적으로 사용되는 Authorization Code Grant(권한 부여 승인 코드 방식)에 대해서 살펴보고자 한다. 

다음은 KAKAO OAuth 2.0 프로세스이다.

로그인 과정 시퀀스 다이어그램

사용자가 서비스에서 카카오 로그인 버튼을 클릭하면, 서비스는 카카오 인증 서버로 인가 코드 발급을 요청한다. 

카카오 인증 서버는 사용자에게 인증을 요청한다. 인증이 성공 시, 사용자에게 동의 화면을 출력한다. 

사용자가 동의하고 로그인 요청하면, 카카오 인증 서버는 인가 코드(Authorization Code)를 발급해 서비스 앱에 등록된 Redirect URI로 전달한다. 

서비스는 전달받은 인가 코드로 토큰을 요청하여 받는다. 그렇게 해서 사용자 정보를 요청해서 가져오고 유효성 검증 후에, 회원 여부 확인 후에 회원 가입 처리 단계를 거치고 서비스 서버는 클라이언트에 해당 사용자의 로그인에 대한 세션을 발급한다. 

 

글의 마무리

"왜 대부분 사이트에서 OAuth 방식을 사용할까?"라고 생각해보면 사실 간단하기 때문이라고 생각한다. 사용자 입장에서도 귀찮게 회원가입 없이 소셜로그인 동의 버튼을 누르면 간단하게 로그인이 되거나 간소하게 회원가입을 진행할 수 있기 때문이다. 서비스를 운영하는 입장에서도 사용자의 ID, password를 보관하지 않아도 되니 편할 것이다. 

다음 프로젝트 때는 OAuth 방식으로 사용자 인증 방식을 구현해 봐야겠다.  

 

 

📚 참고자료

https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api
https://gilssang97.tistory.com/55

 

728x90

'Web' 카테고리의 다른 글

시맨틱 태그(Semantic Tag)란?  (0) 2023.11.09
웹 브라우저의 동작원리  (0) 2023.09.22
CORS란 무엇일까?  (0) 2023.09.03
쿠키와 세션  (0) 2023.07.06