22sook00 logo
SookDev

인증방식에 따른 전략 (Authentication Strategies)

tag
auth
date
Oct 1, 2023

Authentication: Methods, Protocols, and Strategies

🧩 인증 작동방식

이메일과 비밀번호를 이용한 방식

  • 과거에는 대다수의 웹에서 native 인증처리. 인증시스템이 비표준이며 안전하지 않음을 의미
  • 무상태성 (비저장 프로토콜) 인 HTTP,HTTPS 를 통해 통신하기 떄문에 사용자가 액세스 할 때마다 로그인해야한다.
  • 암호기반 인증은 쉽게 공격을 당할 수 있다.

새로운 인증방법

  • OAuth 2.0의 인증 및 권한 매커니즘을 활용한 방식으로, OIDC , SAML 과 같은 표준화 된 인증 프로토콜을 이용할 시 개발자가 직접 개발하지 않아도 안전한 인증매커니즘을 사용할 수 있다.
  • JWT 와 같은 토큰기반 인증을 통해, 지정해 둔 토큰만료 시간까지 재 로그인을 하지 않도록 한다.
    • 🔐
      post 클라이언트에서 로그인에 필요한 정보를 서버측에 보낸다. → 서버는 로그인에 필요한 정보가 맞으면 고유 ID값 부여 후 기타 정보와 함께 페이로드에 넣는다 → 페이로드에서 유효기간을 설정한다 → 암호화할 시크릿 키를 이용하여 HTTP 200 과 함께 액세스 토큰을 발급해준다. (JWT) → get 클라이언트는 발급받은 bearer JWT 토큰을 인증이 필요한 곳마다 헤더에 실어 요청한다 → 서버측은 토큰이 valid 한지 토큰 시그니처를 체크하고 시크릿 키로 복호화 한 후 조작여보와 유효기간 등을 확인한다. → 검증이 완료되면 페이로드의 정보를 디코딩하여 클라이언트 측에 HTTP 200 과 함께 유저 정보를 보내준다.
  • MFA (멀티팩터 인증방식) 는 생체인식, 터치 인증과 등 모바일로 전송되는 일회용 암호 혹은 토큰과 결합하여, 더 강력한 추가 인증방법으로 암호를 보호한다.
 

🧩 인증(Authentication) 과 권한(Authorization) 차이

인증은 어떠한 시스템에 액세스 하기위한 결정을 내릴 수 있는 단계이다.
권한은 사용자가 인증이 되었을 시, 사용자 혹은 시스템의 역할에 따라 액세스 가능 여부를 결정하는 것이다.
즉,
  • 인증 : 사용자의 신원확인, 누가 서비스를 사용하는지 확인하는 절차
  • 권한 : 인증된 사용자가 특정 리소스에 액세스가 가능한지 식별

네트워크 레벨 암호화

인증, 권한절차가 끝나서 API 호출하게 되면 네트워크를 통해 데이터를 가져오게 된다.
가져오는 도중 통신갈취를 막기 위해 HTTP 에서 네트워크 암호화를 하게 된다. 많이 사용하고 있는 암호화 방식 중 하나는 HTTPS 기반 프로토콜을 사용하느 것이다.

메세지 무결성

공격자에 의해 데이터가 중간에 변경되지 않도록 방지하는 것을 말한다. 이 무결성을 보장하기 위해 데이터에 대한 Signature 를 생성하여 검증하는 방식이 있다.
Signature 는 헤더에서 지정한 해시값에 헤더+페이로드로 저장된 데이터, 시크릿키를 저장하여 인코딩한다. 이 인코딩한 해시코드를 현재 가지고있는 데이터를 인코딩한 값과 같은지 비교하는 방법이다.

메세지 본문 암호화

네트워크 레벨의 암호화를 사용할 수 없거나 신뢰할 수 없다면 추가적으로 데이터 자체를 암호화 할 수 있다. (클레임을 암호화하는 뜻같음)
전체데이터를 암호화 할 경우 암호화에드는 비용이 많이 들어가고, 데이터기반 라우팅 변환작업이 어렵기 때문에 일반적으로 보안이 필요한 곳에만 암호화하는 방식을 이용한다.
(큐브에디터 o.header.html, o.html 만 암호화 했던 작업 생각하면 될듯!)
 

