인증과 인가
당신이 누구인지 확인하고, 무엇을 할 수 있는지 정하는 방법이다.
목차 (8)
인증과 인가는 다른 질문이다
인증(authentication)은 "당신은 누구인가"를 확인하는 일이고, 인가(authorization)는 "그 사람이 이 일을 해도 되는가"를 정하는 일이다. 건물로 치면 출입구에서 신분증을 보는 것이 인증, 신분이 확인된 사람의 출입 카드로 몇 층 문까지 열리는지 정하는 것이 인가다. 영어로는 둘을 줄여 authn, authz라고도 쓴다.
둘은 순서가 있다. 누구인지 모르면 권한을 따질 수 없으므로 인증이 먼저다. HTTP도 둘을 다른 상태 코드로 나눈다. 401(Unauthorized)은 이름과 달리 "누군지 모르니 인증하라"는 뜻이고, 403(Forbidden)은 "누군지는 알지만 이 일은 허락되지 않는다"는 뜻이다. 실제 사고는 인증보다 인가 쪽에서 더 자주 난다. 로그인은 한 곳에서 하지만, 권한 확인은 기능과 데이터마다 빠짐없이 해야 하기 때문이다.
비밀번호 저장: 되돌릴 수 없게, 일부러 느리게
서버는 비밀번호를 알 필요가 없다. 로그인 때 입력한 값이 처음 정한 값과 같은지만 확인하면 된다. 그래서 비밀번호는 암호화(되돌릴 수 있음)가 아니라 해시(hash, 되돌릴 수 없음)로 저장한다. 해시가 무엇인지는 암호 노트와 데이터 노트의 암호와 해시에 있고, 인코딩 도구에서 SHA-256 값을 직접 계산해 볼 수 있다.
해시만으로는 모자라다. 같은 비밀번호는 같은 해시가 되므로, 유출된 표에서 같은 값끼리 묶으면 누가 흔한 비밀번호를 쓰는지 바로 보이고, 흔한 비밀번호들의 해시를 미리 계산해 둔 표로 한꺼번에 찾을 수 있다. 이를 막는 것이 사용자마다 다른 무작위 값을 섞는 솔트(salt)다. 솔트는 비밀이 아니어서 해시 옆에 그대로 저장한다. 하는 일은 미리 계산한 표를 쓸모없게 만들고, 사용자 하나하나를 따로 맞혀 보게 만드는 것이다.
마지막 문제는 속도다. SHA-256 같은 일반 해시는 빠르게 만들어졌고, GPU로는 초당 수십억 번을 계산한다. 유출된 해시를 놓고 후보를 넣어 보는 공격(오프라인 추측)에 그 속도가 그대로 공격자의 속도가 된다. 그래서 비밀번호에는 일부러 시간과 메모리를 많이 쓰도록 만든 비밀번호 해시 함수(password hashing function, 키 유도 함수 KDF라고도 한다)를 쓴다. 로그인 한 번에 수십 밀리초는 사용자에게 티가 안 나지만, 수십억 개를 맞혀 보려는 쪽에는 감당하기 어려운 비용이 된다. 비용 설정값은 해시와 함께 저장해, 하드웨어가 빨라지면 다음 로그인 때 더 높은 값으로 다시 해시한다.
평문 저장: 데이터베이스가 한 번 새면 모든 비밀번호가 그대로 드러난다.
되돌리지 않고 어떻게 맞는지 아나
흔히 묻는 것이 "솔트 때문에 같은 비밀번호도 매번 다른 값이 되는데, 로그인할 때는 어떻게 비교하나"다. 답은 복호화하지 않고 같은 계산을 한 번 더 한다는 것이다. 매번 달라지는 것은 가입하거나 비밀번호를 바꿀 때 솔트를 새로 뽑기 때문이고, 뽑은 솔트는 해시 결과와 함께 저장해 둔다. 로그인 때는 그 사용자의 저장값에서 솔트와 비용 설정을 꺼내, 입력한 비밀번호에 그 솔트를 붙여 같은 비용으로 다시 해시한다. 새로 나온 값이 저장된 해시 결과와 같으면 처음과 같은 비밀번호다.
Argon2·bcrypt 같은 라이브러리는 알고리즘, 비용 설정, 솔트, 해시 결과를 PHC 문자열 형식 같은 문자열 하나에 묶어 저장한다. 그래서 코드에서는 솔트를 따로 다룰 일이 없다.
# Python, argon2-cffi
from argon2 import PasswordHasher
hasher = PasswordHasher()
stored = hasher.hash("correct horse") # 가입: 솔트를 새로 뽑아 문자열에 함께 담는다
hasher.verify(stored, "correct horse") # 로그인: 문자열 속 솔트·비용으로 다시 계산해 비교 → 통과
hasher.verify(stored, "wrong") # 다르면 VerifyMismatchError
hasher.check_needs_rehash(stored) # 비용 설정을 올렸다면 True → 이번 로그인 때 다시 해시해 저장비교는 상수 시간으로 한다. 앞에서부터 한 글자씩 보다가 다르면 바로 멈추면, 걸린 시간 차이로 몇 글자까지 맞았는지가 샌다. verify 같은 라이브러리 함수는 이것을 알아서 한다(argon2-cffi API). 직접 비교해야 한다면 hmac.compare_digest처럼 상수 시간 비교 함수를 쓴다.
OWASP Password Storage Cheat Sheet가 권하는 선택지와 최소 설정은 다음과 같다.
| 함수 | 특징 | OWASP 최소 설정 |
|---|---|---|
| Argon2id | 2015년 비밀번호 해시 대회 우승작. 메모리를 많이 써서 GPU·전용 칩으로 병렬화하기 어렵다. RFC 9106으로 표준화됐다 | 메모리 19 MiB, 반복 2, 병렬 1. 새로 만든다면 첫 선택 |
| scrypt | 메모리를 많이 쓰게 설계한 앞 세대 함수 | N=2^17, r=8, p=1 (Argon2id를 쓸 수 없을 때) |
| bcrypt | 1999년부터 쓰인 검증된 함수. 입력이 72바이트에서 잘린다 | 작업 계수 10 이상. 이미 쓰는 시스템에서 |
| PBKDF2 | HMAC을 여러 번 반복한다. 메모리를 쓰지 않아 GPU에 약하지만 FIPS 인증 환경에서 쓸 수 있다 | HMAC-SHA-256으로 600,000회 이상 (FIPS-140이 필요할 때) |
사용자에게 무엇을 요구할지는 미국 표준 기술 연구소(NIST)의 디지털 신원 지침 SP 800-63B(개정 4판)가 기준으로 많이 쓰인다. 흔히 보던 규칙 몇 가지는 오히려 하지 말라고 적혀 있다. 대문자·숫자·특수문자를 섞으라는 규칙은 사람들이 "Password1!"처럼 뻔한 변형을 고르게 만들 뿐 효과가 작았다는 것이 유출 데이터 분석의 결론이다.
| 항목 | SP 800-63B 개정 4판의 요지 |
|---|---|
| 길이 | 비밀번호만으로 로그인한다면 15자 이상, 다중 인증의 한 요소라면 8자 이상. 최대 길이는 64자 이상 허용 |
| 조합 규칙 | 문자 종류를 섞으라는 규칙을 강제하지 않는다. 공백과 유니코드도 받는다 |
| 금지 목록 | 흔한 비밀번호, 예상하기 쉬운 값, 유출된 비밀번호 목록과 비교해 걸리면 다른 것을 고르게 하고 이유를 알려 준다 |
| 주기적 변경 | 정기적으로 바꾸라고 요구하지 않는다. 유출 증거가 있을 때만 바꾸게 한다 |
| 비밀번호 관리자 | 자동 채우기와 붙여넣기를 막지 않는다. 관리자를 쓰면 더 강한 비밀번호를 고르게 된다 |
| 추측 제한 | 로그인 실패가 이어지면 시도 횟수를 제한한다. 금지 목록이 작아도 되는 이유가 이것이다 |
HTTPS가 있으면 브라우저에서 비밀번호를 암호화하지 않아도 되는 이유
로그인 폼에서 비밀번호를 서버로 보내기 전에 자바스크립트로 해시하거나 공개키로 암호화하는 경우가 많다. "평문 비밀번호가 네트워크로 나가면 안 된다"는 생각에서다. 하지만 HTTPS를 쓰면 그 걱정은 이미 TLS가 맡고 있고, 브라우저에서 한 번 더 하는 작업은 대개 보호를 더하지 못한다.
- TLS가 이미 전송 구간을 지킨다: 오가는 내용을 암호화하고(기밀성), 중간에서 바꾸면 알아채며(무결성), 상대가 진짜 그 서버인지 인증서로 확인한다(인증). 비밀번호도 이 안에서 암호문으로만 지나간다.
- 브라우저 해시는 새 비밀번호가 될 뿐이다: 서버는 받은 해시가 맞는지만 보므로, 해시를 가로챈 사람은 원래 비밀번호를 몰라도 그 해시를 그대로 보내 로그인한다. 서버가 그 값을 그대로 저장하면 DB가 새는 순간 바로 쓸 수 있는 로그인 정보가 된다. 그래서 서버는 받은 값이 무엇이든 다시 느린 해시로 저장해야 하고, 결국 브라우저 해시가 빠진 셈이 된다.
- 그 자바스크립트도 같은 서버가 보낸다: TLS가 깨진 상황이라면 공격자는 해시하는 스크립트 자체를 바꿔 평문을 빼돌릴 수 있다. TLS가 멀쩡하다면 스크립트 암호화는 겹칠 뿐이다. 어느 쪽이든 브라우저 쪽 암호화가 TLS를 대신하지 못한다.
- 직접 만든 암호화는 새 문제를 부른다: 페이지에 공개키를 넣어 비밀번호를 RSA로 암호화하는 식은 키 교체, 같은 암호문을 다시 보내는 재전송, 패딩 실수 같은 문제를 스스로 풀어야 한다. TLS가 이미 표준으로 풀어 둔 것들이다.
대신 해야 할 일은 이렇다. 모든 페이지와 API를 HTTPS로만 받고 HSTS로 첫 요청까지 막는다(보안 › 네트워크). 서버에서 Argon2id 같은 느린 해시로 저장한다. 로드 밸런서에서 TLS를 풀었다면 그 뒤 내부 구간도 암호화한다. 그리고 요청 본문이 로그에 그대로 남아 비밀번호가 로그 파일에 찍히는 실수를 막는다. 큰 서비스들도 평문 비밀번호가 내부 로그에 남아 있던 것을 뒤늦게 찾아 사용자에게 비밀번호 변경을 권한 일이 있었다.
브라우저에서 키를 만드는 것이 의미 있는 경우도 있다. 서버조차 내용을 몰라야 하는 종단 간 암호화다. 비밀번호 관리자나 종단 간 암호화 백업은 브라우저·앱에서 비밀번호로 암호화 키를 유도하고, 서버에는 암호문만 맡긴다. 이때도 로그인용 값과 암호화 키는 서로 다른 유도 경로로 만든다. 비밀번호를 아예 서버에 보내지 않는 방법도 있다. 비밀번호 기반 키 교환(PAKE)인 OPAQUE(RFC 9807)와, 비밀 자체가 없는 아래의 패스키다.
다중 인증: 종류가 다른 요소를 겹친다
비밀번호는 피싱, 재사용, 유출로 언제든 남의 손에 들어갈 수 있다. 다중 인증(MFA, multi-factor authentication)은 종류가 다른 증거를 둘 이상 요구해, 하나가 새도 그것만으로는 들어올 수 없게 한다. 인증 요소는 전통적으로 셋으로 나눈다. 아는 것(비밀번호, PIN), 가진 것(휴대폰, 보안 키), 나인 것(지문, 얼굴)이다. 같은 종류를 두 번 묻는 것, 예를 들어 비밀번호 다음에 보안 질문을 묻는 것은 다중 인증이 아니다.
두 번째 요소도 방식마다 강도가 다르다. 문자로 받는 일회용 코드는 번호를 빼앗는 유심 바꿔치기(SIM swap)나 가로채기에 약하다. 앱이 만드는 시간 기반 일회용 코드(TOTP)는 그보다 낫지만, 사용자가 가짜 사이트에 코드를 직접 입력하면 공격자가 그 코드를 곧바로 진짜 사이트에 쓸 수 있다. 푸시 승인은 알림을 계속 보내 지친 사용자가 누르게 만드는 수법(MFA 피로 공격)에 노출된다. 출처에 묶인 공개키 서명을 쓰는 보안 키와 패스키만이 피싱 자체에 버틴다. 각 방식의 장단점은 OWASP Multifactor Authentication Cheat Sheet에 정리되어 있다.
다중 인증은 복구 경로까지 같은 강도여야 의미가 있다. 두 번째 요소를 잃었을 때 이메일 링크 하나로 다시 설정할 수 있다면, 공격자도 그 길로 들어온다. 복구 코드를 미리 발급해 두거나 요소를 둘 이상 등록하게 하는 이유다.
서버 쪽에서는 공격자가 유출된 비밀번호 목록을 대량으로 넣어 보는 무차별 대입과 크리덴셜 스터핑(사람과 운영 노트)에도 대비한다. OWASP Credential Stuffing Prevention Cheat Sheet는 다중 인증을 가장 강한 방어로 꼽고, 그게 어려우면 여러 겹을 함께 쓰라고 권한다. 실패가 늘수록 단계적으로 늦추는 속도 제한, 새 기기나 수상한 주소에서만 요구하는 추가 인증, 유출된 비밀번호 목록과의 대조, 비밀번호는 맞았는데 두 번째 요소에서 막힌 경우의 사용자 알림이다. IP 차단은 공격자가 수많은 프록시 주소를 돌려 쓰므로 주된 방어가 될 수 없고, 계정을 오래 잠그면 공격자가 남의 계정을 일부러 잠그는 수단이 되므로 잠금은 짧게, 본인 확인과 묶어 둔다.
패스키: 비밀을 보내지 않는 로그인
패스키(passkey)는 공개키 암호로 비밀번호를 대신하는 로그인이다. 웹 표준 이름은 WebAuthn(Web Authentication)이고, 이를 포함한 규격 묶음을 FIDO2라고 부른다. 가입할 때 기기가 그 사이트 전용 키 쌍을 만들어 공개키만 서버에 맡기고, 로그인할 때는 서버가 보낸 무작위 값(챌린지, challenge)에 개인키로 서명해 돌려준다. 공개키 암호의 원리는 암호 노트에 있다.
이 구조에서 세 가지가 따라 나온다. 첫째, 서버에는 공개키만 있어서 서버의 데이터베이스가 유출돼도 로그인에 쓸 비밀이 없다. 둘째, 챌린지가 매번 새로 바뀌어 지난번 응답을 다시 보내는 공격(재전송)이 통하지 않는다. 셋째, 브라우저가 지금 접속한 출처(origin)를 서명할 내용에 넣고 키도 사이트마다 따로 쓰므로, 생김새가 똑같은 가짜 사이트에서는 진짜 사이트용 서명을 얻을 수 없다. 사용자가 속아도 피싱이 성립하지 않는 것이다. 지문이나 얼굴은 기기 안에서 개인키를 꺼내 쓰는 잠금장치일 뿐, 생체 정보가 서버로 가지 않는다.
등록: 인증기가 이 사이트만을 위한 키 쌍을 만들고, 공개키만 서버에 보낸다. 개인키는 기기 밖으로 나가지 않는다.
패스키는 기기 하나에 묶인 것(보안 키)과 운영체제 계정이나 비밀번호 관리자를 통해 여러 기기로 동기화되는 것이 있다. 동기화 패스키는 휴대폰을 잃어도 되찾을 수 있는 대신, 그 동기화 계정의 보안이 중요해진다. 개념과 지원 현황은 FIDO Alliance의 패스키 소개, 브라우저 API는 MDN의 Web Authentication API 문서에 있다.
세션과 토큰: 로그인 상태를 기억하는 두 방식
HTTP는 요청마다 따로 논다. 한 번 로그인한 뒤에도 요청마다 "아까 그 사람"임을 알려야 하는데, 방식은 크게 둘이다. 세션(session)은 서버가 로그인 상태를 저장해 두고 브라우저에는 추측할 수 없는 무작위 번호(세션 ID)만 쿠키로 준다. 서버는 요청마다 그 번호로 저장소를 찾아본다. 자체 포함 토큰은 "이 사람은 민지, 15분 뒤 만료"라는 내용 자체를 서명해서 건네고, 서버는 저장소를 찾지 않고 서명만 확인한다. 대표 형식이 RFC 7519의 JWT(JSON Web Token)다. JWT의 내용은 base64url로 적혀 있을 뿐 암호화된 것이 아니어서 누구나 읽을 수 있다.
| 함정 | 무엇이 문제인가 | 대책 |
|---|---|---|
| 로그인 후에도 같은 세션 ID | 로그인 전에 심어 둔 번호가 로그인 뒤에도 유효하면 남이 그 세션을 이어 쓴다(세션 고정) | 로그인·권한 변경 때 세션 ID를 새로 발급한다 |
| 자바스크립트가 읽는 곳에 보관 | localStorage에 둔 토큰은 XSS 한 번이면 통째로 빠져나간다 | HttpOnly·Secure·SameSite 쿠키에 둔다(웹 보안 노트) |
| 토큰 서명 검사가 느슨함 | 토큰이 스스로 밝힌 알고리즘을 그대로 믿거나 서명 없는 토큰(alg: none)을 받아들이면 위조된다 | 서버가 쓸 알고리즘과 키를 미리 정해 두고, 발급자·대상·만료를 모두 확인한다 |
| 무를 수 없는 긴 토큰 | 로그아웃하거나 기기를 잃어도 만료 전까지 유효하다 | 액세스 토큰은 짧게, 오래 가는 갱신 토큰(refresh token)은 서버에서 무를 수 있게 둔다 |
| 로그인 뒤의 쿠키를 훔친다 | 다중 인증은 로그인할 때만 묻는다. 정보 탈취 악성코드나 중간에서 중계하는 피싱 프록시가 로그인 뒤의 세션 쿠키를 가져가면 다중 인증을 다시 거치지 않고 들어온다(MITRE ATT&CK T1539) | 세션 수명을 줄이고, 결제·비밀번호 변경 같은 민감한 작업 앞에서 다시 인증하고, 갑자기 바뀐 위치·기기를 감시한다. 로그인 단계는 피싱에 버티는 패스키로 막는다 |
어느 쪽이 더 안전하다기보다 쓰임이 다르다. 한 서비스 안의 웹 로그인이라면 세션 쿠키가 단순하고 무르기도 쉽다. 여러 서비스가 같은 신원을 확인해야 하거나 서버가 저장소를 공유하기 어려울 때 토큰이 쓸모 있다. 세션 관리 전반은 OWASP Session Management Cheat Sheet, JWT의 안전한 사용법은 RFC 8725(JWT Best Current Practices)에 있다.
OAuth 2.0과 OpenID Connect: 비밀번호를 건네지 않고 권한을 빌려준다
"구글 계정으로 계속하기"나 "이 앱이 내 캘린더를 읽도록 허용"의 뒤에는 OAuth 2.0(RFC 6749)이 있다. 예전에는 다른 서비스의 데이터를 쓰려면 그 서비스의 비밀번호를 앱에 알려 줘야 했다. OAuth는 사용자가 인가 서버에서 직접 동의하면 앱이 범위(scope)와 기한이 정해진 액세스 토큰만 받게 한다. 앱은 비밀번호를 끝내 보지 못하고, 사용자는 언제든 그 앱의 권한만 거둘 수 있다.
이름 그대로 OAuth는 인가 규격이다. 액세스 토큰은 "이 토큰을 든 쪽에 캘린더 읽기를 허락한다"는 뜻일 뿐 "이 사람이 민지다"라는 증명이 아니다. 로그인에 쓰려면 그 위에 얹은 OpenID Connect(OIDC)가 필요하다. OIDC는 같은 흐름에서 누가 언제 어느 앱을 위해 로그인했는지 적어 서명한 ID 토큰을 함께 준다. 자세한 규칙은 OpenID Connect Core 1.0에 있다.
회사에서 한 번 로그인으로 메일, 메신저, 사내 시스템에 모두 들어가는 것을 단일 로그인(SSO, single sign-on)이라 한다. 로그인을 맡는 신원 공급자(IdP, identity provider)가 신원을 확인하고, 각 서비스(SP, service provider)는 IdP가 서명해 준 증명만 믿는다. 새 서비스는 OIDC를 많이 쓰고, 기업용 SaaS에서는 XML로 쓴 서명된 주장(assertion)을 주고받는 SAML 2.0(2005년 OASIS 표준)도 여전히 흔하다. SSO는 비밀번호를 하나로 줄이고 퇴사자 계정을 한곳에서 끊게 해 주지만, 그만큼 IdP 계정 하나가 모든 문의 열쇠가 되므로 IdP 로그인에 가장 강한 다중 인증을 건다.
여러 흐름 가운데 지금 권장되는 것은 인가 코드 흐름(authorization code flow)에 PKCE(Proof Key for Code Exchange, RFC 7636)를 더한 것이다. 인가 코드는 브라우저 주소를 거쳐 앱에 오므로 도중에 새어 나갈 수 있다. PKCE는 앱이 처음에 비밀 값의 해시만 보내고 코드를 토큰으로 바꿀 때 원래 값을 보여 주게 해서, 코드만 가로챈 쪽은 토큰을 받지 못하게 한다. 해시를 되돌릴 수 없다는 성질이 여기서도 쓰인다.
앱이 매번 새 무작위 code_verifier(dBjftJeZ4C…)를 만들고, 그 SHA-256 값인 code_challenge(E9Melhoa2O…)를 계산해 둔다.
2025년에 나온 RFC 9700(OAuth 2.0 Security Best Current Practice)은 그동안 드러난 문제를 모아 정리했다. 토큰을 주소에 바로 실어 보내던 암묵적 흐름(implicit)과 앱이 사용자 비밀번호를 직접 받는 흐름(password grant)은 쓰지 않고, 모든 클라이언트에 PKCE를 쓰며, 돌아올 주소(redirect URI)는 미리 등록한 값과 정확히 같을 때만 받아들이라는 것이 요지다.
인가 모델: 역할, 속성, 그리고 객체마다 확인하기
권한 규칙을 적는 방식은 몇 가지 틀로 나뉜다. 서비스가 작을 때는 역할 하나로 충분하지만, 조직이 커지고 데이터마다 주인이 생기면 사용자·자원·상황의 속성을 함께 보게 된다. 속성 기반 모델은 NIST SP 800-162가 개념을 정리했다.
| 모델 | 판단 기준 | 예 | 잘 맞는 곳 |
|---|---|---|---|
| ACL(접근 제어 목록) | 자원마다 허락된 사용자 목록 | 이 문서는 민지와 준호가 편집 가능 | 파일 공유처럼 자원마다 따로 정할 때 |
| RBAC(역할 기반) | 사용자의 역할 | 관리자는 모든 주문을 본다 | 직무가 분명한 조직, 관리 화면 |
| ABAC(속성 기반) | 사용자·자원·환경의 속성 조합 | 같은 부서 사람이 업무 시간에만 본다 | 규칙이 세밀하고 자주 바뀌는 곳 |
| 관계 기반(ReBAC) | 사용자와 자원 사이의 관계 | 폴더를 공유받으면 안의 파일도 본다 | 공유와 소유가 얽힌 협업 서비스 |
어떤 모델을 쓰든 가장 흔한 사고는 확인을 빠뜨리는 것이다. 주소나 요청에 들어 있는 번호(/orders/1002)만 보고 데이터를 내주면, 로그인한 누구든 번호를 바꿔 남의 데이터를 볼 수 있다. 이를 IDOR(Insecure Direct Object Reference, 안전하지 않은 직접 객체 참조)라고 한다. 번호를 추측하기 어렵게 바꾸는 것은 보조 수단일 뿐이고, 해법은 요청마다 서버에서 "이 사용자가 이 객체에 이 일을 해도 되는가"를 확인하는 것이다.
OWASP Top 10에서 접근 통제 실패(Broken Access Control)가 첫째 자리에 있는 이유도 이 확인이 기능마다 흩어져 빠지기 쉽기 때문이다.
| 원칙 | 뜻 |
|---|---|
| 기본은 거부 | 허락하는 규칙에 걸리지 않으면 거부한다. 새 기능이 규칙을 잊어도 열리지 않는다 |
| 서버에서 확인 | 버튼을 숨기는 것은 화면 정리일 뿐이다. 요청은 누구나 직접 보낼 수 있다 |
| 요청마다, 객체마다 | 목록에서 한 번 거른 것으로 끝내지 않고, 읽기·수정·삭제 요청마다 그 객체의 주인과 권한을 본다 |
| 한 곳에 모으기 | 권한 판단을 공용 함수나 미들웨어로 모아, 기능마다 제각각 구현하다 빠뜨리지 않게 한다 |
| 최소 권한 | 필요한 만큼만 준다(보안의 기초) |
실무 점검 목록은 OWASP Authorization Cheat Sheet와 OWASP IDOR Prevention Cheat Sheet에 있다.
- Authentication — Wikipedia
- Password Storage Cheat Sheet — OWASP
- SP 800-63B Authentication and Authenticator Management — NIST
- RFC 9106 Argon2 Memory-Hard Function — IETF
- PHC string format — Password Hashing Competition
- argon2-cffi API reference
- RFC 9807 The OPAQUE Augmented PAKE Protocol — IETF
- Multifactor Authentication Cheat Sheet — OWASP
- Passkeys — FIDO Alliance
- Web Authentication API — MDN
- Session Management Cheat Sheet — OWASP
- RFC 7519 JSON Web Token — IETF
- RFC 8725 JWT Best Current Practices — IETF
- RFC 6749 The OAuth 2.0 Authorization Framework — IETF
- RFC 7636 Proof Key for Code Exchange — IETF
- RFC 9700 OAuth 2.0 Security Best Current Practice — IETF
- OpenID Connect Core 1.0 — OpenID Foundation
- SP 800-162 Guide to ABAC — NIST
- Authorization Cheat Sheet — OWASP
- Insecure Direct Object Reference Prevention Cheat Sheet — OWASP
- Credential Stuffing Prevention Cheat Sheet — OWASP
- T1539 Steal Web Session Cookie — MITRE ATT&CK
- Security Assertion Markup Language (SAML) — OASIS