.NET에서 Twilio Verify API를 사용해 TOTP 기반 패스워드리스 인증을 구현하는 방법을 단계별로 설명한다. 비밀번호 없이 인증하는 방식의 개념부터 QR 코드 등록, 코드 검증까지 3단계 아키텍처를 Razor Pages 기반으로 완성한다.
핵심 포인트- 패스워드리스 인증은 TOTP, SMS, 패스키 등을 활용해 비밀번호 없이 로그인하며 보안과 편의성을 동시에 확보한다.
- Twilio Verify API로 TOTP Factor를 생성하고 검증하는 3단계 흐름(사용자명 제출 → QR 코드 등록 → 코드 검증)을 구현한다.
- QRCoder 라이브러리로 서버에서 QR 코드를 Data URI로 직접 생성해 인증 앱 등록에 활용한다.
- 시드 생성에 RandomNumberGenerator.GetBytes(20)를 사용해 cryptographically secure 난수를 확보한다.
- .NET 9 Razor Pages에 DotNetEnv로 환경변수를 관리하고 세션으로 Factor 상태를 유지한다.
상세 정리- 배경: 비밀번호 유출·피싱에 취약한 전통 인증을 대체하기 위해 TOTP 기반 패스워드리스 방식을 Twilio Verify로 구현한다.
- 3단계 흐름: 사용자명 제출로 Factor 생성 → QR 코드 스캔 후 첫 TOTP 코드 검증 → 이후 로그인마다 코드 검증.
- 프로젝트 셋업: dotnet new razor로 Razor Pages 앱 생성, Twilio/QRCoder/DotNetEnv NuGet 패키지를 설치한다.
- Factor 생성: RandomNumberGenerator.GetBytes(20)로 20바이트 랜덤 생성 후 hex 변환하고, 앞 32자를 seed로 사용한다(Twilio 8~64자 요건 충족).
- NewFactorResource.Create() 호출로 Factor를 생성하고, 반환된 OTP URI를 QRCoder로 Base64 Data URI로 변환해 img 태그에 삽입한다.
- 세션 관리: friendly name, Factor SID, URL, OTP URI를 세션에 저장해 Challenge 단계에서 재사용한다.
- Factor 검증: FactorResource.Update()에 초기 6자리 코드를 전달해 Factor를 "verified" 상태로 전환한다.
- 이후 로그인: ChallengeResource.Create()로 Challenge 생성 후 사용자 제출 코드로 검증하고 성공·실패 메시지를 표시한다.
- 코드 포맷 강제: input의 pattern="[0-9]{6}"으로 클라이언트 측에서 6자리 숫자 입력을 강제한다.
- 환경변수: TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN, TWILIO_VERIFY_SERVICE_SID를 .env 파일에 관리하고 DotNetEnv.Env.Load()로 로드한다.
왜 읽나.NET 애플리케이션에 TOTP 기반 패스워드리스 인증을 도입하려는 백엔드 개발자에게 Twilio Verify의 Factor 생성부터 코드 검증까지 전 흐름을 따라가는 실습 레퍼런스.