[다시하는 백엔드 기초 공부] 인증(Authentication)과 인가(Authorization)
인증(Authentication)과 인가(Authorization)
둘 다 편의상 auth로 줄여 부르기도 하고 구분없이 ‘인증’으로 부르는 경우가 많지만 사실 두 개념은 엄연히 분리해서 봐야한다.
**인증(Authentication)**은 사용자의 신원을 확인하는 절차로, 서비스 이용 대상의 확인 그리고 다른 사용자들과의 구분 및 정보 보호를 주 목적으로 한다. **인가(Authorization)**는 사용자에게 권한을 부여하는 과정으로 리소스에 대한 접근과 작업 허가 범위 등을 확인한다.
공통적으로는 둘 다 사용자가 특정 리소스에 접근하는 과정에 활용되며, 순서는 항상 인증 후 인가로 이어진다. (누구인지 모르면 권한을 줄 수 없으므로)
웹에서의 인증과 인가
웹에서의 사용자 인증 과정은 일반적으로 로그인이 가장 많이 사용된다. 사용자 본인이 누구인지에 대한 정보로 아이디를 제공하고 본인이 그 사용자인지에 대한 증거로서 비밀번호를 제공한다. 인증이 이루어지고 나면 인가는 사용자 정보를 바탕으로 어플리케이션에서 처리하도록 구현이 이루어진다.
HTTP 프로토콜 내에서의 한계
HTTP의 특징은 통신이 지속되지 않고 클라이언트에서 보내는 요청에 따라 서버에서 응답을 보내주는 단방향 통신이며 각 요청은 모두 독립적이라는 것이다. 또한 서버가 클라이언트의 상태를 보존하지 않는 Stateless 프로토콜이다.
서버가 상태를 보존하지 않기 때문에 클라이언트가 서버에 로그인 요청을 이미 했다 하더라도 다음 요청을 보낼 때 서버는 요청을 보낸 사용자가 누구였는지 기억하지 못한다. 즉, 새로운 요청을 할 때마다 인증 과정을 거쳐야한다.
하지만 실제 웹 어플리케이션들은 매번 로그인을 거치지 않아도 이용하는데 문제가 없는데, 이는 다양한 인증 방식을 통해 클라이언트가 사용자 정보를 저장해놓고 사용하기 때문이다.
주요 인증 방식
— HTTP 환경에서 사용되는 인증 방식들은 여러가지가 있지만 대표적인 몇 가지를 소개해본다.
Basic Authentication
가장 단순한 인증방법으로 HTTP header에 사용자의 username과 password를 포함하여 서버에 보내는 것이다.
간단하고 별도의 세션 관리가 불필요하다는 장점이 있지만 Authorization: Basic <base64(username:password)>
형태로 Base64 인코딩을 적용한다고는 해도 암호화를 한 것은 아니기 때문에 보안이 취약하다.
세션 기반 인증 (쿠키 인증)
사용자 로그인을 하면 서버에서 DB에 유저 세션 정보를 생성하고 세션 ID를 클라이언트에 반환한다. 이후 클라이언트의 웹 브라우저가 종료될 때까지 쿠키에 세션 ID를 저장해놓고 인증상태를 유지하며 요청마다 Cookie: session_id=…
정보를 포함한다.
서버에서는 요청이 올 때마다 세션 ID를 기반으로 DB의 유저 세션 정보를 확인하여 처리하는데, 현재 서비스를 사용중인 유저들의 상태를 관리해야 할 경우 유용하지만 단점으로 DB 리소스를 소요하며 서버 확장 시 세션 공유 문제 등이 발생할 수 있다.
토큰 기반 인증
사용자 로그인 성공 시 서버가 비밀 키를 사용하여 발행한 토큰을 클라이언트에 반환하고 이후 요청마다 Authorization: Bearer <token>
을 헤더에 포함하여 보내면 서버에서 토큰이 유효한지를 검증하고 요청을 처리한다.
유저의 상태 정보를 서버가 기록해놓는 세션 기반 인증은 stateful 한 방면, 토큰 기반 인증은 서버에서 토큰의 유효성 검사만 하기 때문에 stateless 하다.
JWT (JSON Web Token)
토큰 기반 인증에서 대표적으로 사용하는 형식. JSON 데이터 구조를 토큰에 담아 사용자 정보, 만료 시간 등을 포함시킬 수 있으며 구조는 아래와 같다.
- header: 토큰 유형(=”JWT”)과 사용된 서명 알고리즘 정보 두 가지 정보가 들어있다.
- payload: 정보(claim)를 담는 공간으로 iss(발급자), sub(주체), exp(만료 시간), iat(발급 시간) 등이 표준으로 사용되며 그 외 임의의 정보도 포함시킬 수 있다.
- signiture: 헤더+페이로드를 서버의 비밀키를 사용하여 서명한 값 JWT의 장점은 서버가 세션 저장소를 가지지 않아도 되고 여러 서비스 간 인증 정보를 공유할 수 있어서 확장성이 좋다는 것, 그리고 다양한 언어/플랫폼에서 지원된다는 것이다. 하지만 payload에 따라 토큰이 길어질 수 있고 토큰이 중간에 탈취될 가능성에 대비해 클라이언트에서 안전한 보관방법이 필요한데, 한번 발행된 토큰은 취소할 수 없어 이에 대한 블랙리스트 관리나 짧은 만료시간+리프레시 토큰 사용 등 대비가 함께 필요하다.
API Key 인증
API 사용을 위한 고정된 키를 클라이언트 측에 발급하여 사용하도록 하는 방법. 간단하지만 키가 탈취될 경우 제어하기가 어려워 사용자 단위 인증보다는 내부 API 또는 외부 파트너 API 등 앱 단위 인증에 주로 사용된다.
OAuth 2.0
현재 구글/페이스북/깃허브 계정 등을 통한 소셜 로그인이나 써드파티 앱 연동에 활용되는 위임 인증 방식. 클라이언트에서 구글 같은 외부 인증 서비스로부터 인증 코드를 받으면 클라이언트가 인증 코드를 기반으로 access 토큰을 발급하고 해당 토큰을 사용하여 서버에 요청을 보내는 방식이다. 플로우가 복잡하고 보안 취약점 관리가 필요하다는 단점이 있지만 보안 수준이 높다.