프론트엔드 CS - 토큰기반 인증방식

김서영·2024년 7월 24일
0

프론트엔드 CS

목록 보기
8/11

토큰기반 인증방식


쿠키-세션 방식의 단점을 해결하기 위한 방법으로 사용한다.

토큰 기반 인증의 작동 원리

  1. 로그인 요청: 사용자가 로그인 폼을 제출하여 서버에 로그인 요청을 보낸다.
  2. 토큰 발급: 서버는 사용자의 자격 증명을 확인하고, 확인되면 JWT(JSON Web Token)를 생성하여 클라이언트에 반환한다.
  3. 토큰 저장: 클라이언트는 서버로부터 받은 토큰을 로컬 스토리지 또는 쿠키에 저장한다.
  4. 인증된 요청: 클라이언트는 보호된 리소스에 접근할 때 토큰을 HTTP 헤더에 포함하여 서버에 요청을 보낸다.
  5. 토큰 검증: 서버는 요청에 포함된 토큰을 검증하고, 유효한 경우 요청을 처리한다.

JWT(JSON Web Token)

토큰이란, 로그인 이후 서버가 만들어서 사용자에게 넘겨주는 문자열
이 문자열은 사용자 정보가 암호화 되어있고, 이 토큰을 이용해 인증된 사용자인지 서버가 판단한다.
이 때 사용되는 토큰이 JWT이고 하나의 표준 인증 방식이다!

JWT는 세 파트로 나눠지며 각 파트는 순서대로 header, payload, Signature 으로 구성된다.

JWT 구조

1. header(헤더)

토큰의 타입과 해싱 알고리즘의 정보 이렇게 2가지 정보가 담겨 있다.
typ: 토큰의 타입을 지정한다.-> JWT
alg: 해싱 알고리즘을 지정한다. 보통 HMAC-SHA256 혹은 RSA 가 사용되며, 이 알고리즘은 토큰을 검증 할 때 사용되는 signature 부분에서 사용된다.

2. payload(페이로드)

토큰의 내용물이 인코딩된 부분
즉, 토큰에 담을 사용자의 정보가 들어 있는 부분이다.
여기에 담는 정보의 한 ‘조각’ 을 클레임(Claim) 이라고 부르고, 이는 Json(Key/Value) 형태의 한 쌍으로 이뤄져있다.
토큰에는 여러개의 클레임들을 넣을 수 있다.

1. registered claim

  • "iss"(issuer) : 토큰 발급자
  • "sub"(subject) : 토큰 제목(주로 유저 식별자 등)
  • "aud"(audience) : 토큰 대상자
  • "exp"(expiration time) : 토큰 만료 시간
  • "nbf"(not before) : 토큰 활성화 시간
  • "iat"(issued at) : 토큰 발급 시간
  • "jti"(JWT ID) : JWT 고유 식별자

2. public claim

공개용으로 사용하기 위한 claim으로 특정 프로젝트나 조직에서 사용하는 claim을 자유롭게 정의해서 사용할 수 있다.

3. private claim

JWT를 사용하는 개발자나 프로젝트에서만 사용되는 claim을 정의해서 사용할 수 있다.
이를 위해 claim 이름 앞에 일반적으로 발행자(issuer)의 도메인 이름을 추가해 claim 충돌을 방지하는 것이 좋다.

단, Payload는 암호화되지 않기때문에 민감한 정보를 포함하면 안된다.

3. Signature(서명)

토큰을 인코딩하거나 유효성 검증을 할 때 사용하는 고유한 암호화 코드이다.
헤더(Header)와 내용(Payload)의 값을 각각 BASE64로 인코딩하고, 인코딩한 값을 비밀키를 이용해 헤더에서 정의한 알고리즘으로 해싱을 하고, 이 값을 다시 BASE64로 인코딩하여 생성한다.
secret key로 사용되는 일련의 문자열으로, 이를 통해 JWT의 위변조 여부를 확인한다.

