WebAuthn(Web Authentication)은 W3C와 FIDO Alliance가 정의한 비밀번호 없는 강력 인증 표준이다. FIDO2 프로젝트의 핵심 구성요소로, 공개키 암호화를 기반으로 한다.
FIDO2 구성
FIDO2
├── WebAuthn (W3C 표준): 브라우저-서버 API
└── CTAP2 (Client To Authenticator Protocol 2)
: 기기-인증장치 통신
인증장치(Authenticator):
- 플랫폼 인증장치: Touch ID, Face ID, Windows Hello
- 로밍 인증장치: YubiKey, Google Titan Key
등록(Registration) 흐름
javascript
// 서버: 챌린지 생성
const options = await generateRegistrationOptions({
rpName: 'My App',
rpID: 'app.example.com',
userID: userId,
userName: 'user@example.com',
challenge: crypto.randomBytes(32),
authenticatorSelection: {
authenticatorAttachment: 'platform', // 내장 인증장치
userVerification: 'required', // 생체/PIN 필수
residentKey: 'required', // Passkey 모드
}
});
// 클라이언트: 등록 실행
const credential = await navigator.credentials.create({
publicKey: options
});
// 서버: 검증 및 공개키 저장
await verifyRegistrationResponse({
response: credential,
expectedChallenge: challenge,
expectedOrigin: 'https://app.example.com',
expectedRPID: 'app.example.com',
});
인증(Authentication) 흐름
javascript
// 서버: 챌린지 생성
const options = await generateAuthenticationOptions({
rpID: 'app.example.com',
challenge: crypto.randomBytes(32),
userVerification: 'required',
});
// 클라이언트: 서명 생성
const assertion = await navigator.credentials.get({
publicKey: options
});
// 서버: 서명 검증
// - challenge 일치 확인
// - counter 증가 확인 (재사용 공격 방지)
// - 공개키로 서명 검증
await verifyAuthenticationResponse({
response: assertion,
expectedChallenge: challenge,
expectedOrigin: 'https://app.example.com',
authenticator: storedAuthenticator,
});
보안 특성
| 속성 | 설명 |
|---|
| 피싱 방지 | 공개키가 도메인에 바인딩 (rpID) |
| 재사용 공격 방지 | 매 인증마다 새 챌린지 사용 |
| 클론 방지 | 서명 카운터 단조 증가 |
| 자격증명 분리 | 사이트별 별도 키페어 |
관련 문서
- •[[passwordless-auth|패스워드리스 인증]]
- •[[tpm|TPM (신뢰 플랫폼 모듈)]]
- •[[certificate-pinning|인증서 피닝]]