2021-04-11(Sun)

항목

내용

학습 날짜

2021-04-11(일)

학습 시간

09:00~23:00

학습 범위 및 주제

인증, 인가

학습 목표

인증과 인가에 대해서 깊이 파보자.

동료 학습 방법

-

상세 학습 내용

로그인에 대해서 애매한 부분들을 모조리 메꾸겠다는 마음으로 다시 학습을 진행하였고, 아래 내용으로 블로그 글을 작성하였다.

들어가며

로그인이 뭔지 답할 수 있어? - 이호준 멘토님

안녕하세요! 로그인에 대해 궁금해진 카뎃 iwoo입니다.

사실 로그인 자체는 트렌센더스 프로젝트를 하며 팔 수 밖에 없었던 주제이기에 어떤 개념들이 있는지는 알고 있었습니다. 하지만 계속되는 꼬리 질문으로 들어가면 모르는 부분이 존재하더군요. 가령 bcrypt 알고리즘은 레인보우 공격을 막기 위해 솔트를 넣어가며 암호화한다는 것까진 알고 있었지만, 그 솔트가 어떤 식으로 생성되는지는 모르고 있었습니다.

흠 시간 없다고 덮어뒀던 궁금증이 올라오네요, 이 참에 그간 로그인에 대해서 파봤던 내용을 공유합니다!

로그인은 무엇일까?

In computer security, logging in (or logging on, signing in, or signing on) is the process by which an individual gains access to a computer system by identifying and authenticating themselves. - Wikipedia

로그인은 자원에 접근할 수 있는 권한을 획득하기 위해 인증과 인가를 받는 절차입니다. 로그인을 쉽게 접할 수 있는 웹 서비스를 예로 들어봅시다.

웹 서비스는 보통 클라이언트가 서버에 자원을 요청하고, 서버가 적절하게 자원을 응답하는 형태로 운영됩니다. 이 때 클라이언트가 다양하고, 각 클라이언트가 요청할 수 있는 자원이 제각각 다르다면, 서버 입장에서는 자원을 적절하고 유효한 클라이언트에게 전달해야 한다는 이슈가 생깁니다. 이를 위해서 서버는 클라이언트의 자원 요청에 대해 인증과 인가 과정을 거칩니다.

  • 인증(Authentication)

    • 어떤 정보가 어떤 자에게 유일하게 속한다는 사실을 확인하고 이를 증명하는 행위

    • ex) ID, 패스워드 입력, 휴대폰 번호 인증, 이메일 인증, 지문 인증...

  • 인가(Authorization)

    • 인증된 사용자에 대한 자원 접근 권한을 확인하는 과정

    • ex) 신원이 확인된 유저의 보안 레벨이 자원 요청이 가능한지 확인

먼저 인증에 대해 자세히 알아보겠습니다.

다양한 인증 수단들

인증 수단은 다양하지만, 큰 범주로 보면 3가지-지식, 소유, 신체로 분류할 수 있습니다.

  1. 지식

    • 내가 알고 있는 것

    • ID와 패스워드, 어릴 적 별명 등등

    • 분실의 우려는 없지만 '추정 공격'에 취약해서 보안성이 다소 낮은 편에 속함.

  2. 소유

    • 내가 가진 것

    • 인증서, 보안카드, OTP, 휴대폰 인증문자, 인증 메일 등등

    • 보안성이 높지만 분실의 위험이 있음.

  3. 신체

    • 지문, 음성, 홍채, 안면 형태, 심박수 등

    • 보안성이 높고 분실의 위험은 낮지만 저장해 둔 정보가 유출되고 나면 대체하여 인증할 수단이 없다는 단점이 있음.

보통 금전 거래 등 심각한 일이 일어나지 않는 인증에 대해서는 '지식'을 인증수단으로 하여 1차 인증만 하는 경우가 많습니다. 하지만 심각한 일이 일어날 소지가 있다면 2 요소 인증(Two Factor Authentication, 2FA)을 하는 편이 보안상 바람직합니다.