🧩 인증 유형

  • 토큰인증 : 가장 일반적인 인증 프로토콜. 사용자가 초기 로그인 하여 인증절차를 걸친 후 토큰을 부여받고, 그 토큰이 유효할 때 까지 재로그인 하지 않아도 액세스가 가능한 방식.
  • 비밀번호 인증 : 사용자가 초기 로그인하여 인증절차를 가진 후, 사용자는 사용했던 문자, 숫자, 특수문자 형태의 이메일 혹은 비밀번호를 기억하여 액세스 할 때마다 로그인 해야하는 방식. 암호가 복잡하고 자주 갱신될 수록 계정이 더 안전해진다.
  • 생체인증 : 지문이나 홍채, 안면인식 등 개인이 가지고 있는 생물학적 데이터를 저장 후 이후 로그인 시 저장된 생체 데이터로 판독하여 편리하고 안전한 방식.
  • 인증서 기반 인증 : 디지털 인증서를 이용하여 사용자를 식별한다. 디지털 인증서는 개인 키가 없으면 위조가 불가능하며 대부분 클라우드 기반 관리 시스템과 함께 제공된다.
  • MFA : 둘 이상의 인증요소 조합으로 위의 유형들이 결합 될 수 있다. 멀티팩터 방식은 보안성이 크게 올라가기 때문에 공격자가 쉽게 손상시키기 어렵다.
  • 비밀번호 없는 인증 (pass key) : 사용자는 지문이나 하드웨어에서 생성된 코드와 같은 다른 형태의 인증을 제공하는데, 보통 MFA 및 SSO(Single Sign-On) 와 결합되어 사용된다.
    • 🔐
      SSO(Single Sign-On) 한 곳에서 인증절차를 거친 후 여러 사용자 계정에서 로그인 할 수 있는 개념. 대표적으로 우리가 자주 사용하는 Google, Apple, Git 이 있다. 서비스 공급자와 ID 공급자의 인증절차 방식은 다음과 같이 이루어진다. ID 공급자(ex-구글)는 인증서 혹은 토큰을 사용하여 서비스 공급자에게 ID 정보를 전송하고 사용자의 인증여부를 확인 한다 → 서비스 공급자는 사용자에게 액세스 권한을 부여하게 된다.
 

🧩 인증 프로토콜

  • PAP(암호인증 프로토콜)
  • CHAP(챌린지 핸드셰이크 인증 프로토콜)
  • LDAP (Lightweight Directory Access Protocol)
  • EAP (확장 가능한 인증 프로토콜)
  • OIDC (오픈아이디 커넥트) // TODO
  • SAML (보안 주장 마크업 언어) // TODO

JWT (JSON Web Token)

가장 많이 사용되고 있는 사용자 인증 표준으로, 웹 상에서 정보를 안전하게 보호하기 위한 정보를 인코딩하여 정보 혹은 토큰을 교환하는 방식.
토큰 자체를 정보로 사용하는 self-contained 방식으로 안전성을 보장한다.
주로 회원인증이나 정보전달을 위해 사용되고 access token. 즉 JWT 를 HTTP header 에 넣어 통신을 한다.
JWT 인증
🔐
post 클라이언트에서 로그인에 필요한 정보를 서버측에 보낸다. → 서버는 로그인에 필요한 정보가 맞으면 고유 ID값 부여 후 기타 정보와 함께 페이로드에 넣는다 → 페이로드에서 유효기간을 설정한다 → 암호화할 시크릿 키를 이용하여 HTTP 200 과 함께 액세스 토큰을 발급해준다. (JWT) → get 클라이언트는 발급받은 bearer JWT 토큰을 인증이 필요한 곳마다 헤더에 실어 요청한다 → 서버측은 토큰이 valid 한지 토큰 시그니처를 체크하고 시크릿 키로 복호화 한 후 조작여보와 유효기간 등을 확인한다. → 검증이 완료되면 페이로드의 정보를 디코딩하여 클라이언트 측에 HTTP 200 과 함께 유저 정보를 보내준다.
JWT 정보교환
🔐
개인/공용 키 쌍을 사용하여 서명 → 페이로드와 헤더를 통해 서명을 가져올 수 있기 때문에 데이터가 손상되지 않고 안전하게 교환 가능
JWT는 크게 Header, Payload, Signature 세가지 요소로 구성된다.
notion image
header eyJhbGciOiJ…cCI6IkpXVCJ9 +(.)
payload eyJzdWIiOiI…F0IjoxNTE2MjM5MDIyfQ + (.)
signature cThIIoDvwdu…seEFoqwxjF_xSJyQQ
최종적으로 만들어진 토큰은 HTTP 통신 간 이용되며,  Authorization 이라는 key의 value (Bearer Token) 로서 사용된다.
 
