보안 및 권한 부여 방식 이해

Mixer·2023년 11월 21일
0

소프트웨어 보안이란?

소프트웨어 보안은 공격에 맞서 기능을 유지할 수 있도록 보안 구조에 메커니즘을 구현하는 개념이다.
이는 소프트웨어가 시장에 출시되기 전에 소프트웨어 보안 테스트를 거쳐 악성 공격을 견딜 수 있는 성능을 확인하는것을 뜻한다.

또한 소프트웨어 보안의 취지는 보안 요소를 추가해 추가 보안층을 확보할 필요 없이 처음부터 안전한 소프트웨어를 구축하는 것인데 다음 단계로는 소프트웨어가 공격에 취약하거나 노출되지 않도록 올바른 사용 방법을 사용자에게 교육하는 것이다.

소프트웨어 보안이 매우 중요한 이유는 악성 코드로부터 공격이 무결성과 인증, 가용성을 훼손하는 동시에 소프트웨어의 모든 부분에 심각한 손상을 줄 수 있기 때문이다.
프로그래머가 프로그래밍 이후가 아닌 프로그래밍 단계에서 이를 고려해 개발한다면 이런 피해를 미리 방지할 수 있다.

IT 보안의 4가지 유형

IT 보안은 특정 개체의 모든 데이터를 전자적 물리적인 측면에서 보호하는 프로세이이다.

  • 네트워크 보안: 동일한 네트워크에 있는 여러 장치 간의 보안이며, 이 경우엔 소프트웨어 보안과 하드웨어 보안 두가지 모두가 중요하고 또한 네트워크를 보호하고자 하는 기업은 네트워크가 악의적으로 사용되지 않도록 주의해야한다.

  • 엔드포인트 보안: 엔드포인트 보안은 사용되는 장치에 중점을 둔 보안으로, 원치않는 사용자가 몰래 침입하는 것을 방지하기 위해 노트북이나 전화, 컴퓨터, 태블릿 등을 안전하게 만들며, 여기에는 다양한 암호화, 사용자 제어, 소프트웨어 보안 방법이 포함되는 경우가 많다.

  • 인터넷 보안: 보통 사이버 보안으로 알려져 있으며 정보의 전송과 사용을 다룬다.
    정보를 가로챌 때 사이버 보안 공격이 발생하는 것이므로 보통 다양한 암호화 기능과 인증 계층을 사용해 이런 공격을 차단한다.

  • 클라우드 보안: 클라우드 보안은 클라우드 상에서 소프트웨어 보안 위험을 낮추는데 중점을 두고있으며, 일부 클라우드 보안 개념은 동일한 네트워크에 있는 데이터 전송과 장치를 보호해야 한다는 점에서 위에 나열된 다른 형태의 보안과 중복된다.

시큐어 코딩, Secure Cording

시큐어 코딩은 사이버 공격에 대한 방어뿐만 아닌 개발자의 실수나 코드상의 논리적 오류로 인해 발생할 수 있는 문제점을 사전에 차단 및 대응하는 내용도 포함된다.
소프트웨어의 가용성과 신뢰성이 위협받는 취약점은 모두 보안의 대상으로 정의 한 것이다.
정보 보호가 소프트웨어 개발의 중요한 주제인 만큼 시큐어 코딩은 선택이 아닌 필수요소가 되었다.

소프트웨어 보안 취약점은 다음과 같은 경우에 자주 발생한다
1. 소프트웨어 요구 사항 정의 시에 아예 보안 요구사항을 고려하지 않았다.
2. 소프트웨어가 논리적인 오류를 포함한 채로 설계되고 개발되었다.
3. 기술적 취약점을 보완하지 않은 코딩 규칙을 적용해 코딩했다.
4. 발견된 취약점에 대해 적절한 관리 또는 패치를 제때 수행하지 않았다.


웹 인증/보안

Https

HTTP
HTTP(Hypertext Transfer Protocol)는 클라이언트와 서버 간 통신을 위한 통신 규칙 세트 또는 프로토콜

HTTPS
HTTPS(Hypertext Transfer Protocol Secure)는 HTTP의 확장 버전 또는 더 안전한 버전이며, HTTPS에서는 브라우저와 서버가 데이터를 전송하기 전에 안전하고 암호화된 연결을 설정합니다.

왜 HTTPS가 HTTP보다 안전한가?

HTTPS는 HTTP와 다르게 443번 포트를 사용하며, 네트워크 상에서 중간에 제 3자가 정보를 볼 수 없도록 암호화를 지원하고 있다.
HTTPS는 어플리케이션 계층과 전송 계층 사이에 신뢰계층인 SSI/TLS 계층을 넣어 신뢰할 수 있는 HTTP 요청을 말하며 이를 통해 '통신을 암호화' 한다.

HTTPS 전송