2 요소 인증은 단순히 인증 절차를 2번 거치는게 아닙니다. 서로 다른 분류의 인증 수단을 2가지 이상 거쳤을 때 비로소 2 요소 인증이라고 할 수 있습니다. 예시를 보시죠!

  • ex 1) 아이디와 비밀번호를 검증하고 나서 어릴적 별명을 검증했다면? -> 인증 수단으로 '지식'을 2번 활용했으므로 2 요소 인증이라 할 수 없음.

  • ex 2) 아이디와 비밀번호를 검증하고 나서 휴대폰으로 보낸 SMS 인증번호를 검증했다면? -> '지식'과 '소유'를 차례로 활용했으므로 2 요소 인증이라 할 수 있음.

실제로 제가 진행했던 트렌센던스 프로젝트에서는 아이디/비밀번호 검증 외에 이메일 인증번호 검증을 통해 '2 factor authentication'을 구현했습니다.

HTTP 프로토콜에서 인증 상태를 유지하는 방법은?

인증을 구현해내더라도 웹 서비스에서는 고려해야할 문제가 더 있습니다.

웹 서비스에 주로 쓰이는 HTTP 프로토콜은 기본적으로 요청에 대해 응답을 받으면 연결이 끊어지고(connectionless), 통신이 종료되면 어떠한 상태 정보도 남지 않습니다(stateless). 따라서 따로 처리를 해주지 않으면 서버 입장에서는 자원을 요청한 클라이언트가 이미 인증을 거쳤는지 확인할 방법이 없습니다.

그럼 클라이언트가 매 자원을 요청할 때마다 인증을 반복해야할 수 있고, 이로 인해 1) 클라이언트 입장에서는 핵 귀찮을 수 있고(UX 문제) 2) 서버 입장에서도 과도한 인증을 위해 자원을 써야할 수 있습니다(비효율 문제).

이 문제를 해결하기 위한 수단으로 쿠키와 세션을 사용한 서버 기반 인증방식토큰 기반 인증방식을 고려할 수 있습니다.

  • 쿠키는 웹 브라우저 또는 로컬 디스크에 키-값 형태로 저장되는 작은 데이터 파일입니다.

  • 서버는 Set-Cookie 응답 헤더를 통해 클라이언트 측 브라우저 로컬에 쿠키를 생성하라고 요청할 수 있습니다. (만료기간, 도메인 등 옵션 설정 가능)

  • 쿠키를 인증 상태 유지에 활용할 때는 아래 과정을 거칩니다.

    1. 클라이언트가 로그인하며 인증 정보를 요청 헤더에 담아서 서버에 전달
    2. 서버가 인증된 사용자 정보를 담은 쿠키를 생성하라는 내용을 `Set-Cookie` 응답 헤더에 담아서 응답
    3. 클라이언트는 브라우저에 쿠키를 생성하고, 이후 쿠키가 만료될 때까지 요청 헤더에 쿠키 정보를 넣어서 요청
    4. 서버는 요청 헤더에 포함된 쿠키 정보를 통해 클라이언트 인증 여부 판단
  • 장점

    • 서버 자원을 따로 사용하지 않아서 서버 부하가 상대적으로 적습니다.

  • 단점

    • 쿠키를 저장할 때 암호화를 한다고 하더라도 유의미한 사용자 정보가 클라이언트 측에 저장되므로 보안이 취약합니다.

    • 하나의 도메인 당 20개의 값만 가질 수 있고, 하나의 쿠키 값은 4096 Byte까지만 저장 가능하며, 총 300개까지만 쿠키를 저장할 수 있는 등의 제약사항이 있습니다.

    • 쿠키는 단일 도메인 및 서브 도메인에서만 작동하도록 설계되어 있기 때문에 여러 도메인에서 관리하기 어렵습니다.

