{
"typ" : "JWT",
"alg" : "HS256"
}
토큰의 정보를 담기위해 이름이 지정된 클레임, 사용에 필수는 아니다.
- iss : 토큰 발급자.
- sub : 토큰 제목.
- aud : 토큰 대상자.
- exp : 토큰의 만료시간, NumericDate 형식으로 구성되고 **현재 시간** 이후로 설정되어 있어야 한다.
- nbf : 토큰의 활성날짜. NumericDate 형식으로 구성되고 작성된 **날짜** 이후로 토큰이 활성화 된다.
- iat : 토큰의 발급 시간. 해당 정보를 통해 유효성을 확인 할 수 있다.
- jti : 고유 식별자, 중복처리 방지를 위해 사용함
정해진 형식이 아닌 임의의 정보를 필요에 따라 정의하는 클레임. 모든 사용자가 알 수 있는 정보를 담고 있기 때문에
충돌에 대한 대비를 해야한다. 예로는 그룹화(user_, system_) 또는 네임스페이스 적용
ex)
- name : 사용자의 이름
- email : 사용자의 이메일
- role : 사용자의 권한
특정 시스템 또는 사용자에게 의미가 있는 정보를 담기 위해 사용한다. 클라이언트와 서버간 약속된 형식으로 사용되며,
일반적으로 공개되지 않는다. 유일성 보장을 위해 특정 접두사나 식별자를 추가한다.
ex)
- app-private-date
1. Header와 Payload를 Base64URL 인코딩한다.
2. 인코딩 결과 Header+Payload 와 같이 연결한 후 비밀키를 이용해 Header의 alg 필드에 정의된 보안 알고리즘을
사용하여 암호화 한다.
3. 암호와된 결과값을 다시 Base64로 인코딩한다.
- 사용자 인증에 필요한 모든 정보를 토큰 자체에 저장하기 때문에 별도의 세션 상태를 유지할 필요가 없다.
- 클레임(claim) 기반으로 정보를 저장하고 전송하기 때문에 필요에 따라 클레임을 확장할 수 있다.
- 별도의 저장소가 필요하지 않아 서버의 자원 절약 및 트래픽의 과부하를 줄인다.
- 자체적으로 만료 시간을 포함하여 유효 기간을 설정 하여 자동으로 폐기 할 수 있다.
- 서명을 통한 토큰의 무결성을 보장한다.
- 정보를 토큰에 저장하기 때문에 토큰의 크기에 따라 네트워크 과부화 및 처리 시간을 증가 시킬 수 있다.
- 인코딩된 내용의 길이에 따라 payload의 크기가 증가한다.
- 한번 발급된 토큰은 불변하기 때문에 유효성 관리를 위한 메커니즘을 추가로 구축해야 한다.
- 사용자의 정보를 업데이트 해야하는 경우
- 토큰을 클라이언트측에서 저장하고 관리하기 때문에 토큰의 탈취 및 디코딩에 대한 보안 조치가 필요하다.
- payload는 base64로 디코딩이 가능하기 때문에 중요한 정보를 넣어서는 안된다.
base64를 사용하여 인코딩되며 암호화 알고리즘이 아니기 때문에 디코딩시 payload의 정보를 그대로 확인 할 수 있다. 때문에 PW와 같은 중요 정보를 넣지 않는것이 좋다.
- 로그인
- 로그인시 유저의 정보를 기반으로 JWT를 발급하고 요청에 따라 JWT만을 검증하고 권한을 확인하여 작업을 처리 한다.
- 세션의 유지가 필요 없고 요청에 따라 토큰만 확인하면 되기 때문에 서버의 자원을 아낄 수 있다.
- 정보 교환
- 자가수용적 특징과 클레임 기반의 유연성을 활용하여 효율적으로 데이터를 전달하고 받을 수 있다.
- 서명을 통해 무결성을 검증하고 데이터의 정확성을 보장받을 수 있다.
- 클라이언트로부터 로그인 요청이 들어온다.
- 서버에서 DB와 로그인 요청에 대한 유효성을 검사한다.
- 유효성에 통과한다면 서버에서 토큰(JWT)을 발행 한다.
- 발행된 토큰을 클라이언트에게 응답한다.
- 클라이언트가 데이터를 요청할때 토큰(JWT)와 함께 요청한다.
- 서버에서 토큰의 대한 유효성 검사를 한다.
- 유효하다면 요청 데이터를 응답한다.
token의 경우 클라이언트 측에서 관리되고 발행 후 유효기간 동안 되돌릴수 없기 떄문에 Access 토큰 을 탈취 당할시 보안에 대한 위협이 있을 수 있다. 이를 해결하기 위해 Access Token과 Refresh Token을 발행 한다.
1. 로그인 요청 2. 로그인 성공시 access token 및 refresh token 발급 3. access token을 사용하여 api 요청 4. access token의 유효성 문제가 있을다면 refresh token을 통해 검증 후 access 토큰을 재발행 한다.
- Access Token : 인증된 유저인지 서버에서 검증하는 토큰. 클라이언트에서 요청 헤더에 담아 보내는 토큰 이다.
- Refresh Token : access token이 만료되거나 유효성에 문제가 있을 경우 Refresh Token을 사용하여 검증 후 통과시 access token을 재발행 한다.
access token의 유효기간을 짧게, refresh token의 유효기간은 길게 설정함으로써 토큰의 생명주기를 빠르게 하여 보안적으로 유리하게 유저인증을 할 수 있다.
토큰을 저장하는 방식에는 두가지 방법이 있다. 웹 스토리지 (local, session)와 cookie이다. 이곳에 저장할 경우 페이지 이동 또는 브라우저를 재접속 하더라도 로그인을 유지할 수 있다. 하지만 JS를 통해 접근 할 수 있기 때문에 XSS와 CSRF 공격에 취약하다. 때문에 보안에 대한 대처를 해야한다.
1. XSS(Cross-Site Scripting) 공격
- 공격자가 클라이언트 브라우저에 악의적인 스크립트를 삽입하여 실행하는 공격
- url 또는 페이지에 JS 코드를 집어넣어 의도치 않은 명령을 실행시키거나 쿠키, 세션등의 정보를 탈취 할 수 있다.
- 대처법 : 입력 값 검증, 특수 문자 이스케이프 출력, 콘텐츠 타입 설정, HTTP-Only 쿠키 설정 등을 통해
대처 할 수 있다.
2. CSRF (Cross Site Request Forgery) 공격
- 인증된 사용자를 통해 비정상적인 request를 서버로 요청하여 정보를 탈취하거나 변경하는 공격
- 인증 되어 있는 사용자에게 악의적인 정보 변경과 같은 request를 img나 link에 포함하여 클릭하게 유도한다.
인증되어 있기 때문에 request는 정상적으로 수행되고 의도치 않은 정보변경이 실행되어 피해가 발생한다.
- 대처법 : CSRF 토큰, Same-site 쿠키 속성 설정, 리퍼러 헤더 검증, 2차 인증요구 등을 사용하여 대처 할 수 있다.
브라우저내에 local storage에 저장하고 요청 헤더에 토큰을 포함시켜 서버로 전송 시킨다.
장점
1. JS를 통해 쉽게 접근이 가능하기 때문에 간편하게 JS로 접근하여 토큰을 관리하거나 사용할 수 있다.
2. 클라이언트측에서 관리되기 때문에 서버는 토큰의 유효성만 검사하는 등 서버의 부담을 줄이는 장점이 있다.
3. 브라우저에 저장되기 때문에 토큰의 유효 기간내에서는 페이지를 닫거나 새로고침을 하더라도 토큰을 유지 할 수 있다. 또한 DB에 문제가 발생할시 토큰에 대한 유효성만 체크하면 되기 때문에 서버에 대한 의존성이 적다.
단점
1. JS를 통해 쉽게 접근이 가능하기 때문에 XSS 공격에 취약할 수 있다.
2. 저장된 토큰의 상태는 서버의 데이터가 달라지더라도 변하지 않기 때문에 유효성 체크에 대한 추가적인 로직을 구현해야 한다.
쿠키에 저장하여 클라이언트측에서 http 요청시 헤더에 쿠키가 포함되어 서버로 전송되게 된다.
장점
1. 쿠키는 모든 주요 브라우저에서 지원되는 기능이며, 호환성이 좋다.
2. HTTP 요청 헤더에 쿠키는 자동으로 포함되어 서버는 토큰을 쉽게 인식하고 처리 할 수 있다.
3. 만료 기간을 설정할 수 있어 이를 통해 유효 기간을 제어 할 수 있다.
단점
1. 쿠키는 4KB의 용량 제한되고, 도메인 당 쿠키의 총 개수도 제한되기 때문에 여러개의 쿠키를 사용해야하는 문제가 발생할 수 있다.
2. 모든 HTTP 요청에 자동으로 포함되므로, 불필요한 데이터 전송으로 인해 성능 저하가 발생할 수있다.
3. 최신 브라우저에서는 Same-site가 기본정책이지만 만약 Same-site 설정이 없는 쿠키의 경우 CSRF 공격에 취약할 수 있다.
JWT를 사용해서 기존에 사용하던 Session 방식에 비해 서버에 부담을 줄이고 더 많은 사용자의 트래픽을 효율적으로 감당할 수 있는 방식을 확인했다.
하지만 보안적인 측면에서 session 방식에 비해 XSS, CSRF 공격에 취약하다는 점을 알고 대응해야 하는 점이 있다.
프로젝트의 요구사항이나 보안제한에 따라 저장 방식 또는 Access Token과 Refresh Token을 사용하는 여부를 결정해야 할 것으로 생각된다.