Header
  • 토큰을 암호화 하는데 사용되는 알고리즘을 지정.
  • 예시 - 헤더에서 디코딩 된 형식은 다음과 같이 생겼다.
    • { “alg”: “HS256”, // 해싱 알고리즘 “typ”: “JWT” }
 
Payload
실제 토큰으로 사용하려는 모든 데이터는 페이로드에 보관된다. 각 데이터를 Claim이라고 하며 다음과 같이 3가지 종류가 있다.
  • Reserved claims : 이미 예약된 Claim. 필수는 아니지만 사용하길 권장. key 는 모두 3자리 String이다.
    • iss (String) : issuer, 토큰 발행자 정보
    • exp (Number) : expiration time, 만료일
    • sub (String) : subject, 제목
    • aud (String) : audience,
  • Public claims : 사용자 정의 Claim.
    • Public 이라는 이름처럼 공개용 정보
    • 충돌 방지를 위해 URI 포맷을 이용해 저장한다.
  • Private claims : 사용자 정의 Claim
    • Public claims 과 다르게 사용자가 임의로 정한 정보
    • 아래와 같이 일반 정보를 저장한다.
      • { "sub": "1234567890", "name": "sook", "iat": 1516239022 }
 
Signature
  • Header와 Payload의 데이터 무결성과 변조 방지를 위한 서명
  • 헤더에서 지정한 해싱 알고리즘과 함께 base64UrlEncode(헤더+페이로드), 시크릿 키를 인코딩 한 후 서명된다.
    • HMACSHA256( base64UrlEncode(header) + "." + base64UrlEncode(payload), // your-256-bit-secret ) secret base64 encoded
 
//TODO
언제 JWT 를 사용하면 좋을까
 

🧩 API 인증방법

기본 HTTP 인증

유저는 본인 인증을 위해 유저네임, 암호를 제공.
HTTP 헤더 자체에 base64 로 인코딩형태로 변경하여 인증을 요청하기 때문에 쿠키나 세션ID, 로그인페이지가 필요하지 않다.
ex ) id : sook / pw: sook123!
HTTP 헤더에 “sook: sook123!” 라는 문자열을 Base64를 활용해 인코딩 Authorization 이름의 헤더로 서버에 전송하여 인증을 요청하면 다음과 같은 형태가 된다.
//sook: sook123! 인코딩예시 Authorization: Basic ZG9uZ3dvb2s6cGFzc3dvcmQ=
사용하기 쉬운 만큼 전송중인 사용자가 자격증명을 중간에 가로챌 수 있어 공격에 취약하다.
중간에 헤더를 가로채서 인코딩한 값을 디코딩 해버리면 아이디,비밀번호 값이 그대로 노출되기 때문에 꼭 https 프로토콜을 사용해야 한다.
base64 디코딩 변형 사이트 👉🏻 https://www.base64decode.org/

API 키

특정 사용자만 알 수 있는 문자열로,
이용하려는 사이트에서 제공하는 API 키를 발급받아 해당 API 호출 시 키를 입력하여 호출한다.
API 키 인증방법은 매우 빠르지만 한번 API 가 노출될 경우 전체 API까지 노출될 위험성이 있어 높은 보안인증이 필요한 경우에 권장하지 않는다.

API 토큰

해당 방식으로 유저가 로그인 할 경우 ID, PW로 사용자 인증을 한 후 기간이 유효한 API 토큰을 발급하여 인증하는 방식이다.
🔐
유저는 ID, PW 로 로그인하며 API 호출을 위한 API 토큰을 요청하게 된다. → API 인증서버는 ID,PW 를 바탕으로 유저인증을 한다. → 인증되면 유효한 시간을 가진 API Access Token 을 발급한다. (secure HTTP Cookie + HTTP Only 설정) → 유저는 해당 API Access Token을 이용하여 API 호출을 한다.
 
API를 호출 할 때마다 네트워크에 사용자 ID, PW 를 보낼 시 사용자 계정정보가 그만큼 노출빈도가 높고 탈취당할 위험성이 있기 때문에 API 토큰을 별도로 발급하여 사용한다.
API 토큰 탈취당한다면?
사실상 토큰만 탈취당했기 때문에 ID와 비밀번호는 탈취당하지 않으며, API 호출도 가능하다.
또한 ID,PW 를 직접적으로 보낼 시 다른 서비스에서 동일한 문자열을 사용할 가능성이 있기 때문에 연쇄공격을 당할 수 있지만 토큰을 사용하게 되면 이러한 피해를 줄일 수 있다.
 
여기에 더 보안강화를 하기 위해 클라이언트 인증방식을 추가 할 수 있다.
Client ID 와 Client Secret 을 받는것이 일반적인데, Client ID는 특정 앱 등록 ID 이고 Client Secret은 특정 앱의 비밀번호로, 앱을 등록할 때 앱 별로 발급된다.
API 토큰 발급 시, Client ID 와 Client Secret 을 이용해 클라이언트 앱을 인증한 후
추가적으로 유저의 ID, PW 를 받아 검증한다. 이렇게 모든 인증절차를 거치면 API Access Token 을 발급할 수 있다.

OAuth 2.0

토큰을 기반으로 한 개방형 표준인증 프로토콜이다.
해당 사이트에 직접 가입하지 않고 구글, 애플, 깃 등 사이트에서 인증을 거쳐 사용자의 계정 정보를 공유할 수 있다. 계정 정보공유를 승인하는 Access Token 으로 사용하려는 사이트에 비밀번호 공유 없이 권한을 부여받을 수 있다.
ex)
어떠한 네이버 카페 같은 웹사이트에 접속해 로그인을 했다고 하자. 회원가입, 로그인을 하는 순간 사용자 인증은 끝났다.그 후 글쓰기 권한, 수정 권한, 게시글 관리 권한 등등 회원의 등급 별로 가능해지는데 이것을 접근 권한이 다르기 때문이다.
따라서 OAuth는 인증정보만 다루고, 사용자가 로그인등을 요청한 서버에서는 접근권한을 다룬다.
이렇게 사용자가 로그인 등 해당 사이트에 대한 접근 권한을 요청하면 이러한 접근 권한을 다루는 곳은 Athorization 서버라 부르며, 이 Athorization 서버에서 이 사용자에 대한 인증을 확인하기 위해 사용자 정보를 요청하고 그 인증 정보를 가지고 있는 서버는 Resource(naver, payco 등) 서버라고 한다.
notion image
OAuth 1.0 과 다른점은 다음과 같다.
  • Signature 의 단순화
  • 모바일을 수용하는 새로운 인증코드
  • 장기인증을 지원하는 단기토큰