세션(Session)

  • 세션은 클라이언트와 웹 서버 간의 네트워크 연결이 지속적으로 유지되고 있는 상태를 뜻합니다.

  • 세션의 만료 시점은 보통 브라우저가 종료될 때까지 입니다.

  • 세션을 인증 상태 유지에 활용할 때는 아래 과정을 거칩니다.

    1. 클라이언트가 로그인하며 인증 정보를 요청 헤더에 담아서 서버에 전달
    2. 서버가 인증된 유저에 고유한 ID 값을 부여하여 세션 저장소에 저장한 후, Session ID를 발행
    3. 서버가 Session ID를 쿠키에 저장하여 클라이언트에 응답
    4. 이후 클라이언트는 요청 헤더에 쿠키를 담아서 자원 요청
    5. 서버는 요청에 포함된 쿠키의 Session ID를 검사하여 인증 여부 판단
  • 세션 저장소는 DB에 저장하기도 하고, REDIS 등 메모리를 사용하기도 합니다.

  • 결국 세션도 쿠키를 사용하지만, 사용자 정보 파일을 브라우저에 저장하는 것이 아니라 서버 측에 저장한다는 측면에서 다릅니다.

  • 장점

    • 쿠키 자체에 유의미한 사용자 정보가 저장되지 않으므로 보안상 이점이 있습니다.

  • 단점

    • 서버 메모리 or DB에 상태 정보를 저장하기 때문에 세션이 많아질 경우 용량이 부족해질 수 있습니다.

    • Session ID를 검증하는 데 일일이 세션 저장소에 접근해야하므로 서버 부하가 커질 수 있습니다.

    • 서버가 여러개가 존재한다면 각 서버가 동일한 세션 저장소를 참조하기 어렵습니다. 매 요청마다 다른 서버가 응답한다면, 세션 저장소에 인증 정보가 없어서 계속 인증을 새로 해야할 수도 있습니다. sticky 세션(같은 서버에 세션을 계속 연결하는 방식)을 사용하여 억지로 해결할 수 있기는 하지만, 번거롭고 비효율이 발생합니다. 결국 서버 확장성(scalability)이 나빠집니다.

    • CORS(Cross-origin Resource Sharing)가 어렵습니다. 세션에서 활용하는 쿠키 역시 단일 도메인 및 서브 도메인에서만 작동하도록 설계되어 있기 때문입니다.

토큰

  • 서버가 사인한 토큰을 이용하여 인증을 수행하는 방식입니다.

  • 토큰을 인증 상태 유지에 활용할 때는 아래 과정을 거칩니다.

    1. 클라이언트가 로그인하며 인증 정보를 요청 헤더에 담아서 서버에 전달

    2. 서버는 사용자를 검증하고, 유효할 경우 토큰을 발급하여 클라이언트에 응답

    3. 클라이언트는 토큰을 저장하고, 서버 요청시 해당 토큰을 요청 헤더에 담아서 서버에 전달

    4. 서버는 토큰을 검증하여 인증 여부 판단

  • 장점

    • 서버는 전달받은 토큰을 검증만 하면 되기 때문에 서버의 부담이 줄어듭니다.

    • CSRF(Cross-Site Request Forgery)를 방지합니다.

    • 따로 쿠키 매니저를 둘 필요가 없기 때문에 모바일 애플리케이션에서 사용하기 편리합니다.

    • CORS가 용이합니다. 토큰 기반 인증에서는 토큰만 유효하다면 어디서든 작동할 수 있기 때문입니다.

  • 단점

    • stateless한 토큰의 특성 때문에 토큰을 강제로 만료시킬 수 없습니다. 그래서 토큰이 공격자에게 탈취되었다면, 공격자는 토큰이 만료될 때까지 서버에 요청을 할 수 있습니다.

참고

학습 내용에 대한 개인적인 총평

갑자기 다음 주 금요일에 라이브코딩을 하게 되어.. 마음이 부산스럽긴 한데, 매일 하던 공부는 쭉 이어서 잘해나가야겠다.

로그인에 대해서 트렌센던스 프로젝트에서 다뤘던 부분은 잘 기억하고 있지만, 안 다뤘던 부분은 구멍이 뚤린 것을 느꼈다. 이 참에 제대로 학습해서 메꿔버려야겠다.

다음 학습 계획

  • Rails로 로그인 기능 구현하기

Last updated