반면, HTTPS는 HTTP와 달리 SSL(Secure Sockets Layer)나 TLS(Transport Layer Security) 프로토콜을 사용하여 데이터를 암호화하여 전송한다. 이를 통해, 해커가 데이터를 가로채도 암호화된 상태로만 볼 수 있으며 데이터의 무결성을 보장할 수 있고 또한 HTTP와 달리 CA에서 발급하는 인증서를 통해 사용자가 HTTPS로 인터넷에서 민감한 정보를 주고받는 경우에 적합하다고 볼 수 있다.

암호화/복호화


SSL/TLS

  • 보안 소켓 계층 SSL, Secure Sockets Layer
    SSL은 웹서버와 웹 브라우저 간의 (또는 두 서버사이) 전송되는 데이터를 암호화하여 인터넷 연결을 보호하기 위한 표준 기술이다.
    이 기술은 해커가 개인 데이터나 금융 데이트 등의 전송되는 정보를 보거나 훔치는 것을 방지한다.

    - 공개 키 암호화
    	+ 대칭키 방식
        해시 테이블처럼 키가 있어야 암호화 할 수 있다
        암호화할 때 1234라는 암호로 키를 사용했다면 1234가 있어야 복호화 할 수 있다.
        + 대칭키를 공유할 때 위험이 노출되기 때문에 매우 위험하다
        
        비대칭 키 방식
        공개키(public key)와 개인키(private key)를 가지며
        공개키로 암호화 하는 경우와 개인키로 암호화 하는것을 구분한다
        암호화할 때의 키와 복호화할 때의 키 값이 다르면 비대칭키 라고 한다.
  • 전송 계층 보안 TLS, Trapsort Layer Security
    TLS는 SSL의 향상된 더욱 안전한 버전이며, SSL이 더욱 일반적인 용어이기 때문에 DigiCert는 보안 인증서를 여전히 SSL로 언급하고 있지만 DigiCert에서 SSL을 구입하면 가장 신뢰할 수 있는 최신 TLS 인증서를 얻을 수 있다.

    - TLS와 SSL은 내부 알고리즘 다른 것을 사용하지만 동작 방식은 같다.
    
    1. 클라이언트가 서버에 TLS 연결을 요청한다.
    2. 서버는 인증서를 클라이언트에게 보낸다.
    3. 클라이언트는 이 이늦ㅇ서를 검증하여 서버가 신뢰할 수 있는 서버인지 확인
    4. 클라이언트와 서버는 대칭 키를 생성
    5. 클라이언트는 이 대칭키를 서버의 공개키로 암호화하여 보낸다
    6. 서버는 자신의 비밀키를 사용해 이 대칭키를 복호화한다.
    7. 클라이언트와 서버는 이 대칭키를 사용해 데이터를 암호화 및 복호화한다

출처 https://velog.io/@kwontae1313/HTTP%EB%B3%B4%EB%8B%A4-HTTPS%EA%B0%80-%EC%99%9C-%EB%8D%94-%EC%95%88%EC%A0%84%ED%95%A0%EA%B9%8C

인증서

  • 데이터 제공자 신원 보장
    데이터를 제공한 서버가 진짜로 데이터를 보내준 서버인지 인증, 확인하는 용도

  • 도메인 종속
    인증서에는 서버의 도메인 관련 정보가 있어서 데이터 제공자의 인증을 용이하게 한다

브라우저는 서버가 전송한 '응답 + '전달받은 인증서'를 확인할 수 있다.
클라이언트는 인증서에 작성된 도메인과 응답 객체에 작성된 도메인을 비교하며 응답에서 확인한 도메인과 인증서에 작성된 도메인이 같지 않은 경우에 클라이언트는 서버 제공자가 아닌 전혀 다른 데이터 제공자임을 알 수 있다.

출처 https://velog.io/@mmmdo21/7.Backend-%EC%9D%B8%EC%A6%9D-%EB%B3%B4%EC%95%88

⚙️ 인증서는 서버의 신원을 보증하여 클라이언트가 접속한 사이트가 해커가 정교하게 만든 가짜 사이트가 아님을 보장해주는 역할을 하고 있다.

CA

CA는 인증서를 발급해주는 공인된 기관을 뜻한다

  • 보증을 할 수 있는 제 3자를 Certificate Authority, CA
  • 각 브라우저는 신뢰할 수 있는 CA의 정보를 가지고 있기때문에 각 브라우저가 가지고 있는 인증서는 다르다
  • CA들은 서버의 공개키와 정보를 CA의 비밀키로 암호화하여 인증서를 발급한다

서버가 클라이언트에게 CA에서 발급받은 인증서를 전달하면 클라이언트는 OS 또는 브라우저에 미리 내장되어 있던 CA 리스트를 통해 브라우저에서 인증된 CA에게 발급받은 인증서인지 먼저 확인
만약 인증된 CA에서 발급된 인증서가 아니라면 위 이미지처럼 서버와 연결이 안전하지 않다는 메세지가 나온다.


