1. 인증(Authentication)과 인가(Authorization)
인증(Authentication)은 사용자가 서비스에 등록되어 있는지 검증하기 위해 사용된다. 예를 들어, 사용자가 입력한 정보가 서비스에 등록되어 있다면 인증된 사용자라고 할 수 있다.
인가(Authorization) 는 인증이 완료된 사용자가 서버에서 보호하고 있는 자원에 접근할 수 있는지 권한을 확인하는 과정이다. 먼저 인증이 되어야만, 인가 여부를 확인할 수 있다. 예를 들어, 게시판에 글을 작성하는 것은 로그인 된(인증된) 사용자(USER, ADMIN)라면 누구나 할 수 있지만, 관리자 페이지에 접근하는 것은 관리자 권한(ADMIN)이 있는 사람만 가능할 것이다.
인증(Authentication), 인가(Authorization) 방식은 토큰(Token)과 세션(Session) 방식에서 사용될 수 있다.
2. 세션(Session) 방식
세션(Session)방식은 서버에서 사용자를 식별하기 위한 정보를 저장하는 방법이다. 쿠키(Cookie)방식과 달리 사용자를 식별하기 위한 정보를 서버에서 저장하고 있기 있다.
세션을 사용하여 사용자를 식별하는 방법은 다음과 같다.
- 클라이언트가 서버로 요청을 보낸다. (이 요청에는 쿠키를 포함하고 있지 않다.)
- 서버는 이후의 요청에 대해서 사용자를 식별하기 위한 세션을 생성하여 서버 메모리에 저장하고, 세션을 구분하기 위한 SessionID를 생성한다. 이 SessionID를 응답에 포함하여 전달하고, 브라우저의 쿠키에 저장한다.
- 사용자는 앞으로 요청을 보낼 때마다 요청 헤더의 쿠키 값으로 SessionID를 포함하여 전달하고, 서버는 SessionID를 통해 서버 메모리에 저장된 세션 데이터를 가져온다.
3. JWT 토큰(Token) 방식
토큰(Token) 방식은 Stateless한 인증 방식에서 사용되며, 인증된 사용자를 의미하는 토큰 값을 클라이언트 측에서 관리한다.
토큰은 다음과 같이 작동한다.
- 사용자가 로그인을 시도한다.
- 사용자가 입력한 정보가 서버에 저장되어 있는지 확인하고, 이 사용자의 인증(Authentication), 인가(Authorization) 정보를 담은 JWT 토큰을 발급한다.
- 사용자는 서버의 자원에 접근하려고 할 때, 요청 헤더의 Authorization 값으로 토큰 값을 포함하여 요청한다.
- 서버는 요청 헤더에 담긴 토큰이 유효한지 검증한다.
- ex) 토큰이 만료되었는지, 토큰이 조작되었는지 …
- 먼저 토큰을 검증하여 유효한 사용자인지 검증하고(인증 여부), 사용자가 요청한 자원에 접근할 권한이 있는지(인가 여부)를 확인한다.
- 인증되지 않은 사용자는 서버에서 401 Unauthorized 예외를 발생한다.
- 보호하고 있는 자원에 접근할 수 있는 사용자라면 요청 자원에 대한 데이터를 응답으로 내려주고, 권한이 없는(인가되지 않은) 사용자라면 접근하지 못하고 예외가 발생한다.
- 인가되지 않은 사용자는 서버에서 403 Forbidden 예외가 발생시킨다.
JWT 토큰은 Header, Payload, Signatrue로 구성되어 있다.
- Header(헤더) : JWT 토큰의 암호화 유형을 포함한다.
- 사진에서는 HS256 알고리즘을 사용하여 암호화하였음을 알 수 있다.
- Payload(본문) : JWT 토큰이 담고 있는 데이터를 의미한다.
- Payload에는 중요한 정보를 절대로 담아서는 안 된다. (ex. 비밀번호)
- 발급된 JWT 토큰을 사진처럼 복호화할 수 있기 때문에 중요한 정보는 담지 않는다.
- 서버에서는 payload에 담긴 name 값으로 DB에 저장된 사용자를 조회하고, 조회한 사용자의 암호화된 비밀번호와 요청 데이터에 담긴 평문 비밀번호를 비교하여 일치하는지 확인한다.
- Signature(서명) : JWT 토큰의 무결성을 검증하는데 사용된다.
- JWT 토큰 검증 과정
- JWT 토큰 파싱 : 클라이언트가 Authorization 헤더에 담은 JWT 토큰을 파싱하여 Header, Payload, Signatrue 세 부분으로 분리한다.
- 서버는 Header와 Payload를 사용하여 다시 서명을 하는데, 이 때 JWT 토큰 생성 시 사용하였던 동일한 알고리즘(ex. HS256)을 사용한다.
- 서명을 생성할 때, Header와 Payload를 Base64URL로 인코딩하고, 여기에 서버에 저장된 비밀키(Secret Key)를 사용하여 서명 값을 생성한다.
- 클라이언트에서 보낸 JWT 토큰에 담긴 서명과 서버에서 다시 생성한 서명이 일치한 경우, 해당 JWT 토큰이 유효함을 의미한다.
- JWT 토큰 검증 과정
4. 결론
세션(Session) 방식은 서버가 사용자 정보를 저장하고 관리하기 때문에 Stateful한 방식이다. 서버는 각 사용자의 상태를 유지하며, 요청이 있을 때마다 이 정보를 참조하여 사용자를 인증하고 인가한다.
반면, JWT 토큰 방식은 클라이언트가 토큰을 보관하고 전달하는 Stateless한 방식이다. 서버는 사용자의 상태 정보를 유지하지 않으며, 클라이언트가 요청 시에 제공하는 토큰을 통해 인증과 인가를 수행한다.
두 방식 모두 사용자의 인증 및 인가 시스템을 구현할 수 있지만, 세션 방식은 서버가 인증 및 인가 정보를 관리하는 반면, JWT 토큰 방식은 이러한 정보를 포함하는 토큰을 클라이언트가 관리하게 된다.