보안 고려사항

  1. HTTPS 사용: 모든 통신을 HTTPS로 보호해야 한다.
  2. 토큰 만료: 토큰에 만료 시간을 설정하여 보안을 강화하면 좋다.
  3. 리프레시 토큰: 액세스 토큰이 만료된 경우 새로운 토큰을 발급받기 위해 리프레시 토큰을 사용한다.
  4. XSS 방어: 토큰을 안전하게 저장하고 XSS 공격에 대비해야 한다. 이를 위해 HttpOnly 쿠키를 사용할 수 있다.
  5. 토큰 검증: 서버에서 항상 토큰의 서명을 검증하고, 필요한 경우 클레임을 확인한다.

JWT 토큰을 쿠키에 저장했을 때 취약점

1. XSS(교차 사이트 스크립팅) 공격

- 취약점

  • 쿠키 탈취: 악의적인 스크립트가 실행될 경우, 쿠키에 저장된 JWT 토큰이 탈취될 수 있다. 이는 쿠키의 HttpOnly 속성을 설정하지 않으면 더 쉽게 발생할 수 있다.

- 대응 방법

  • HttpOnly 속성 사용: 쿠키에 저장할 때 HttpOnly 속성을 설정하면 JavaScript로 쿠키에 접근할 수 없다.

    Set-Cookie: token=your_jwt_token; HttpOnly

  • Content Security Policy(CSP): CSP를 설정하여 악의적인 스크립트가 실행되지 않도록 한다.

  • 입력 검증 및 인코딩: 사용자 입력을 철저히 검증하고, HTML 인코딩을 통해 XSS를 방지한다.

2. CSRF(교차 사이트 요청 위조) 공격

- 취약점

  • 자동 전송: 쿠키는 같은 도메인에서 자동으로 전송되므로, 악의적인 웹사이트에서 요청을 보낼 때 쿠키가 자동으로 포함되어 공격에 노출될 수 있다.

- 대응 방법

  • CSRF 토큰 사용: CSRF 토큰을 사용하여 요청을 검증한다. 서버는 각 요청에 대해 유효한 CSRF 토큰을 확인해야 한다.
  • SameSite 속성 설정: 쿠키의 SameSite 속성을 Strict 또는 Lax로 설정하여 CSRF 공격을 방지한다.

    Set-Cookie: token=your_jwt_token; SameSite=Strict

3. 쿠키 도난

- 취약점

  • 클라이언트 측 도난: 사용자가 공유 컴퓨터를 사용하거나 쿠키를 적절히 보호하지 않으면, 다른 사용자가 쿠키에 접근할 수 있다.

- 대응 방법

  • Secure 속성 사용: HTTPS를 통해서만 쿠키가 전송되도록 Secure 속성을 설정한다.

    Set-Cookie: token=your_jwt_token; Secure

  • 쿠키 만료 시간 설정: 쿠키의 유효 기간을 설정하여 만료 시간을 짧게 유지한다.

    Set-Cookie: token=your_jwt_token; Max-Age=3600

4. 토큰 탈취 후 재사용

- 취약점

  • 탈취된 토큰 재사용: 탈취된 JWT 토큰이 만료되기 전까지 유효하므로, 이를 재사용하여 악의적인 요청을 보낼 수 있다.

- 대응 방법

  • 짧은 만료 시간: JWT 토큰의 만료 시간을 짧게 설정하고, 리프레시 토큰을 사용하여 새 토큰을 발급받도록 한다.

    const token = jwt.sign({ email }, secretKey, { expiresIn: '15m' });

  • 로그인 세션 관리: 서버 측에서 사용자 세션을 관리하고, 의심스러운 활동이 감지되면 세션을 무효화한다.

5. 로그아웃 처리 문제

- 취약점

  • 쿠키 삭제 어려움: 쿠키를 삭제하지 않으면 사용자가 로그아웃 후에도 토큰이 유효하게 남아 있을 수 있다.

- 대응 방법

  • 쿠키 삭제: 로그아웃 시 클라이언트에서 쿠키를 삭제한다.

    document.cookie = "token=; Max-Age=0; path=/; domain=yourdomain.com;";

profile
개발과 지식의 성장을 즐기는 개발자

0개의 댓글