Hashing

암호화, Encyrption

암호화는 일련의 정보를 임의의 방식을 사용해 다른 형태로 변환하여 해당 방식에 대한 정보를 소유한 사람을 제외하곤 이해할 수 없도록 알고리즘을 이용해 정보를 관리하는 과정이다.

Hashing

'해싱'은 각 사용자의 일반 텍스트 암호를 가져와 단방향 수학 함수를 통해 암호화를 실행하는 것이다.
이때 '해시'라고 하는 고유한 숫자 및 문자 문자열이 생성된다.
정리하면, '해싱'은 암호화를 실행하는 행위이자 방법이고, '해시'는 비밀번호라고 생각하면 쉽다.

해시 알고리즘 규칙

  1. 모든 값에 해싱 값을 계산하는데 오래 걸리지 말아야 한다.
  2. 모든 값은 고유한 해싱 값을 가진다.
  3. 아주 작은 단위의 변경이라도 완전히 다른 해쉬 값을 가져야 한다.

Case1. DB에 password가 그대로 저장된 경우
1. 서버가 클라이언트로부터 이메일 주소, 패스워드를 받는다.
2. 서버는 DB에 이메일, 패스워드를 요청하고 받은 후, 클라이언트로부터 받은 정보와 비교한다
3. 일치하면 DB에 다시 해당하는 이메일 주소의 관련 정보를 요청해서 클라이언트에게 반환한다
-> 이메일 주소는 공개되어도 되지만, 패스워드는 조심해야한다, 해커가 DB에 접근해 유저의 비밀번호를 알아내어버리면 대부분의 유저는 비밀번호 하나로 여러 사이트를 사용하기 때문이다
또한 비밀번호를 데이터베이스에 그대로 저장하면 누구든 볼 수 있기때문에 (*서버에 접근할 수 있는 어드민, 직원)

Case2. DB에 간단한 알고리즘으로 암호화된 패스워드를 저장할 경우
1. 서버가 클라이언트로부터 이메일 주소, 패스워드를 받는다.
2. 서버는 DB에 이메일, 암호화 알고리즘으로 '암호화'된 패스워드를 요청하고 받는다.
3. 서버는 가지고 있던 암호화 알고리즘으로 클라이언트로부터 받은 패스워드를 암호화하여, DB로부터 받은 암호화된 패스워드와 비교한다.
4. 일치하면 DB에 다시 해당 이메일 주소의 관련 정보를 요청해 클라이언트에게 반환해준다.
-> DB에는 비밀번호를 그대로 저장하여 노출 시키는 것이 아닌, 알고리즘으로 암호화된 문자열을 저장해둔다.
해커가 DB에 접근해 유저의 비밀번호를 빼내어도 알고리즘을 모르기 때문에 원래의 비밀번호를 알아낼 수 없다.

Salt

암호화해야 하는 값에 어떤 '별도의 값'을 추가해 결과를 변형하는 것

한차례 더 안전장치를 만들어서 사용하여 '은어'로 소금 친다라는 표현

1차적으로 해싱된 암호문에 소금을 쳐서 암호문을 한번 더 비꼬아 저장하는 것으로
위와 같이 회원 DB에는 Salt 값을 저장할 Attribute가 추가 되었다 물론 salt는 다른 곳에 보관하는 것을 추천한다.

솔트는 길면 길수록 좋다. 그리고 간혹 Salt를 하드코딩하여 전체 회원에게 동일하게 적용하는 경우는 무용지물
회원별로 별도의 난수를 생성해서 각기 다른 Salt를 저장해서 사용하는 것이 좋다.

이렇게 해두면 해커가 DB까지 털어간다 하더라도 회원들의 비밀번호가 안전하게 보호된다
기본적으로 회원들의 비밀번호가 지나치게 간결하면 궁극적으로는 보안에 취약할 수 밖에 없으니,
회원 가입을 받을 때 최소 자릿수 이상으로 가입을 받고 특수 문자 등을 섞어서 받기를 권장한다.


Cookie

쿠키는 웹 사이트가 사용자 정보를 저장하기 위해서, 사용자의 PC나 스마트폰, 태블릿과 같은 디바이스에 저장하는 파일을 의미한다.
커머스를 예로 들자면, 사이트에서 어떤 사용자가 어떤 상품을 장바구니에 담았는지 저장하고 유지하기 위해, 쿠키로써 휴대폰에 데이터를 저장하고, 다음번 방문하더라도 장바구니에 담긴 상품이 그대로 저장되어 있다.
이렇게 쿠키는 웹 데이터 분석 외에도 커머스의 장바구니 정보는 물론, ID 와 비밀번호 정보를 쉽게 입력하기 위해 혹은 특정 사용자에게는 배너 광고를 타게팅하기 위해서도 저장한다.

