이 페이지는 자동 번역되었습니다. 영어 원문은 여기.

Passkeys 치트시트. passkey 프로그램을 위한 실무 가이드, 도입 패턴, KPI.
2024년의 디지털 기업에게 안전하고 단순한 사용자 인증을 제공하는 것은 필수입니다. 새로운 로그인 표준인 패스키는 이러한 요구 사항을 충족하는 이상적인 솔루션입니다. 그러나 패스키가 사용자에게 제공하는 향상된 사용자 경험과 보안은 개발자로서 이를 구현할 때 대가가 따릅니다. 구현이 어려운 이유는 패스키가 사용자뿐만 아니라 개발자에게도 비교적 새로운 기술이며, 비밀번호 기반 인증에 비해 구현이 상당히 까다로울 수 있기 때문입니다. 실제로 비밀번호 인증에는 API 엔드포인트 1개가 필요한 반면, 패스키 인증에는 최소 4개의 API 엔드포인트가 필요합니다.
패스키 인증을 제공하기 위한 서버 측 핵심 구성 요소 중 하나는 **WebAuthn 서버(녹색 라이브러리 부분)**입니다. WebAuthn 서버가 보다 광범위한 엔터프라이즈 스택 통합에 어떻게 부합하는지에 대한 포괄적인 가이드는 관련 전문 기사를 참조하세요.
출처: Yubico
이 블로그 게시물에서는 여러 WebAuthn 서버 라이브러리 / 패키지 / SDK를 비교하고, 차이점을 분석하며, 패스키 구현이 처음인 개발자를 위한 권장 사항을 제공합니다.
우선 WebAuthn 서버 라이브러리가 왜 필요한지 더 잘 이해하기 위해 패스키를 구현하는 방법을 살펴보겠습니다. 원칙적으로 웹사이트와 앱에 패스키를 통합하는 방법에는 두 가지가 있습니다.
서드파티 패스키 솔루션은 통합하기 쉽고 일반적으로 많은 엔지니어링 시간(특히 엣지 케이스, 유지 보수, 복구, 대체 수단 및 개선된 패스키 UX의 경우)을 절약해주지만, 일부 개발자는 모든 것을 직접 구현하는 것을 선호합니다.
라이브 데모에서 passkeys를 체험하세요.
직접 구현(DIY)하는 패스키 방식이 어떻게 작동하는지 살펴보겠습니다. 아주 기본적인 설정에서는 등록(가입) 및 인증(로그인) 메커니즘이 필요합니다. WebAuthn 의식(ceremony)이라고도 불리는 이 두 프로세스는 전반적인 흐름이 비슷한 스키마를 따르지만 다르게 처리됩니다.
PublicKeyCredentialCreationOptions 및 PublicKeyCredentialRequestOptions라고 합니다. 이 WebAuthn 매개변수에서 가장 중요한 부분 중 하나는 챌린지입니다. 그런 다음 WebAuthn 매개변수가 프론트엔드로 다시 전송됩니다.모든 가입/로그인 프로세스에는 이러한 단계가 포함되므로 백엔드는 사용자, 패스키 및 가입/로그인 요청을 추적해야 합니다.
Igor Gjorgjioski
Head of Digital Channels & Platform Enablement, VicRoads
We hit 80% mobile passkey activation across 5M+ users without replacing our IDP.
See how VicRoads scaled passkeys to 5M+ users — alongside their existing IDP.
Read the case study패스키의 작동 방식과 서드파티 패스키 솔루션을 사용하지 않는 간단한 구현 모습에 대해 더 깊이 알고 싶다면 여기에서 블로그 기사를 살펴볼 수 있습니다.
실제 시나리오에서 패스키를 직접 구현할 때는 단순히 필요한 API 엔드포인트와 가입 및 로그인을 위한 기본 구현을 제공하는 것에 그치지 않는다는 점을 명심하세요. 그 외에도 다음 주제와 사용 사례를 해결해야 합니다.
그러나 기본 패스키 구현의 경우 WebAuthn 표준만 준수하면 됩니다. 널리 알려지고 지원되는 WebAuthn 서버 라이브러리를 구현하는 것만으로도 대개 충분합니다. 라이브러리는 WebAuthn 서버 매개변수를 생성하고 로그인 챌린지를 검증하여 본질적으로 개발자 대신 암호화 및 가장 복잡한 부분을 처리합니다.
업데이트와 지원을 위해 Passkeys Community에 참여하세요.
분석된 모든 WebAuthn 서버 라이브러리는 패스키 인증을 제공하는 데 필요한 기능을 갖추고 있습니다. 따라서 당사는 다음 기준에 특별히 주의를 기울였습니다.
다음 WebAuthn 서버 라이브러리가 분석되었습니다(2023년 12월 기준 GitHub 별 수 내림차순).
실제로 얼마나 많은 사람이 passkeys를 쓰는지 확인하세요.
type UserModel = { id: string; username: string; currentChallenge?: string; }; /** * 인증자는 특정 UserModel을 참조하는 외래 키를 가지며, 자체 DB 테이블을 갖는 것을 강력히 권장합니다. * * 아래의 "SQL" 태그는 컬럼 데이터 타입과 * 등록 중 받은 데이터를 어떻게 저장하여 후속 인증에서 사용할지에 대한 제안입니다. */ type Authenticator = { // SQL: base64url로 인코딩한 후 `TEXT`로 저장합니다. 이 컬럼에 인덱스를 생성하세요 credentialID: Uint8Array; // SQL: 원본 바이트를 `BYTEA`/`BLOB` 등으로 저장합니다... credentialPublicKey: Uint8Array; // SQL: 일부 인증자는 원자적 타임스탬프를 카운터로 반환하므로 `BIGINT`를 고려하세요 counter: number; // SQL: `VARCHAR(32)` 또는 유사한 타입, 현재 가능한 가장 긴 값은 12자입니다 // Ex: 'singleDevice' | 'multiDevice' credentialDeviceType: CredentialDeviceType; // SQL: `BOOL` 또는 지원되는 유사한 타입 credentialBackedUp: boolean; // SQL: `VARCHAR(255)`이며 문자열 배열을 CSV 문자열로 저장합니다 // Ex: ['usb' | 'ble' | 'nfc' | 'internal'] transports?: AuthenticatorTransport[]; };
public class StoredCredential { /// <summary> /// 공개 키 자격 증명 소스의 자격 증명 ID입니다. /// </summary> public byte[] Id { get; set; } /// <summary> /// 공개 키 자격 증명 소스의 자격 증명 공개 키입니다. /// </summary> public byte[] PublicKey { get; set; } /// <summary> /// 공개 키 자격 증명 소스를 사용하는 의식(ceremony)의 인증자 데이터에서 가장 최근 서명 카운터 값입니다. /// </summary> public uint SignCount { get; set; } /// <summary> /// 공개 키 자격 증명 소스가 등록될 때 getTransports()에서 반환된 값입니다. /// </summary> public AuthenticatorTransport[] Transports { get; set; } /// <summary> /// 공개 키 자격 증명 소스가 생성될 때의 BE 플래그 값입니다. /// </summary> public bool IsBackupEligible { get; set; } /// <summary> /// 공개 키 자격 증명 소스를 사용하는 의식의 인증자 데이터에서 가장 최근 BS 플래그 값입니다. /// </summary> public bool IsBackedUp { get; set; } /// <summary> /// 공개 키 자격 증명 소스가 등록될 때 attestationObject 속성의 값입니다. /// 이를 저장하면 Relying Party가 나중에 자격 증명의 증명 상태를 참조할 수 있습니다. /// </summary> public byte[] AttestationObject { get; set; } /// <summary> /// 공개 키 자격 증명 소스가 등록될 때 clientDataJSON 속성의 값입니다. /// 위의 attestationObject 항목과 함께 이를 저장하면 Relying Party가 나중에 증명 서명을 재검증할 수 있습니다. /// </summary> public byte[] AttestationClientDataJson { get; set; } public List<byte[]> DevicePublicKeys { get; set; } public byte[] UserId { get; set; } public PublicKeyCredentialDescriptor Descriptor { get; set; } public byte[] UserHandle { get; set; } public string AttestationFormat { get; set; } public DateTimeOffset RegDate { get; set; } public Guid AaGuid { get; set; } }
<?php declare(strict_types=1); namespace App\Entity; use App\Repository\PublicKeyCredentialSourceRepository; use DateTimeImmutable; use Doctrine\DBAL\Types\Types; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Uid\AbstractUid; use Symfony\Component\Uid\Uuid; use Webauthn\PublicKeyCredentialSource as BasePublicKeyCredentialSource; use Webauthn\TrustPath\TrustPath; #[ORM\Table(name: 'pk_credential_sources')] #[ORM\Entity(repositoryClass: PublicKeyCredentialSourceRepository::class)] class PublicKeyCredentialSource extends BasePublicKeyCredentialSource { #[ORM\Column(type: Types::DATETIME_IMMUTABLE)] public readonly DateTimeImmutable $createdAt; #[ORM\Id] #[ORM\Column(type: Types::STRING, length: 255)] #[ORM\GeneratedValue(strategy: 'NONE')] private string $id; public function __construct( string $publicKeyCredentialId, string $type, array $transports, string $attestationType, TrustPath $trustPath, AbstractUid $aaguid, string $credentialPublicKey, string $userHandle, int $counter ) { $this->id = Uuid::v4()->toRfc4122(); $this->createdAt = new DateTimeImmutable(); parent::__construct($publicKeyCredentialId, $type, $transports, $attestationType, $trustPath, $aaguid, $credentialPublicKey, $userHandle, $counter); } public function getId(): string { return $this->id; } }
discouraged, preferred, required 값을 가지는 UserVerificationRequirement 매개변수 대신 webauthn4j는 boolean 변수로 verificationRequired와 userPrecenseRequired를 제공합니다.다음 표는 WebAuthn 서버 라이브러리의 개요를 제공합니다.
최신 뉴스를 위해 Passkeys Substack을 구독하세요.
대부분의 라이브러리가 동일하게 강력하고 WebAuthn 표준을 구현하므로 다음 결정 트리를 권장합니다.
아직 특정 프로젝트가 없이 전반적인 WebAuthn 서버에 대해 더 알아보고 싶은 경우, 라이브러리마다 문서나 예제 구현 같은 보충 자료에 차이가 있으므로 몇 가지 권장 사항을 드릴 수 있습니다. 패스키 구현 여정을 시작하고 싶어 하는 소프트웨어 개발자를 위해 다음 구현을 선택할 것을 권장합니다.
서버 측에서 WebAuthn이 작동하는 방식에 대해 더 깊이 이해하고 싶다면 WebAuthn RFC에서 새로운 자격 증명 등록(7.1) 및 인증 어설션 검증(7.2)을 위해 구현해야 하는 모든 단계를 자세히 설명하는 'WebAuthn Relying Party Operations' 섹션을 매우 상세하게 읽어볼 수 있습니다.
본인의 특정 패스키 및 WebAuthn 요구 사항을 평가하세요. 이 블로그 게시물에서는 검색 가능한 자격 증명(discoverable credentials)으로만 패스키를 지원하길 원한다고 가정했습니다. PublicKeyCredentialCreationOptions 및 PublicKeyCredentialRequestOptions를 클라이언트 측 navigator.credentials.create() 및 navigator.credentials.get() WebAuthn API 호출과 함께 읽어보고, 귀하의 사용 사례에 맞게 WebAuthn 서버 SDK 환경 설정에서 매개변수를 올바르게 지정하세요.
모든 WebAuthn 서버 라이브러리에서 다음 정보에 지속적으로 액세스하려면 적절한 데이터베이스 구조를 제공해야 합니다.
일부 라이브러리에는 구체적인 권장 사항과 예제가 있습니다(유용하다고 판단된 내용은 위에 제공했습니다). 어떤 WebAuthn 필드를 어디에 저장해야 하는지 완전히 이해하는 것이 필수적입니다. 사용자 ID(user.id)에 사용할 값을 식별하는 데 특별한 주의를 기울이세요. 자세한 설명은 여기를 참조하세요. 또한 사용자가 패스키를 삭제할 때 발생하는 상황도 고려하세요. 이 외에도 특정 인증자의 사용을 선택적으로 제한할 수 있습니다. 패스키와 관련된 유효한 인증자 목록은 여기에서 찾을 수 있습니다. 보안 키의 증명을 지원하고 확인하려는 경우 이는 완전히 다른 차원의 이야기입니다. 자세한 정보는 여기에서 찾을 수 있습니다.
사용자가 패스키 및 대체 인증 방법을 사용할 기기를 파악하세요. 사용자가 어떤 기기, 브라우저 및 운영 체제를 사용하는지 확실하지 않은 경우 State of Passkeys에서 플랫폼, 브라우저 및 운영 체제 전반의 패스키 준비(passkey-readiness)에 관한 최신 데이터를 확인하세요. 특정 기기의 패스키 도입 및 패스키 준비 점유율에 대해 구체적인 질문이 있다면 언제든지 저희에게 문의해 주세요. 이 주제에 대해 추가 인사이트를 제공하고 도움을 드리겠습니다(패스키 준비 상태와 관련한 당사의 최신 블로그 게시물도 참조하세요). 관측성 측면에서 볼 때, 클라이언트 측 WebAuthn 실패와 서버 검증 거절을 별도의 스트림으로 유지하세요. 클라이언트 측 버킷 정의에는 WebAuthn 오류를 사용하세요. 또한 Windows 10 및 Linux의 경우 이들 운영 체제가 패스키 지원을 최소한으로 제공(지원하는 경우조차)하므로 전용 솔루션을 마련해야 한다는 점을 염두에 두어야 합니다.
실제로 얼마나 많은 사람이 passkeys를 쓰는지 확인하세요.
오늘날 거의 모든 언어나 프레임워크에는 잘 확립된 WebAuthn 서버 라이브러리가 존재합니다. 다양한 언어의 라이브러리를 비교해 보면 특정 구현의 명확한 우월성은 없습니다. 오히려 가장 익숙한 프레임워크 / 프로그래밍 언어를 사용하는 것이 좋습니다. 또는 WebAuthn을 직접 구현하고 수반되는 모든 사항을 직접 관리하고 싶지 않다면 Corbado와 같이 사전 구축된 전용 패스키 인증 솔루션을 사용해 볼 수 있습니다. 패스키 중심의 올인원 인증 솔루션인 Corbado는 훌륭한 패스키 인텔리전스, 세션 관리 및 대체 인증 방법을 제공하므로 제품 개발에만 집중하고 인증은 맡겨둘 수 있습니다. 사용 수 제한 없이 여기에서 무료로 사용해 볼 수 있습니다.
Corbado는 대규모로 consumer authentication을 운영하는 CIAM 팀을 위한 Authentication Intelligence Platform입니다. IDP 로그와 일반 analytics 도구가 보여주지 못하는 것을 볼 수 있게 해드립니다: 어떤 디바이스, OS 버전, 브라우저, credential manager가 passkey를 지원하는지, 왜 등록이 로그인으로 이어지지 않는지, WebAuthn 플로우가 어디서 실패하는지, OS나 브라우저 업데이트가 언제 조용히 로그인을 망가뜨리는지 — Okta, Auth0, Ping, Cognito 또는 자체 IDP를 교체하지 않고도 전부 파악할 수 있습니다. 두 가지 제품: Corbado Observe는 passkey 및 다른 모든 로그인 방식에 대한 observability를 더합니다. Corbado Connect는 analytics가 내장된 managed passkey를 제공합니다 (기존 IDP와 함께). VicRoads는 Corbado로 500만+ 사용자에게 passkey를 운영하고 있습니다 (passkey 활성화율 +80%). Passkey 전문가와 상담하기 →
먼저 특정 프레임워크용 라이브러리가 있는지 확인한 다음, 프로그래밍 언어용 라이브러리가 있는지 확인하세요. 나열된 모든 라이브러리가 WebAuthn 표준을 동일하게 구현하므로, 라이브러리 간의 기능 차이보다는 기존 스택에 대한 친숙도를 우선시하여 선택해야 합니다.
최소한 자격 증명, 사용자, 챌린지 및 인증자를 유지해야 합니다. 사용자 ID(userHandle)로 할당할 값에 세심한 주의를 기울이고, 사용자가 기기에서 패스키를 삭제할 수 있는 시나리오를 계획하세요.
WebAuthn 서버 라이브러리는 PublicKeyCredentialCreationOptions 및 PublicKeyCredentialRequestOptions 매개변수를 생성하고 서명된 챌린지를 검증하는 등 가장 복잡한 암호화 작업을 처리합니다. 처음부터 이를 올바르게 수행하는 것은 이미 테스트와 감사를 거친 FIDO 준수 라이브러리를 사용하는 것보다 훨씬 어렵습니다.
Windows 10과 Linux는 패스키 지원이 가장 부족하므로 이러한 플랫폼의 사용자를 위한 전용 대체 솔루션이 필요합니다. 클라이언트 측 WebAuthn 실패와 서버 검증 거부를 별도의 스트림으로 모니터링하면 프로덕션 환경에서 OS별 문제를 식별하는 데 도움이 됩니다.
관련 글
목차