Cookie, Session, Token

🧩 Cookie, Session, Token 의 특징

쿠키와 세션 인증방식은 기본적으로 세션저장소를 필요로 한다.
💡
유저 로그인 → 서버에서 계정정보 확인 후 고유 ID 값 부여하여 세션 저장소에 저장 → 고유 ID 값과 연결되는 세션 ID(쿠키) 생성 → HTTP 헤더에 세션ID(쿠키) 추가하여 클라이언트에 전송 → 브라우저(클라이언트) 는 세션ID(쿠키)를 저장 → 인증이 필요한 요청에 쿠키를 헤더에 끼워 서버에 요청 → 서버는 쿠키를 받아 세션 저장소에 저장하며 일치하는 정보 가져옴 → 인증완료 후 사용자에게 맞는 데이터 보내준다.

Cookie

서버에서 발급된 세션을 열기 위한 값(세션 ID 라고 칭함)
사용자 정보를 브라우저 메모리에서 관리한다.
서버의 자원은 사용하지 않는다는 뜻으로, 클라이언트가 인증정보를 책임지는 것을 의미한다. 구성은 이름, 값, 만료날짜, 경로정보가 있다.
(크롬 등 웹브라우저에서 사용자가 직접 쿠키삭제 할 수 있는것을 생각해!)
 
쿠키는 조작된 데이터일 수 있어 실제 정보가 존재하는 DB를 사용하여 작업.
보안과 관련없는 장바구니, 자동로그인 설정에 유용하게 사용된다.
ex ) react-cookie 라이브러리로 자동로그인 설정유무 세팅가능
만약 공격자가 HTTP 요청 중간에서 쿠키 탈취한다면 모든 정보가 탈취된다고 볼 수 있다.
 

Session