쿠키를 세분화하면 두 가지로 구분된다.

  • 퍼스트파티 쿠키: 웹사이트 속성이 호스트메인 일 경우 해당하는데, 현재 방문하는 도메인에 설정된 쿠키를 의미한다, 커머스의 장바구니에 담긴 정보를 저장하기 위한 쿠키이기도 하며 보통 광고나 웹로그 분석 툴의 경우 서드파티 쿠키를 이용하는 경우가 대다수지만, 예외적으로 구글 애널리틱스와 뷰저블은 퍼스트파티 쿠키를 사용한다.

  • 서드파티 쿠키: 방문한 도메인 외, 즉 외부업체가 심는 쿠키이다.
    서드파티 쿠키는 애드테크 회사들이 사이트를 넘나들면서 사용자 행동을 추적할 수 있는 기반 인프라로, 사용자가 쇼핑몰 사이트를 방문하고 나서 신문사 사이트에 들어갔을 때 쇼핑몰에서 했던 행동들을 기반해 신문사 사이트에서 거기에 맞는 광고를 보여줄 수 있다.

쿠키 전달 방법

쿠키가 클라이언트에 저장되고, 자동으로 요청된다.

  1. 서버가 응답헤더에 Set-Cookie 라는 프로퍼티에 쿠키의 이름, 값, 경로 등의 옵션을 저장
  2. 쿠키가 담긴 응답을 받은 클라이언트는 응답헤더에 존재하는 Set-Cookie를 확인
  3. 매 요청 시 마다 쿠키의 이름과 값을 서버에게 전달하게 된다
    -> 서버가 쿠키를 저장하면, 이후로는 해당 웹사이트를 방문할 때, 내 요청에 자동으로 쿠키가 항상 함께 전송
    -> 서버는 받은 쿠키 내용을 바탕으로 로그인 유지 등을 한다

쿠키 이용법

서버는 쿠키를 이용하여 데이터를 클라이언트에 저장하고 이 데이터를 다시 불러오 사용할 수 있다.

  • 하지만 데이터를 저장한 이후 아무때나 데이터를 가져올 순 없다, 데이터를 저장한 이후 특정 조건들이 만족되어야 다시 가져올 수 있기 때문이다.
'Set-Cookie': [
			   'cookie=good',
               'Secure=Secure; Secure',
               'HttpOnly=HttpOnly; HttpOnly',
               'Path=Path; Path=/cookie',
               'Domain=Domain; Domain=velog.io'
              ]

쿠키 옵션

  1. Domain

도메인은 흔히 알고 사용하는 www.google.com 과 같은 서버에 접속할 수 있는 이름
쿠키 옵션에서 도메인은 포트 및 서브 도메인 정보, 세부 경로를 포함하지 않는다.

따라서 요청해야할 URL이 http://www.localhost.com:3000/users/login 이라 하면 이곳에서 Domain은 localhost.com 이 된다.

만약 쿠키 옵션에 도메인 정보가 존재한다면 클라이언트에서는 쿠키의 도메인 옵션과 서버의 도메인이 일치해야만 쿠키를 전송할 수 있다. 이를 통해 naver.com에서 받은 쿠키를 google.com에 전송하는 일을 막을 수 있다.

💡 서브도메인이란?
www 같은 도메인 앞에 추가로 작성되는 부분을 말한다.

  1. Path

Path는 세부 경로로서 서버가 라우팅할 때 사용하는 경로를 의미한다.
http://www.localhost.com:3000/users/login 인 경우 여기에서 path, 즉 세부 경로는 /user/login이 된다.
이를 명시하지 않으면 기본적으로 / 으로 설정되어 있다.

Path 옵션의 특징은 설정된 경로를 포함하는 하위 경로로 요청을 하더라도 쿠키를 서버에 전송할 수 있다.
Path가 /users 로 설정되어 있고, 요청하는 세부 경로가 /users/velog인 경우라면 쿠키 전송이 가능하다.

하지만 /posts/velog 로 전송되는 요청은 path 옵션(/users)를 만족하지 못하기 때문에 서버로 쿠키를 전송할 수 없다.

  1. MaxAge or Expires
    쿠키가 유효한 기간을 정하는 옵션으로, 만약 쿠키가 영원히 남아있다면 그만큼 탈취 되기도 쉬워지기 때문에 이런 유효기간을 설정하는 것이 보안 측면에서 중요하다.

MaxAge는 쿠키가 유효한 시간을 초 단위로 설정하는 옵션이며

Expries 는 언제까지 쿠키가 유효한지 심판의 날을 지정할 수 있다.
이때 옵션의 값은 클라이언트의 시간을 기준으로 하며, 이후 지정된 시간, 날짜를 초과하게 되면 쿠키는 자동 파괴된다.

