Chrome 128 및 129에는 패스키 기반 인증 시스템을 빌드하는 기본 API인 WebAuthn에 새롭고 흥미로운 기능이 도입되었습니다.
- 힌트: 힌트를 사용하면 신뢰 당사자 (RP)가 브라우저에서 WebAuthn UI를 더 효과적으로 제어할 수 있습니다. 보안 키를 사용하려는 기업 사용자에게 특히 유용합니다.
- 관련 출처 요청: 관련 출처 요청을 사용하면 RP가 여러 도메인에서 패스키를 유효하게 만들 수 있습니다. 이제 여러 사이트를 소유하고 있다면 사용자가 사이트 전체에서 패스키를 재사용하도록 하여 로그인 문제가 발생하지 않도록 할 수 있습니다.
- JSON 직렬화: JSON 직렬화 API를 사용하면 WebAuthn API 간에 전달되는 옵션과 사용자 인증 정보를 인코딩 및 디코딩하여 RP의 프런트엔드 코드를 간소화할 수 있습니다.
힌트
이제 hints
를 통해 신뢰 당사자 (RP)가 패스키를 만들거나 패스키로 인증하기 위한 UI 환경설정을 지정할 수 있습니다.
이전에는 RP가 사용자가 패스키를 만들거나 인증하는 데 사용할 수 있는 인증자를 제한하려는 경우 authenticatorSelection.authenticatorAttachment
를 사용하여 "platform"
또는 "cross-platform"
를 지정할 수 있었습니다. 각각 인증자를 플랫폼 인증자 또는 로밍 인증자로 제한합니다.
hints
를 사용하면 이 사양을 더 유연하게 만들 수 있습니다.
RP는 PublicKeyCredentialCreationOptions
또는 PublicKeyCredentialRequestOptions
에서 선택적 hints
를 사용하여 배열의 환경설정 순서로 "security-key"
, "client-device"
, "hybrid"
를 지정할 수 있습니다.
다음은 "security-key"
를 힌트로 사용하는 "cross-platform"
인증자를 선호하는 사용자 인증 정보 생성 요청의 예입니다. 이렇게 하면 Chrome에 엔터프라이즈 사용자를 위한 보안 키 중심 UI를 표시하라는 신호가 전달됩니다.
const credential = await navigator.credentials.create({
publicKey: {
challenge: *****,
hints: ['security-key'],
authenticatorSelection: {
authenticatorAttachment: 'cross-platform'
}
}
});
RP가 교차 기기 인증 시나리오의 우선순위를 지정하려는 경우 "hybrid"
를 힌트로 사용하는 "cross-platform"
인증자를 선호하는 인증 요청을 전송할 수 있습니다.
const credential = await navigator.credentials.create({
publicKey: {
challenge: *****,
residentKey: true,
hints: ['hybrid']
authenticatorSelection: {
authenticatorAttachment: 'cross-platform'
}
}
});
관련 출처 요청
관련 출처 요청을 사용하면 RP가 여러 도메인에서 패스키를 사용할 수 있도록 할 수 있습니다. 중앙 집중식 로그인 환경을 구축하고 제휴 프로토콜을 사용하는 것이 대부분의 사이트에 권장되는 솔루션입니다. 하지만 여러 도메인을 소유하고 있고 제휴가 불가능한 경우 관련 출처가 해결책이 될 수 있습니다.
모든 WebAuthn 요청은 신뢰 당사자 ID(RP ID)를 지정해야 하며 모든 패스키는 단일 RP ID와 연결됩니다. 기존에는 출처가 도메인을 기반으로만 RP ID를 지정할 수 있었으므로 이 경우 www.example.co.uk
는 example.co.uk
의 RP ID를 지정할 수 있지만 example.com
는 지정할 수 없습니다. 관련 출처 요청을 사용하면 타겟 도메인에서 /.well-known/webauthn
에 있는 잘 알려진 JSON 파일을 가져와서 소유권 주장이 제기된 RP ID를 확인할 수 있습니다. 따라서 example.co.uk
(및 example.in
, example.de
등)은 모두 example.com
가 다음 형식으로 지정하는 경우 example.com
의 RP ID를 사용할 수 있습니다.
URL: https://example.com/.well-known/webauthn
{
"origins": [
"https://example.co.uk",
"https://example.de",
"https://example.sg",
"https://example.net",
"https://exampledelivery.com",
"https://exampledelivery.co.uk",
"https://exampledelivery.de",
"https://exampledelivery.sg",
"https://myexamplerewards.com",
"https://examplecars.com"
]
}
관련 출처 요청을 사용하여 사이트 전반에서 패스키 재사용 허용에서 관련 출처 요청을 설정하는 방법을 알아보세요.
JSON 직렬화
WebAuthn 요청 및 응답 객체에는 사용자 인증 정보 ID, 사용자 ID, 챌린지와 같이 ArrayBuffer에 원시 바이너리 데이터가 포함된 여러 필드가 있습니다. 웹사이트에서 JSON을 사용하여 이 데이터를 서버와 교환하려면 먼저 바이너리 데이터를 Base64URL 등으로 인코딩해야 합니다. 이로 인해 웹사이트에서 패스키 사용을 시작하려는 개발자에게 불필요한 복잡성이 추가됩니다.
이제 WebAuthn은 JSON에서 직접 PublicKeyCredentialCreationOptions
및 PublicKeyCredentialRequestOptions
WebAuthn 요청 객체를 파싱하고 PublicKeyCredential 응답을 JSON으로 직접 직렬화하는 API를 제공합니다. 원시 바이너리 데이터를 전송하는 모든 ArrayBuffer 값 필드는 Base64URL 인코딩된 값으로 또는 Base64URL 인코딩된 값에서 자동으로 변환됩니다.
이 API는 Chrome 129부터 사용할 수 있습니다.
패스키를 만들기 전에 서버에서 JSON으로 인코딩된 PublicKeyCredentialCreationOptions
객체를 가져와 PublicKeyCredential.parseCreationOptionsFromJSON()
를 사용하여 디코딩합니다.
export async function registerCredential() {
// Fetch encoded `PublicKeyCredentialCreationOptions`
// and JSON decode it.
const options = await fetch('/auth/registerRequest').json();
// Decode `PublicKeyCredentialCreationOptions` JSON object
const decodedOptions = PublicKeyCredential.parseCreationOptionsFromJSON(options);
// Invoke the WebAuthn create() function.
const cred = await navigator.credentials.create({
publicKey: decodedOptions,
});
...
패스키를 만든 후에는 서버로 전송할 수 있도록 toJSON()
를 사용하여 결과 사용자 인증 정보를 인코딩합니다.
...
const cred = await navigator.credentials.create({
publicKey: options,
});
// Encode the credential to JSON and stringify
const credential = JSON.stringify(cred.toJSON());
// Send the encoded credential to the server
await fetch('/auth/registerResponse', credential);
...
패스키로 인증하기 전에 서버에서 JSON 인코딩된 PublicKeyRequestCreationOptions
를 가져와 PublicKeyCredential.parseRequestOptionsFromJSON()
를 사용하여 디코딩합니다.
export async function authenticate() {
// Fetch encoded `PublicKeyCredentialRequestOptions`
// and JSON decode it.
const options = await fetch('/auth/signinRequest').json();
// Decode `PublicKeyCredentialRequestOptions` JSON object
const decodedOptions = PublicKeyCredential.parseRequestOptionsFromJSON(options);
// Invoke the WebAuthn get() function.
const cred = await navigator.credentials.get({
publicKey: options
});
...
패스키로 인증한 후에는 서버로 전송될 수 있도록 toJSON()
메서드를 사용하여 결과 사용자 인증 정보를 인코딩합니다.
...
const cred = await navigator.credentials.get({
publicKey: options
});
// Encode the credential to JSON and stringify
const credential = JSON.stringify(cred.toJSON());
// Send the encoded credential to the server
await fetch(`/auth/signinResponse`, credential);
...
자세히 알아보기
WebAuthn 및 패스키에 관해 자세히 알아보려면 다음 리소스를 확인하세요.