이선협(@kciter)
- CoBALT, CTO
kciter - Overview
Just Developer. kciter has 92 repositories available. Follow their code on GitHub.
github.com
들어가기 전에...
인증 및 인가, 계정, 사용자 이런 것들은 원래 복잡하다! (나중에 바꾸기도 어려움)
인증과 인가 무슨 차이일까?
- 인증(Authentication)은 누구인지 확인하는 것
- 인가(Authorization)은 무엇을 할 수 있는지 결정하는 것
- 인증과 인가는 서로 다른 개념
- 인증은 "당신이 누구인가?"를 묻고, 인가는 "당신은 무엇을 할 수 있는가?"를 묻는다.
인증(Authentication)
- 사용자가 누구인지 확인하는 것
- 어떻게 사용자가 누구인지 확인할까?
- 본인임을 증명할 수 있는 방법
- 아이디 / 비밀번호
- Passwordless
- 사용자가 소유한 것 기반
- ex) 휴대폰, 이메일, 카드, 하드웨어 토큰 등
- 사용자의 어떠한 것 기반
- ex) 지문, 얼굴, 음성 등
- 위치, 네트워크 주소, 행동패턴, ...
- 사용자가 소유한 것 기반
- 토큰
- JWT, OAuth2, OpenID Connect
- ...
- 본인임을 증명할 수 있는 방법
보안과 편의 사이
- 보안이 강화될수록 편의성이 떨어짐
- 매번 아이디 / 비밀번호를 입력하는 것은 불편함
- 자주 전송할수록 노출될 확률이 높음 -> 보안 취약
- 토큰은 어떨까?
- 한 번 발급 받으면 계속 사용 가능
- 탈취되면 계정을 빼앗기는 것과 같음
- 유효 기간을 통해 보안을 유지
인가(Authorization)
- 사용자가 무엇을 할 수 있는지 결정하는 것
- 누구인지 확인했다고 해서 모든 것을 할 수 있는 것은 아님
- 인가를 통해 사용자가 할 수 있는 것을 제한
- ex) 관리자, 일반 사용자
- ex) 가게 주인, 라이더, 고객은 서로 다른 권한을 가짐
권한을 부여하는 방법
- 역할 기반 접근 제어(Role-Based Access Control, RBAC)
- 사용자의 역할에 따라 권한을 부여
- ex) 관리자, 일반 사용자
- 속성 기반 접근 제어(Attribute-Based Access Control, ABAC)
- 사용자의 속성에 따라 권한을 부여
- ex) 사용자의 역할, 직급, 리소스의 속성, 환경, ...
- 어떠한 리소스에 접근하려면?
- 사용자: 해당부서 직원, 리소스: 해당부서의 문서, 동작: 읽기
- 사용자가 해당 부서 직원이고, 해당 부서의 문서를 읽으려고 할 때에만 읽기 가능
- 쓰기는 불가능
- 역할 기반이 더 간단하지만, 속성 기반은 더 유연함
- 역할 기반 - Coarse-grained
- 속성 기반 - Fine-grained
사용자와 계정은 무엇이 다른가?
- 보통 사용자와 계정을 동일시 하는 경우가 많음
- 하지만 사용자와 계정은 분명히 다름
- 사용자는 시스템을 이용하는 실제 사람에 대한 정보
- name, email, phone, address, ...
- 계정은 사용자를 식별하기 위한 정보
- id, password, token, ...
제품에 따라 하나의 사용자에 여러 계정이 필요할 수 있다.
사례
- 한 사람이 여러 인증 수단을 가질 수 있음
- 아이디 / 비밀번호, 생체 인식, OAuth, ...
- 한 사람이 여러 이메일 계정을 가지고 있을 수 있음
- GitHub의 경우 이메일 계정을 여러 개 등록할 수 있음
- 한 사람이 여러 소셜 계정과 연동할 수 있음
- Facebook, Google, Twitter, GitHub, ...
다시 사용자와 계정으로 돌아와서
- 계정을 통한 인증
- 사용자에 대한 인가
간단한 역할 기반 접근 제어(RBAC) 모델링
- Users:Accounts = 1:N
- Users:Roles = N:M
- Roles:Permissions = N:M
토큰
토큰은 크게 보면 두 가지로 나뉜다
One-Time Token과 Persistent Token
One-Time Token
- 한 번만 사용할 수 있는 토큰
- 주로 비밀번호 찾기, 이메일 인증 등에 사용
- 사용 후에는 폐기되어야 함
- 사용자가 토큰을 잃어버리면 다시 발급해야 함
- 보통 만료 기간이 있음
- Nonce라고 부르기도 함
사례 / 비밀번호 재설정
Persistent Token
- 계속 사용할 수 있는 토큰
- 주로 지속적인 로그인 상태를 유지하는데 사용
- 사용자가 로그아웃하거나 토큰을 폐기할 때까지 유효
- 만료 기간을 두는 것이 안전
Persistent Token을 어떻게 유지할 것인가?
- Access Token + Refresh Token
- Access Token 만으로는 만료되면 다시 로그인해야 함
- Refresh Token은 Access Token을 갱신하는 데 사용
사례 / 인증과 유효기간
Access Token과 Refresh Token의 사실과 오해
- 오해: 토큰은 JWT로 만들어야 한다.
- 사실: 아니다. JWT가 유용한 경우도 있지만, 다른 방법도 존재
- Opaque Token을 사용할 수도 있음
- 토큰 자체에는 정보가 없고 서버 또는 데이터베이스 토큰을 조회해야 함
- 오해: Refresh Token은 서버에 저장되지 않는다.
- 사실: Refresh Token은 클라이언트와 서버 모두에서 안전하게 저장되어야 함
- 오해: Refresh Token은 무한히 재사용할 수 있다.
- 사실: Refresh Token도 만료 시간이 있으며, 일정 기간 후에는 갱신이 필요
Refresh Token 연장 방법
- Refresh Token은 보통 유효 기간이 길게 설정됨
- 그래도 언젠가 만료됨
1. Refresh Token Rotation(리프레시 토큰 회전)
- Refresh Token을 통해 연장할 때 실행
- 새로운 Refresh Token을 발급하면서 이전 Refresh Token을 폐기
2. Sliding Expiration (슬라이딩 만료 시간)
- Refresh Token을 사용할 때마다 만료 시간을 연장
3. Re-authentication (재인증)
- 일정 기간이 지나면 무조건 다시 로그인을 요구
토큰 통신 / 보관 방법
토큰을 교환하는 방법
- HTTP 헤더에 토큰을 포함하여 전송하는 방법
- 쿠키에 토큰을 저장하여 전송하는 방법
무엇이 옳은가?
- 정답은 없음 결국 트레이드 오프
- 쿠키로 전송하는 방법
- CSRF 공격에 취약
- 클라이언트에서 접근할 수 없음 (읽는 것도 불가능)
- 모든 요청에 토큰이 전송됨
- 단일 도메인에서만 사용 가능
- 해결하려면 reverse proxy를 사용해야 함
- HTTP 헤더로 전송하는 방법
- 토큰을 어딘가에 저장해야 함
- Not httpOnly cookie, localStorage, sessionStorage, IndexedDB, ...
- XSS 공격에 취약 (스크립트 실행이 가능하면 탈취 가능)
- SPA라면 쉬운 대안이 없음
- 토큰을 어딘가에 저장해야 함
헤더 방식 - Bearer 토큰 인증
- Bearer: 전달자, 소지자라는 뜻
- 토큰의 내용은 JWT, Opaque Token 등 아무거나 사용해도 무방
- 보통 Authorization 헤더에 토큰 포함
쿠키 방식을 통한 로그인
쿠키 방식을 통한 인증/인가
헤더 방식을 통한 로그인
헤더 방식을 통한 인증 / 인가
잠깐! 프론트엔드 서버에서 토큰을 어떻게 알죠?
- 프론트엔드 서버가 존재하는 Next.js, Nuxt.js, Gatsby 등의 SSR 프레임워크
- 이 경우 페이지 요청시 서버에서 데이터를 결합
백엔드 서버와 도메인이 다르다면?
- 도메인이 완전히 다르다면 까다로워짐
- SameSite 설정을 None으로 하면 쿠키 전송 가능
- HTTPS(Secure) 사용 필수
- 서버에서 CORS 설정을 통해 쿠키가 전송될 수 있게 허용해야 함
- 혹은 리버스 프록시 서버를 사용하여 쿠키를 전달
- SameSite 설정을 None으로 하면 쿠키 전송 가능
- 서브 도메인 정도 차이라면 쿠키 설정으로 해결 가능
- 도메인 설정을 .example.com과 같이 설정
OAuth 인증
OAuth란?
- OAuth라고 말하면 보통 OAuth 2.0을 의미
- OAuth(Open Authorization)는 타사 애플리케이션이 사용자 비밀번호를 알지 않고도 사용자의 승인하에 보호된 자원에 접근할 수 있도록 해주는 인증 및 인가 프레임워크
- 말이 조금 어려운데 한 마디로 말하면, 사용자의 동의를 받아 다른 애플리케이션에서 사용자의 정보를 사용할 수 있도록 하는 것
- OIDC 기반으로 사용자의 신원을 확인할 수 있음
- 보통 인증/인가 둘다 OAuth로 부르는 경우가 많음
- 그렇지만 OAuth 2.0은 인가 프로토콜이고, OIDC는 인증 프로토콜
OpenID Connect (OIDC)란?
- OAuth 2.0 프로토콜을 기반으로 구축된 인증(Authentication) 프로토콜
- OAuth 2.0의 인가(Authorization) 기능에 인증 기능을 추가하여, 사용자의 신원 확인을 가능하게 함
인증 / 인가 흐름
사례 / 외부 OAuth 제공자와 연동하여 회원가입하기
사례 / 데이터 저장을 위한 Prepare 단계가 있는 경우
Q. 토큰 만료 시간에 대한 적절한 기준이 있나요?
보안에 민감한 서비스는 하루/일주일 (30분/하루도 괜찮음),
아닌 서비스는 한달/삼개월 정도. 정답은 없음.
Q. 정부24에서 제공하는 간편 로그인 기능 중 은행을 통한 인증도 OAuth인증인가요?
OAuth인증은 아닌거 같고, 자체적인 다른 인증 방식을 사용하지 않았을까 추측합니다. 공인인증서의 개선판이 아닐까 추측합니다. 실제로 상세한 명세를 본게 아니라 확실하진 않지만 OAuth는 아닐거 같습니다.
'특강' 카테고리의 다른 글
포트폴리오 (0) | 2025.02.24 |
---|---|
이력서 특강(이민석 교수님) (2) | 2025.01.22 |