💡 쿠키는 위 옵션의 여부에 따라 Session Cookie 세션 쿠키 와 영속성 쿠키 Persistent Cookie로 나뉜다.

  • 세션 쿠키: MaxAge or Expires 옵션이 없는 쿠키로, 브라우저가 실행 중일 때 사용할 수 있는 임시 쿠키이며, 브라우저가 종료되면 해당 쿠키는 삭제된다.

  • 영속성 쿠키: 브라우저 종료의 여부와 상관없이 MaxAge or Expires에 지정된 유효시간만큼 사용 가능한 쿠키

  1. Secure
    사용하는 프로토콜에 따른 쿠키의 전송 여부를 결정하는 옵션으로 만약 Secure 옵션이 true로 설정된 경우 Https를 이용하는 경우에만 쿠키를 전송할 수 있다.

⚙️ Secure option이 없다면 http://www.~~~.com or https://www.~~~.com 에 모두 쿠키를 전송할 수 있다.

  1. HttpOnly

자바스크립트에서 브라우저의 쿠키에 접근 여부를 결정하며 만약 해당 옵션이 true로 설정된 경우에는 자바스크립트로 쿠키에 접근이 불가하다.

⚙️ 명시되지않은 경우 기본적으로 false 로 지정되어 있으며 만약 이 옵션이 false 인 경우 document.cookie를 이용해 자바스크립트 쿠키 접근이 가능하므로 XSS 공격에 취약하다.

  1. SameSite
    Cross-Origin 요청을 받을 경우에 요청에서 사용한 메소드와 해당 옵션의 조합을 기준으로 서버의 쿠키 전송 여부를 결정하게 된다.
  • Lax: Cross-Origin 요청이라면 GET 메소드에 대해서만 쿠키를 전송할 수 있다.
    - 사이트가 달라도, GET 요청이라면 쿠키 전송이 가능하다.

  • Strict: 단어 그대로 가장 엄격한 옵션으로, Cross-Origin이 아닌 same-site인 경우에만 쿠키를 전송할 수 있다.

  • None: Cross-Origin에 대해 가장 관대한 옵션으로 항상 쿠키를 보내줄 수 있다, 다만 쿠키 옵션 중 Secure 옵션을 필요로 한다.
    - 사이트가 달라도, 모든 (GET, POST, PUT 등) 요청에 쿠키 전송이 가능하다.

💡 이때 Same-Site는 요청을 보낸 Origin 서버의 도메인, 프로토콜, 포트가 같은 경우를 말하며 이 중 하나라도 다르다면 Cross-Origin으로 구분한다.

쿠키를 이용한 상태 유지

쿠키의 특성을 이용해 서버는 클라이언트의 인증정보를 담은 쿠키를 전송하고, 클라이언트는 전달받은 쿠키를 서버에 요청과 같이 전송하여 Stateless 한 인터넷 연결을 Stateful 하게 유지할 수 있다.

하지만 기본적으로 쿠키는 오랜 시간 유지될 수 있고, HttpOnly Option을 사용하지 않았다면 자바스크립트를 이용해 쿠키에 접근할 수 있기에 쿠키에 민감한 정보를 담는 것은 위험하다.

이런 인증정보를 이용해 제 3자가 유저인척 서버에 요청을 보낸다면 서버는 누가 요청을 보낸건지 의심하지 않고 이를 인증된 유저의 요청으로 취급하게 되어, 개인정보와 같은 민감한 정보를 제 3자가 탈취하는 2차 피해가 일어날 수 있다.

Session

세션기반 인증, Session-based Authentication

login

만약 사용자가 웹사이트에서 아이디 및 비밀번호를 이용해 로그인을 시도한 후

  • 사용자가 정확한 아이디와 비밀번호를 입력했다면, 서버는 인증에 성공했다고 판단
  • 그 후 다음 행동에서 인증을 필요로 하는 작업( ex. 장바구니 물품 추가 등)을 요청할 경우엔 한번 더 로그인을 해야하는가?
    + 대답은 아니다, 위 이미지와 같이 세션이 이 번거로운 작업을 처리해줘 번거롭게 모든 행동에 유저가 로그인 할 필요가 없어진다.

이때 서버와 클라이언트에 각각 필요한 것은?

  • 서버: 사용자가 인증에 성공했음을 알고 있어야 한다.
  • 클라이언트: 인증 성공에 증명할 수단을 갖고 있어야 한다.

사용자가 인증에 성공한 상태를 세션이라고 한다.

  • 서버는 일종의 저장소에 세션을 저장, (위 이미지 2번 주로 im-memory 자바스크립트 객체를 생각하면 된다) 또는 세션 스토어 (redis 등과 같은 트랜잭션이 빠른 DB)에 저장
  • 세션이 만들어지면, 각 세션을 구분할 수 있는 세션 아이디도 만들어지는데 보통 클라리언트에 세션 성공을 증명할 수단으로써 세션 아이디를 전달한다.
  • 이때 웹사이트에서 로그인을 유지하기 위한 수단으로 쿠키를 사용한다, 쿠키에는 서버에서 발급한 세션 아이디를 저장한다.

