우리가 방문하며 사용하는 수많은 웹 사이트는 일반적으로 아이디와 패스워드 로그인을 요구한다. 나아가 안전함을 담보로 특수문자나 대소문자를 포함한 길고 복잡한 패스워드를 요구하고, 그것도 모자라 몇 개월마다 변경하라고 다시 요구한다.
상황이 이렇다 보니 일부 사용자는 패스워드만 별도로 관리해 주는 앱을 쓰거나, 웹 브라우저에서 지원하는 패스워드 관리 기능으로 스스로 불편함을 해결한다. 사회적으로 패스워드 사용을 줄이거나 아예 없애자는 논의가 없는 것은 아니다. 하지만 여전히 패스워드는 널리 쓰이고 있다.
지금처럼 기억하기 어렵고, 유출되기 쉬우며, 공격에도 취약한 패스워드 문제를 해결하기 위해, 2013년 2월 개방형 산업 협회인 FIDO 얼라이언스(Fast IDentity Online Alliance)가 출범한다. 주요 멤버로는 마이크로소프트, 구글, 애플, 아마존 등이 참여하고 있으며, 이곳에서는 UAF, U2F, CTAP, FIDO2 등 인증 표준을 개발해 왔다.

FIDO 얼라이언스는 자신들이 만든 새로운 인증 방식이 웹 브라우저에서 기본적으로 지원되길 원했다.
그래서 2015년 11월 12일, FIDO 2.0 표준을 웹 국제 표준화 기구인 월드 와이드 웹 컨소시엄(W3C)에 공식적으로 제출한다. 이후 W3C는 이를 ‘웹 인증(WebAuthn)’이라는 이름으로, 첫 번째 작업 초안(Working Draft)을 2016년 5월 31일 발표했다. 여러 차례 개정을 거쳐 2019년 3월 4일에는 최종 단계인 W3C 권고안(Recommendation)을 내놓았다.*
*W3C 표준화 재정 단계: W3C 표준화는 1) Working Draft(WD, 초안), 2) Candidate Recommendation (CR, 후보권고안), 3) Proposed Recommendation(PR, 제안권고안), 4) W3C Recommendation(REC, 권고안) 단계를 걸친다. 권고안 제출은 모든 합의가 끝났다는 것을 의미한다.

이 표준은 우리에게는 WebAuthn보다는 패스키(Passkeys)라는 이름으로 알려져 있다. 패스키는 WebAuthn 자격 증명에 대한 사실상의 비기술적 용어로, ‘공개 키 암호화로 보호되는 피싱 저항 신원 증명’을 의미한다.

그렇다면 WebAuthn은 어떻게 구성될까? 이해를 돕기 위해 WebAuthn로 만든 간단한 웹 사이트를 살펴보자. 사용자를 식별하기 위해 이메일 주소를 사용했으며, 신원 증명(credentials)에는 패스키를 사용했다.
아래 화면은 로그인 화면이다. 여기서 주목할 점은 “패스워드 입력란”이 없다는 것이다.

사용자가 자신의 이메일 주소를 입력하고 ‘로그인’ 버튼을 누르면, 웹 브라우저가 패스키 창을 보여준다. 곧이어 지문으로 본인 인증을 마치면 추가 절차 없이 바로 시스템에 로그인된다.

이러한 WebAuthn을 구성하는 요소는 크게 인증기(Authenticator), 웹 브라우저, 신뢰 당사자(Relying party) 세 가지다.
사용자가 특정 웹 사이트, 즉 신뢰 당사자로 로그인을 시도하면 해당 사이트는 웹 브라우저에 디지털 서명(digital signatures)을 요청한다. 웹 브라우저는 신뢰 당사자로부터 받은 요청 정보를 인증기에 전달하고, 사용자가 지문이나 PIN, 얼굴 인식 등으로 본인 확인을 마치면 인증기는 내부 개인 키로 서명해 웹 브라우저에 전달한다. 이 정보는 다시 신뢰 당사자로 전달되는 과정을 거친다.

이처럼 WebAuthn은 디지털 서명을 통해 사용자의 신원을 확인한다. 인증기는 이 디지털 서명에 필요한 키를 저장하는 역할을 맡는다.
WebAuthn W3C 표준에서는 서명에 필요한 키를 저장하는 방법을 명시하지 않았기 때문에, 다양한 인증기를 사용할 수 있다. 대표적으로 운영체제 수준에서는 애플의 키체인(Apple Keychain), 마이크로소프트의 윈도우즈 헬로(Windows Hello)가 있다. 또, 구글 계정과 연동해 사용할 수 있는 구글 비밀번호 관리자도 있다. 이러한 이유로 사용자 환경에 따라 웹 브라우저가 보여주는 패스키 창은 서로 달라진다. 나는 터치 아이디(Touch ID)를 지원하는 맥북에서 구글 크롬 브라우저를 사용하고 있기 때문에, 앞서 예시로 본 패스키 창이 나타난 것이다.
WebAuthn은 웹 사이트별로 고유한 자격 증명을 보장하며, 인증 과정에서 사용자의 생체 정보(지문, 얼굴 등)는 브라우저나 신뢰 당사자로 전송되지 않는다. 인증기 내부에서만 사용할 뿐이다. 신뢰 당사자는 오직 전달받은 공개 키만을 이용해 웹 브라우저가 보낸 서명이 유효한지 여부만 검증한다.
이번에는 더 구체적으로 WebAuthn이 어떻게 동작하는지 자세히 살펴보자. 사용자가 웹 사이트에 회원 가입하고, 로그인하는 예시와 함께 보겠다.
회원 가입