서버에서 가지고있는 정보
웹에서 사용자의 상태 정보를 저장하고 관리하기 위한 방식 중 하나
세션은 사용자가 웹 서비스와 상호작용할 때 생성되며 사용자의 상태 정보를 서버측에 저장한다.
이 정보를 통해 사용자를 식별하고 로그인 상태, 권한등을 알 수 있다.
인증의 책임을 서버가 지게 하려면 세션을 함께 이용한다.
서버가 클라이언트에 대한 고유ID 를 부여하고 서버측에서 세션ID(쿠키)를 관리한다.
그렇기때문에 사용자의 정보 중 보안상 중요한것이 있다면 세션에서 관리한다.
즉, 사용자는 쿠키를 이용하고 서버에서는 쿠키를 받아 세션의 정보로 접근하는 방식으로 인증한다.
그렇기 때문에 세션ID(쿠키) 가 탈취 되더라도 실제 정보는 서버 세션에 존재하기 때문에 쿠키 자체는 유의미한 값을 갖지 않는다.
그러나 서버에 세션저장소를 사용하기 때문에 부하가 높아져 추가적인 저장공간이 필요할 수 있다.
그리고 세션 하이재킹 공격이 가능할 수 있는데, 이때 HTTPS 를 사용하여 요청자체를 탈취해도 정보를 읽기 힘들게 하거나 세션에 유효시간을 부여 하므로서 탈취를 예방할 수 있다.
 

Token

JWT (Json Web Token) , OpenID Connect 프로토콜
유저가 로그인 한 후 정보가 맞을 시 생성되는 access-token 을 HTTP 헤더에 담아 서버에 전송한다.
JWT 토큰발급 후 검증만 하기 때문에 별도의 저장소가 필요하지 않는 무상태성(stateless) 성격이 있어 서버를 확장하거나 유지보수하는데 유리하다.
또한 토큰기반으로 하는 다른 인증시스템, third-party web 에 접근이 가능하다.
그러나 토큰은 임의로 생성된 비밀번호와 같으므로 제한된 수명이 있으며 쿠키/세션과 달리 삭제가 불가하여 악의적으로 이용되도 만료전까지는 정보가 이용될 수 있다. 그렇기때문에 access-token 유효기간을 짧게하고 토큰만료 시 refresh token 으로 새로 생성하여 탈취피해를 최소화 시킬 수 있다.
또한 페이로드의 클레임들은 인코딩만 될 뿐 따로 암호화가 되지 않기때문에 누군가 악의적으로 디코딩하면 누구나 정보를 확인 할 수 있다. 따라서 매우 중요한 정보는 넣으면 안된다.
또한 따로 저장소가 있지 않기 때문에 정보가 많아질수록 base64로 인코딩한 값이 길어질 수 있다. 인증요청이 많아질수록 서버의 자원낭비가 발생할 수 있다.
 
 
✳️ JWT 인증방식과 세션쿠키 인증방식 차이
JWT 와 세션은 사용자 인증 및 권한 부여에 사용되는 두가지 주요 방식이다.
세션쿠키 : 세션저장소에 유저의 정보를 넣는다.
JWT : 유저 정보들를 토큰 안에 넣는다.
클라이언트 입장에서는 HTTP 헤더에 세션아이디 혹은 토큰을 실어보내준다는 점에서 동일하지만
서버측에서는 인증을 위해 암호화 하냐, 별도로 저장하냐 차이가 존재한다.
세션
JWT
저장위치
서버측에서 사용자 데이터를 저장하며 클라이언트는 세션 ID 만 가지고 있음
클라이언트 측에서는 사용자 데이터를 포함하는 토큰을 저장
확장성
서버에서 세션을 관리하므로 서버자원 사용
클라이언트 측에서 토큰을 검증하므로 서버자원을 덜 사용하고 확장성이 더 뛰어나다.
보안
서버에서 데이터를 안전하게 관리하므로 데이터 유출 가능성이 낮음
토큰은 안전하게 서명되어 있지만 클라이언트 측에 저장되므로 XSS 공격에 노출 될 수 있음 만약 JWT 키가 노출이 된다면 그 시간이 끝나기 전까지 막을 수 있는 방법이 없어 보안에 취약하다.
사용 사례
로그인 상태관리, 권한부여, 사용자 데이터 관리 등에 적합
분산 시스템, API 인증, 단일 로그인(SSO,SNS 로그인) 등에 적합

🧩🧩 결론

🧸
쿠키/세션은 세션 저장소에 유저 정보를 넣는 반면, JWT 토큰방식은 토큰에 유저 정보를 넣는다. 즉, 클라이언트 측에서는 HTTP 헤더에 세션ID(쿠키) 혹은 access-token 을 실어 보내준다는 공통점이 있지만 서버입장에서는 인증을 위해 별도의 저장소를 이용하거나 암호화를 하는 방식 차이가 발생한다.
 

📜 참조