쿠키를 통해 유효한 세션 아이디가 서버에 전달되고, 세션 스토어에 해당 세션이 존재한다면 서버는 해당 요청에 접근 가능하다고 판단한다.

만일 쿠키에 세션 아이디 정보가 없는 경우엔 서버는 해당 요청이 인증되지 않았음을 알려준다.

로그아웃

세션 아이디가 담긴 쿠키는 클라이언트에 저장되어 있으며, 서버는 세션을 저장하고 있다.
그리고 서버는 세션 아이디로만 인증 여부를 판단한다.

쿠키는 세션 아이디, 인증 성공에 대한 증명을 갖고 있으므로 스마트폰, 공공PC, 태블릿이 탈취될 경우 서버는 해당 요청이 인증된 사용자의 요청이라고 판단한다
그래소 특히 공공PC에서 로그아웃을 해야하는 이유이다.

로그아웃은 다음 두 가지 작업을 해야한다.

  • 서버: 세션 정보를 삭제해야 한다.
  • 클라이언트: 쿠키를 갱신해야 한다.

서버는 클라이언트의 쿠키를 임의로 삭제할 수 없다, 대신에 set-cookie로 클라이언트에게 쿠키를 전송할 때 세션 아이디의 키값을 무효한 값으로 갱신할 수 있다.


Token/OAuth

토큰기반 인증, Token-based Authentication

세션 기반 인증은 서버(DB)에 유저 정보를 담는 인증 방식이었다.
서버에서는 유저가 민감하거나 제한된 정보를 요청할 때 마다 유저의 요청에 정보를 전달해도 괜찮을까?를 확인하기 위해 클라이언트가 보낸 세션 ID를 서버가 가지고 있는 세션 객체와 비교했다.
매 요청마다 데이터베이스를 살펴보는 부담이 서버에 부담을 주기에 부담을 줄이는 방식을 고안한 것이 토큰기반 인증이다.

클라이언트에 인증 정보를 보관할 수 있는 토큰

토크은 유저 정보를 암호화하기 때문에 클라이언트측에 담을 수 있다.

JWT (JSON Web Token)

대표적인 토큰기반 인증으로 JSON 포맷으로 사용자에 대한 속성을 저장하는 웹 토큰

JWT 종류

JWT는 두 가지 종류의 토큰을 이용해 인증을 구현한다
1. 액세스 토큰(Access Token)
2. 리프레시 토큰(Refresh Token)

액세스 토큰: 보호된 정보들(유저의 이메일, 연락처, 사진 등)에 접근할 수 있는 권한부여에 사용한다.

  • 클라이언트가 처음 인증을 받을 때(로그인 시)액세스 토큰, 리프레시 토큰 두가지를 다 받지만, 실제로 권한을 얻는데 사용하는 토큰은 액세스 토큰이며, 액세스 토큰에는 비교적 짧은 유효기간을 줘서 제 3자가 토큰을 탈취하더라도 오랫동안 사용할 수 없도록 한다.

  • 액세스 토큰의 유효기간이 만료되면 리프레시 토큰을 사용해서 새 액세스 토큰을 발급받는다. 이때, 유저는 다시 로그인 할 필요가 없음

하지만 유저의 편의보다 정보를 지키는 것이 더 중요한 웹사이트는 리프레시 토큰을 사용하지 않는 곳이 많다.

JWT 구조

JWT . 으로 나눠진 세 부분이 존재하며 각각을 Header, Payload, Signature라 한다.

  1. Header
    헤더는 이것이 어떤 종류의 토큰인지, 어떤 알고리즘으로 시그니처를 sign(암호화)할지가 적혀있으며, JSON 형태로 정보가 담겨있다.
{
	"alg":"HS256",  // 암호화 알고리즘
    "typ": "JWT"   // JWT
}

위 JSON 객체를 base64 방식으로 인코딩하면 Header가 완성된다.

  1. Payload
    서버에서 활용할 수 있는 유저의 정보가 담겨 있으며, 여기에는 어떤 정보에 접근 가능한지에 대한 권한 또는 유저의 이름과 같은 개인정보를 담을 수 있고, JWT 발급/ 만료일 등을 명시한다.

페이로드는 시그니처를 통해 유효성이 검증될 정보이긴 하나 너무 민감한 정보는 담지 않는 것이 좋은데 이유는 디코딩이 쉬운 base64 방식으로 인코딩 되기 때문이다.

{
  "sub": "someInfomation",
  "name": "kim",
  "iat": 151623391
}

헤더와 마찬가지로 이 JSON 객체를 base64 방식으로 인코딩하면 payload가 완성된다.

  1. Signature
    base64로 인코딩된 헤더와 페이로드가 완성되면 시그니처는 이를 서버의 비밀키(암호화에 추가할 salt)와 헤더에서 지정한 알고리즘을 사용해 암호화한다.