사용자가 위의 회원 가입 화면에서 이메일과 이름을 입력한 뒤 ‘Sign Up’을 누르면, WebAuthn을 적용한 환경에서는 아래 회원 가입 순차도로 표현한 과정이 실행된다.

이 과정을 한마디로 요약하면, 사용자가 입력한 정보(이메일, 이름)와 함께 패스키를 등록하겠다는 것이다. 여기서 ‘패스키를 등록한다’는 것은 인증기에 웹 서버 도메인과 연결된 개인 키(Private Key)와 공개 키(Public Key)를 생성하고, 이 중 공개 키를 웹 서버 데이터베이스에 저장한다는 것을 의미한다.
이 과정에서는 서로 챌린지(Challenge)를 주고받는다. 챌린지는 서버가 생성한 일회용 무작위 난수로, 보안 측면에서 재전송 공격(Replay attack)을 방지하기 위한 요소이며 인증의 안전함을 보장해 준다. 그림으로 그린 순차도는 다소 복잡해 보일 수 있지만, 사용자 입장에서는 이메일과 이름을 입력하고(순차도 1번) 지문이나 얼굴, PIN 등으로 본인 확인을 하는 것(순차도 5번)만 거치기 때문에 인증이 굉장히 단순하게 느낄 것이다.
사용자가 회원 가입에서 패스키 등록을 마치면, 패스키로 로그인을 할 수 있는 준비가 끝난다.

로그인

위 로그인 화면에서 사용자가 이메일을 입력하고 ‘로그인’을 누르면, 아래 로그인 순차도에 표현된 과정이 실행된다.

로그인 절차는 패스키 인증 과정으로, 웹 브라우저는 인증기가 개인 키로 서명한 정보(순차도 7번)를 웹 서버로 전송하고(순차도 8번), 웹 서버는 회원 가입 시 등록해 둔 공개 키로 해당 서명을 검증한다(순차도 9번).
패스키는 도메인과 한 쌍으로 관리되므로, 가짜 낚시 사이트(Phishing)에서는 키를 생성하거나 사용할 수 없다. 또한 앞서 언급했듯이 사용자의 지문 정보나 생성된 개인 키는 기기 네트워크를 통해 웹 서버로 전송되지 않는다. 웹 서버에는 오직 서명을 검증하기 위한 ‘공개 키’만 있을 뿐이다.
여기까지 읽어온 독자, 특히 개발자인 독자라면, 이를 적용하려면 어디를 어떻게 구현해야 할지 궁금할 것이다. 순차도를 기준으로 개발할 영역과 아닌 영역으로 나눠 보자. 붉은색으로 표시한 곳이 개발 영역이다.


다만 붉은색으로 표시한 영역도 전부 개발할 필요는 없다. 인증기에 키 등록이나 서명을 요청하는 부분, 서버에서 생성하는 챌린지와 공개 키 검증 같은 절차는 공개된 라이브러리로 구현을 대체할 수 있기 때문이다.
따라서 개발자는 웹 서버와 웹 페이지 간의 상호작용(예: API 호출), 사이트마다 달라지는 사용자 식별 정보(이메일, 이름 등)에 집중해 개발해도 좋다. 아래에서 다양한 언어로 구현된 WebAuthn 라이브러리와 예시를 확인할 수 있다.

언러닝(Unlearning). 배운 것을 의도적으로 잊으며 새로운 시도를 하는 것을 뜻하는 단어다. 내가 웹 애플리케이션을 처음 개발했을 때는 2010년이다. 당시에는 아이디와 비밀번호로 로그인하는 방식에 의문을 제기하는 사람이 아무도 없었다. 그러나 이제는 더 이상 ‘안전함’을 담보 잡아 사용자에게 불편을 강요해서는 안 된다.
물론 WebAuthn에도 여러 한계는 있다. 대표적으로 이는 2019년에 W3C 권고안이 되었기 때문에, 아직 사용할 수 있는 기기에 제약이 있다. 그렇다고 이런 한계만을 이유로 WebAuthn을 배제하기보다는, 사용자에게 선택지를 제공하며 점진적인 변화를 만들어 가보는 것은 어떨까.

©️요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.