ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Toy Project 기록하기 5] 세션 인증 방식 vs 토큰 인증 방식
    Frontend/Projects 2023. 3. 9. 23:08

    HTTP는 stateless한 특성을 가지고 있어 서버는 클라이언트의 상태를 저장하지 않습니다. 유저가 로그인을 했더라도 다음 통신에서 클라이언트의 상태를 기억하지 못해 매번 다시 로그인을 요청하는 사태가 발생하게 됩니다. 이러한 문제를 방지하기 위해 서버에서 유저를 인증(유저가 로그인을 시도할 때 서버에서 일치하는 유저 정보를 찾으면 이를 확인하기 위해 토큰이나 세션을 발급해 주는 것)하고 인가(클라이언트에서 해당 토큰이나 세션을 받아 가지고 있다가 새로운 요청 시 인가를 위해 토큰이나 세션을 보내는 것)하기 위해 사용되는 것이 세션과 토큰입니다. 오늘은 두 방식의 특징에 대해 알아보겠습니다. 

     

     


    세션 인증 방식

    세션 인증 방식은 유저의 인증 정보를 서버의 세션 저장소에 저장합니다. 

     

    1. 클라이언트가 로그인 요청을 보낸다.
    2. 해당 인증 정보를 서버에서 확인하여 서버의 세션 저장소에 저장하고, 유저에게는 저장된 세션 정보의 식별자인 Session ID를 발급한다.
    3. 서버에서 Session ID를 받아 브라우저에 쿠키 형태로 저장되며 이후 클라이언트가 요청을 보낼 때 마다 HTTP Cookie 헤더에 Session ID를 담아 서버로 전송한다.
    4. 서버는 요청을 전달받고, Session ID에 해당하는 세션 정보가 세션 저장소에 확인해 인증 상태를 판단한다.
    5. 인증이 완료되고 서버는 유저에 맞는 데이터를 보내준다.

     

    특징

      - Server-Side Rendering으로 처리되는 웹서비스들에서 많이 쓰이는 방법이며 주로 여러 페이지로 구성하는 대규모 시스템에서 사용됩니다.

      - 서버에서 세션 정보를 관리하기 때문에 보안 측면에서 토큰 인증 방식보다 유리합니다. Session ID가 탈취되더라도 무효화 처리를 할 수 있습니다.

      - 메모리에 저장된 세션 정보는 휘발성이기에 서버 재부팅시 사라질 수 있으며 많은 정보를 저장하는데 한계가 있습니다. 하드디스크나 DB에 저장하기에는 작업이 느리고 무겁다는 단점이 있습니다.

     

     

    토큰 인증 방식(JWT)

    JWT(Json Web Token)는 인증에 필요한 정보들을 암호화시킨 JSON 토큰 의미합니다. 

    기본적으로 header, payload, signature로 구성됩니다.

    header: 토큰 타입이나 사용중인 signature 알고리즘 
    payload: 서버에서 보낼 데이터로 토큰에서 사용할 정보가 담겨있음
    signature: 헤더에 정의한 알고리즘 방식을 활용해 header + payload와 서버의 개인키를 합쳐 암호화

     

    토큰 인증 방식은 사용자의 인증 정보를 클라이언트가 토큰으로 직접 가지고 있습니다.

     

    1. 클라이언트가 로그인 요청을 보낸다.
    2. 유저가 인증에 성공하면 서버는 Access Token을 생성해 클라이언트에 보낸다.
    3. 클라이언트가 요청을 보낼 때마다 토큰을 HTTP의 헤더에 함께 실어 보낸다.
    4. signature로 토큰의 내용이 위변조 되었는지 서버 측에서 확인할 수 있다.
    5. 서버에서는 토큰이 유효한지 확인해 유저에게 맞는 데이터를 보낸다.

     

    특징

      - Single Page Application에서 많이 쓰는 방법입니다.

      - 클라이언트가 토큰을 직접 가지고 있기 때문에 유저의 수가 많아져도 서버의 부담이 증가하지 않습니다.

      - 토큰 정보가 탈취되면 토큰이 만료되기 전까지 무효화 처리를 할 수 없습니다.

    ➡️ 기존 발급된 Access Token의 유효기간을 짧게 하고 Refresh Token을 새로 발급합니다. 그렇게 되면 토큰 정보가 탈취되더라도 피해를 줄일 수 있습니다.

     

    Access Token & Refresh Token

    Access Token 인증 방식은 토큰 정보를 탈취당할 경우 보안에 취약하기 때문에 이를 보완하기 위해 나온 것이 Refresh Token입니다. Refresh Token은 Access Token과 똑같은 형태의 JWT인데 각각의 역할이 다릅니다.

     

    Access Token은 탈취당하면 정보가 유출되는 건 동일합니다. 다만 안전성을 높이기 위해 유효기간이 짧게 두어 자주 발급 받게 합니다.

    Refresh Token은 Access Token이 만료됐을 때 재발급을 받기 위한 인증용 토큰입니다. 유효기간이 끝나면 다시 로그인해야 합니다.

     

     

    1. 클라이언트가 로그인 요청을 보낸다.
    2. 서버는 db에서 유저를 확인하고 인증되면 Access Token, Refresh Token을 발급하고 Refresh Token은 db에 저장한다.
    3. 서버는 클라이언트에게 Access Token, Refresh Token을 보낸다.
    4. 클라이언트는 Refresh Token을 안전한 곳에 저장 후 Access Token을 헤더에 실어 요청을 보낸다.
    5. 시간이 지나고 Access Token이 만료되면
    6. 클라이언트는 이전처럼 Access Token을 헤더에 실어 요청을 보낸다.
    7. 서버는 Access Token이 만료됨을 확인하고 권한 없음을 보낸다.
    8. 클라이언트는 Refresh Token과 Access Token을 함께 서버로 보낸다.
    9. 서버는 받은 Access Token을 확인한 후, Refresh Token과 사용자의 db에 저장되어 있던 Refresh Token을 비교한다.
    10. 서버는 Token이 동일하고 유효기간도 지나지 않았다면 새로운 Access Token을 사용자에게 보내준다.
    11. 새로운 Access Token을 헤더에 실어 API 요청을 한다.

     

    특징

      - header와 payload로 signature를 생성하기 때문에 데이터 위변조를 막을 수 있습니다.

      - 인증 정보에 대해 세션 저장소와 같은 별도의 저장소가 필요하지 않습니다.

      - 서버가 stateless 상태를 유지할 수 있어 서버 확장성이 세션 인증 방식에 비해 유리합니다.

      - 토큰의 길이가 늘어날수록 네트워크에 부하를 줄 수 있습니다.

      - payload에는 base64로 인코딩 되어 디코딩하면 누구나 데이터가 볼 수 있기 때문에 중요한 데이터를 넣을 수 없습니다.

      - 인증 정보를 OAuth 등 다른 어플리케이션으로 쉽게 전달할 수 있습니다.  

      - 모바일 어플리케이션 환경에서도 잘 동작합니다.

     

    고려해야 할 보안 이슈

    Access Token, Refresh Token 인증 방식을 사용할 때 서버가 클라이언트에게 토큰을 전달하는 방식에 따라 보안 이슈가 발생할 수 있습니다. 발생할 수 있는 보안 이슈와 적절한 토큰 저장 방식에 대해 알아보겠습니다.

     

    XSS(Cross-Site-Scripting) 공격

    공격자가 script가 삽입될 수 있는 취약한 사이트에 script를 삽입해 실행하는 공격입니다. 보통 의도치 않은 행동을 수행시키거나 쿠키나 세션 토큰 등의 민감한 정보를 탈취합니다. 그래서 공격자가 사용자의 정보를 이용해 사용자인 척 행동할 수 있습니다.

     

    Refresh Token와 Access Token을 함께 쿠키에 저장하면 XSS 공격 노출 시 공격자가 사용자인 척 API를 호출할 수 있습니다. 이를 방지하기 위해 Access Token은 JSON payload에서 따로 받아오는 것이 좋으며, httpOnly 쿠키 방식으로 저장된 정보는 XSS 공격으로 접근할 수는 없지만 여전히 API 요청 시 함께 보낼 수 있기 때문에 추가적인 방어가 필요합니다.

     

    CSRF(Cross-Site-Request-Forgery) 공격

    신뢰할 수 있는 사이트에서 사용자 인증이 되었을 때 사용자의 브라우저가 공격자가 의도한 행위(수정, 삭제, 등록 등)를 수행하게 하는 공격입니다. 사용자가 로그인한 상태에서 CSRF 공격 코드가 삽입된 페이지를 열면 공격 대상이 되는 웹사이트는 신뢰할 수 있는 사용자로부터 온 요청이라고 판단하여 공격에 노출되게 됩니다.  

     

    XSS 공격이 사용자가 특정 사이트를 신뢰하는 점을 노렸다면, CSRF 공격은 특정 사이트가 사용자의 브라우저를 신뢰하는 점을 노린 것입니다.

     

    httpOnly 쿠키 방식으로 Refresh Token만 저장하고 AccessToken을 JSON payload에서 받아오는 구조로 CSRF 공격을 방어할 수 있습니다. 

     

    ✅ 결론적으로 Refresh Token secure httpOnly 쿠키로, Access Token JSON payload로 받아옵니다.

     

     

    🧗‍♀️ 제가 진행한 프로젝트가 궁금하다면

    🔽 프론트엔드는 이곳에서 확인하실 수 있습니다.

    https://github.com/Team-Madstone/doljabee-fe

     

    GitHub - Team-Madstone/doljabee-fe: Climbing Community

    Climbing Community. Contribute to Team-Madstone/doljabee-fe development by creating an account on GitHub.

    github.com

     

    🔽 백엔드는 이곳에서 확인하실 수 있습니다.

    https://github.com/Team-Madstone/doljabee-be

     

    GitHub - Team-Madstone/doljabee-be: Climbing Community

    Climbing Community. Contribute to Team-Madstone/doljabee-be development by creating an account on GitHub.

    github.com

     

     

    참고 자료

    https://fierycoding.tistory.com/69

    https://brunch.co.kr/@jinyoungchoi95/1

     

    반응형

    댓글

Designed by Tistory.