base64 인코딩 자체는 누구나 쉽게 디코딩할 수 있어서 헤더와 페이로드 모두 쉽게 확인할 수 있다.
여기서 비밀키를 사용하면 이를 암호화한 값인 시그니처는 비밀키를 보유한게 아니라면 해독하는데 많은 시간과 노력이 들어가게 된다.

만약 HMAC SHA256 알고리즘을 사용한다면 시그니쳐는 다음과 같은 방식으로 생성된다.
HMACSHA256(base64UrlEncode(header) + '.' + base64UrlEncode(payload), secret);

누군가 권한을 속이기위해 페이로드를 변조하여 base64로 인코딩하더라도 원본 페이로드로 암호화한 시그니처값이 다르기 때문에 서버는 해당 토큰이 변조됐음을 알 수 있다.

토큰 VS 세션

요약하면

  • 토큰 방식은 토큰이 보안, 유저 데이터를 관리한다.
  • 세션 방식은 서버에 보안, 유저 데이터를 관리한다.

이런 이유로 세션과 토큰의 장단점을 따져보면 다음과 같다.

인증방식토큰세션
보안성-WIN
외부 노출시-WIN
성능-WIN
비용WIN-
서버 부하(효율성)WIN-
확장성WIN-

JWT 사용 예시

JWT는 권한 부여에 굉장히 유용하다.
예를 들어, 새로 다운받은 A라는 앱이 Gmail과 연동되어 이메일을 읽어와야 한다고 가정하자

유저는
1. Gmail 인증 서버에 로그인정보(아이디, 비번)을 제공한다.
2. 성공적으로 인증시 JWT를 발급 받는다.
3. A앱은 JWT를 사용해 해당 유저의 Gmail 이메일을 읽거나 사용할 수 있다.

  1. 클라이언트가 서버에 아이디/비밀번호를 담아 로그인 요청
  2. 서버는 아이디/비밀번호를 DB 정보와 일치하는지 확인하고 클라이언트에게 보낼 암호화된 토큰을 생성한다
    • Access/Refresh 토큰 모두 생성
    • Payload(토큰에 담길 정보)는 유저를 식별한 정보, 권한이 부여된 카테고리가 될 수 있다.
    • 두 종류의 토큰이 같은 정보를 담을 필요는 없다.
  3. 서버가 토큰을 클라이언트에게 보내주면 클라이언트는 토큰을 저장한다.
  4. 클라이언트가 HTTP Header or Cookie에 토큰을 담아 보낸다, 쿠키에는 리프레시 토큰을 담고 헤더 또는 바디에는 액세스 토큰을 담는 등 다양한 방법으로 구현할 수 있다.
    • Authorization Heade를 사용한다면 Bearer Authorization을 이용한다
  5. 서버는 토큰을 해독하여 서버에서 발급한 토큰이 맞다는 판단이 들면 클라이언트의 요청을 처리하고 응답을 보낸다.

토큰기반 인증의 장점

1. 무상태성 & 확장성 Statelessness & Scalability

  • 서버는 클라이언트에 대한 정보를 저장할 필요가 없어 부담이 덜하다 -> 발급해주는 토큰인지 검증만 때문
  • 클라이언트는 새로운 요청을 보낼때마다 토큰을 헤더에 포함시키면 된다.
  • 서버를 여러 개 가지고 있는 서비스라면 더욱 빛을 발휘한다, 같은 토큰으로 여러 서버에서 인증이 가능하기 때문에 세션 방식이라면 모든 서버가 해당 유저의 정보를 공유하고 있어야하기 때문이다.
  1. 안전
  • 암호화한 토큰을 사용하고, 암호화 키를 노출할 필요가 없어 안전하다.
  1. 어디서나 생성이 가능하다.
  • 토큰을 검증하는 서버가 토큰을 만들지 않아도 된다.
  • 토큰 생성용 서버를 만들거나, 다른 회사에게 토큰 관련 작업을 위임하는 등 활용이 가능하다
  1. 권한부여에 용이하다
  • 토큰의 페이로드 안에는 어떤 정보에 접근 가능하지 권한을 부여할 수 있다.
    예를 들면 사진과 연락처 사용 권한만 부여하듯이

OAuth

OAuth 2.0, Open Authorization 2.0은 인증을 위한 개방형 표준 프로토콜이다.
이 프로토콜에선 Third-party 프로그램에게 리소스 소유자를 대신하여 리소스 서버에서 제공하는 자원에 대한 권한을 위임하는 방식을 제공한다.

구글, 페이스북, 카카오, 네이버 등에서 제공하는 간편 로그인 기능도 OAuth2 프로토콜 기반의 사용자 인증 기능을 제공하고 있으며, MDS인텔리전스의 IoT 플랫폼인 NeoIDM 또한 OAuth2.0 인증 프레임워크를 기반으로 사용자 인증을 수행한다.

즉, 이미 사용자 정보를 가지고 있는 웹서비스 예를 들면 구글, 깃허브 등에서 사용자의 인증을 대신해주고, 접근 권한에 대한 토큰을 발급한 후 이를 이용해 내 서버에서 인증이 가능해진다.

단 OAuth는 인증(Authentication)을 다른 서비스에 맡길 뿐이고 접근권한 관리(Authorization)는 순전히 내 서버의 몫이다.

OAuth 인증절차

  1. Resource Onwer -> Client Application에 Access service 한다.
  • 사용자는 쿠팡 페이지에 접속한다.
  1. Client Application -> Resource Server에 Access data 한다
  • 사용자가 쿠팡에서 네이버 로그인을 통해 로그인 하고자 한다.
  • OAuth 이용하는 SNS Server 는 자원 서버와 Resource server, 인증 서버 Authorization Server 로 분리되어 있다.

즉 자원 서버와 인증 서버는 역할만 다를 뿐 네이버의 것이다.

  1. Resource Server는 Delegate authentication authorization 하기 위해 -> Authorization Server에 보낸다.
  • 자원 서버는 로그인 사용자 지원을 인증하기 위해 인증 서버로 넘겨주는 것이다
  1. Authorization Server -> Client Application으로 issue authorization code/access token
  • 인증 서버는 접속한 웹페이지의 서버로 인증 코드와 액세스 토큰을 발행해준다.
  • 실질적으로 발행 받은 인증 코드와 액세스 토큰을 통해 네이버의 로그인 서비스를 이용할 수 있다.
  1. Resource Owner-> Grant Aceess를 인증하여 Authorization Server 보낸다.
  • 쿠팡 페이지에서는 사용자의 인증이 완료되어 네이버 로그인이 가능하게 된다.

Resource Owner - 사용자
Client Application - 쿠팡
Resource Server & Authorization Server - 네이버

💡 Authorization grant: 클라이언트가 액세스 토큰을 얻을 때 사용하는 자격 증명으로, 클라이언트가 액세스 토큰을 얻는 방법들이 있다

  • Authorization Code Grant Type
  • Refresh Token Grant Type
  • Client Credentials Grant Type
  • Implicit Grant Type
  • Resource owner Credentials Grant Type
  • Authorization code: Authorization Grant의 한 타입으로 액세스 토큰을 발급받기 전에 필요한 코드

💡 Client ID 로 이 Authorization code 를 받아온 후, Code + Client Secret을 이용해 액세스 토큰을 받아 올 수 있다.
즉, 액세스 토큰을 발급받기 위해 Client ID + Client Secret 가 필요한데, 이 두 가지가 포함된 일종의 허가증이 Authorization Code 이다.

  • Access token: 보호된 리소스에 액세스하는데 사용되는 Credentials, Authorization code 와 Client Secret을 이용해 받아온 이 토큰으로 이제 리소스 서버에 접근할 수 있다.

클라이언트에게 발급된 권한을 나타내고 문자열 타입이다.

  • Scope: 토큰의 권한을 정의한다, 주어진 액세스 토큰을 사용해서 액세스할 수 있는 리소스의 범위이며 사진첩에는 접근할 수 있어도 연락처 등 다른 리소스에는 접근할 수 없도록 접근 권한을 지정 할 수 있다.

Grant Type 종류

Grant Type 이란?

클라이언트가 액세스 토큰을 얻는 여러 방법을 말한다.

Authorization Code Grant Type

가장 일반적으로 쓰이는 방법으로 액세스 토큰을 받아오기 위해서 먼저 Authorization Code를 받은 후 액세스 토큰과 교환하는 방법이다

Authorization Code 절차를 거치는 이유?
보안성 강화 목적으로 클라이언트에서 Client-Secret을 공유하고 액세스 토큰을 가지고 오는 것을 탈취할 위험이 있기 때문에 클라이언트에서는 Authorization Code 만 받아오고, 내 앱(클라이언트)의 서버가 액세스 토큰을 요청 진행한다.


액세스 토큰을 발급받은 후 더 이상 클라이언트는 Authorizaion server를 통하지않고, 리소스 서버와 직접 소통

Refresh Token Grant Type

일정 기간의 유효시간이 지나서 만료된 액세스 토큰을 편리하게 다시 받아오기 위해 사용하는 방법이다

  • 액세스 토큰이 만료될 때마다 사용자에게 인증 권한을 요구하면 유저 입장에서 번거롭기 때문에 클라이언트가 알아서 액세스 토큰을 발급해오는 방법으로 액세스 토큰보다 리프레시 토큰의 유효 시간을 대체로 조금 더 길게 설정하기에 가능한 방법으로, 서버마다 리프레시 토큰에 대한 정책이 다르기 때문에 리프레시 토큰을 사용하기 위해서는 사용하고자 하는 서버의 정책을 살펴봐야한다.


profile
Minthug'life

0개의 댓글