1. 소개
이 섹션은 규범적이지 않습니다.
웹사이트에 로그인하는 것은 생각보다 더 어렵습니다. 사용자 에이전트는 여러 가지 방식으로 경험을 개선할 수 있는 독특한 위치에 있으며, 대부분의 최신 사용자 에이전트는 브라우저 내에 자격 증명 관리 기능을 어느 정도 기본적으로 제공함으로써 이를 인식합니다. 예를 들어, 사용자는 웹사이트의 사용자 이름과 비밀번호를 저장할 수 있으며, 이러한 자격 증명은 이후 로그인 폼에 자동으로 채워지지만, 성공률에는 차이가 있습니다.
autocomplete
속성은 웹사이트가 특정 필드를 "username" 또는 "password"로 표시하여 사용자 에이전트가 로그인 폼을 더 잘 감지하고 채울 수 있도록 돕는 선언적 메커니즘을 제공합니다.
또한, 사용자 에이전트는 이런 세부 정보를 마크업에 제공하지 않은 웹사이트와도 동작할 수 있도록 다양한 감지 휴리스틱을 구현합니다.
이런 휴리스틱과 선언적 감지의 조합은 상대적으로 잘 동작하지만, 현 상태에는 감지에 문제가 있는 큰 공백이 남아 있습니다. 예를 들어, 특이한 로그인 방식(자격 증명을 XMLHttpRequest
[XMLHTTPREQUEST]로 제출하는 등)은 신뢰성 있게 감지하기 어렵고, 사용자가 연합 신원 제공자를 사용해
인증하려는 점점 더 흔한 경우도 마찬가지입니다. 웹사이트가 사용자 에이전트의 자격 증명 관리자와 더 직접적으로 상호작용할 수 있게 하면, 자격 증명 관리자의 정확성을 높일 수 있고,
사용자가 연합 로그인을 할 때도 더 잘 지원할 수 있습니다.
이러한 사용 사례는 § 1.1 사용 사례와 Credential Management: Use Cases and Requirements에서 더 자세히 설명합니다. 이 명세서는 웹사이트가 사용자를 위해 자격 증명을 요청할 수 있고, 사용자가 성공적으로 로그인할 때 사용자 에이전트에 자격 증명을 저장하도록 요청할 수 있는 Credential Manager API를 정의하여, 해당 문서의 많은 요구 사항을 해결하려고 시도합니다.
참고: 여기 정의된 API는 의도적으로 작고 단순합니다. 자체적으로 인증을 제공하려는 것이 아니라, 기존 사용자 에이전트에 구현된 자격 증명 관리자에 대한 인터페이스만 제공합니다. 이 기능은 벤더나 저자가 큰 노력을 들이지 않아도 지금 바로 가치가 있습니다. 물론 앞으로 더 많은 기능을 추가할 수 있습니다. § 9 향후 작업에서 앞으로 탐구할 수 있는 아이디어를 확인하세요.
1.1. 사용 사례
최신 사용자 에이전트는 일반적으로 사용자가 웹사이트에 로그인할 때 비밀번호를 저장할 수 있도록 하고, 사용자가 재방문할 때 로그인 폼에 비밀번호를 완전히 또는 부분적으로 자동으로 채워주는 기능을 제공합니다. 웹사이트 입장에서는 이러한 동작을 전혀 인지하지 못합니다: 비밀번호가 저장되었는지, 채워졌는지 알지 못합니다. 이는 장단점이 있습니다. 한편으로 사용자 에이전트의 비밀번호 관리자는 사이트 협조 여부와 관계없이 동작하므로 사용자에게 매우 좋습니다. 반면, 비밀번호 관리자의 동작은 로그인 폼, 비밀번호 변경 폼 등을 감지하고 채우기 위한 휴리스틱이 뒤섞인 불안정하고 독점적인 조합입니다.
현 상태에서 특히 문제되는 몇 가지가 있습니다:
-
사용자 에이전트는 연합 신원 제공자를 사용하는 사용자를 돕는 데 매우 어려움을 겪습니다. 사용자 이름/비밀번호 폼 제출 감지는 비교적 간단하지만, 제3자를 통한 로그인 감지는 신뢰성 있게 잘 수행하기 어렵습니다. 웹사이트가 전형적인 연합 로그인 동작에 수반되는 리디렉션의 의도를 사용자 에이전트에 알려줄 수 있다면 좋을 것입니다.
-
마찬가지로, 사용자 에이전트는 단순 사용자 이름/비밀번호 폼보다 더 특이한 로그인 메커니즘을 감지하는 데 어려움을 겪습니다. 저자들은 점점 더
XMLHttpRequest
또는 유사한 메커니즘을 통해 비동기적으로 사용자를 로그인시키며, 이는 경험을 개선하고 프레젠테이션을 더 많이 제어하기 위함입니다. 사용자를 위해 좋은 일이지만, 사용자 에이전트가 비밀번호 관리자를 통합하기에는 어렵습니다. 웹사이트가 자신이 사용하는 로그인 메커니즘을 사용자 에이전트가 이해하도록 도울 수 있다면 좋을 것입니다. -
마지막으로, 비밀번호 변경은 웹사이트가 자격 증명이 변경되었음을 명시적으로 사용자 에이전트에 알렸다면 더 잘 지원될 수 있습니다.
2. 핵심 API
개발자 관점에서 자격 증명은 특정
동작의 인증 결정을 내릴 수 있게 하는 객체입니다. 이 섹션에서는 Credential
인터페이스를 기반 클래스로 하여, 이 문서 및 다른 문서에서 정의된 자격 증명을 위한 확장 가능한 API 집합과 navigator.credentials.*
를 통해 개발자가 자격 증명을 얻을 수 있도록 정의합니다.
여러 자격 증명 유형은 각각 JavaScript에서 상속을 통해, 직접 또는 간접적으로 Credential
인터페이스를 구현합니다. 이 문서에서는 PasswordCredential
및 FederatedCredential
두 가지 인터페이스를 정의합니다. 다른 명세(예: [WEBAUTHN])는 다른
자격 증명 유형을 정의합니다.
자격 증명은 특정 origin에 대해 유효하다고 합니다. 이는 해당 origin에서 인증으로 받아들여지는 경우를 의미합니다. 자격 증명이 특정 시점에 유효하더라도, 사용자 에이전트는 같은 자격 증명이 앞으로도 계속 유효할 것이라고 가정할 수 없습니다. 그 이유는 다음과 같습니다.
-
비밀번호 자격 증명은 계정 소유자가 비밀번호를 변경하면 더 이상 유효하지 않을 수 있습니다.
-
SMS로 받은 토큰으로 만든 자격 증명은 한 번만 사용할 수 있을 가능성이 높습니다.
일회용 자격 증명은 자격 증명 소스에서 생성되며, 이는 개인키, 연합 계정 접근, 특정 전화번호로 SMS를 받을 수 있는 능력 등일 수 있습니다. 자격 증명 소스는 JavaScript에 노출되지 않으며, 이 명세에서 명시적으로 표현되지 않습니다. 모델을 통합하기 위해, 비밀번호 자체를 하나의 자격 증명 소스로 간주하며, 이는 비밀번호 자격 증명을 만들기 위해 단순히 복사됩니다.
UA는 유효한 자격 증명이 두 번째 사용에서도 유효할 것이라거나, 유효한 자격 증명을 생성한 자격 증명 소스가 앞으로도 유효한 자격 증명을 지속적으로 생성할 수 있으리라고 가정할 수
없지만, 후자가 전자보다 더 가능성이 높습니다. 과거에 유효했던 자격 증명을 (store()
를 통해) 기록함으로써, UA는 앞으로 사용자가 사용할 수 있는 유효한 자격 증명 소스를 더 잘 제공할 수 있게
됩니다.
2.1. 인프라스트럭처
사용자 에이전트는 내부적으로 자격 증명 저장소를 반드시 제공해야 하며, 이는 벤더별 불투명 저장 메커니즘으로 어떤 자격 증명이 유효했는지를 기록합니다. 이는 자격 증명 접근 및 영속성을 위한 다음 기능을 제공합니다:
-
자격 증명 저장 후에 검색할 수 있도록 합니다. 이 기능은 자격 증명을 받아 자격 증명 저장소에 삽입합니다.
-
자격 증명 목록 검색. 임의의 필터를 받아 해당 필터와 일치하는 자격 증명들의 집합을 반환합니다.
또한 자격 증명
저장소는 origin에 대해 silent access 방지
플래그를 유지해야 하며, 해당 플래그는 특별히
명시되지 않는 한 true
로 설정됩니다.
origin이 해당 플래그가 true
로 설정되어 있으면 사용자 중재 필요 상태입니다.
참고: 사용자 중재의 중요성은 § 5 사용자 중재에서 더 자세히 논의됩니다.
참고: 자격 증명 저장소는 이 문서에서 명세된 API를 구현하는 사용자 에이전트의 내부 구현 세부사항이며, 웹에 직접적으로 노출되지 않습니다. 특정 자격 증명 유형을 지원하기 위해 다른 문서에서 더 많은 기능이 명세될 수 있습니다.
이 문서는 알고리즘 및 본문에 사용되는 여러 기본 개념에 대해 Infra 표준에 의존합니다 [INFRA].
각 environment settings object는 관련 활성 자격 증명 유형을 가지고 있으며, 이는 집합으로, 초기에는 비어 있습니다.
2.1.1. 인프라스트럭처 알고리즘
2.1.1.1. 상위와 동일 출처
environment settings object (settings)가
상위와 동일 출처인 경우, 다음 알고리즘이 true
를 반환합니다:
-
settings의 관련 글로벌 객체에 연결된 Document가 없으면,
false
를 반환한다. -
document를 settings의 관련 글로벌 객체의 연결된 Document로 한다.
-
document에 브라우징 컨텍스트가 없으면
false
를 반환한다. -
origin을 settings의 origin으로 한다.
-
navigable을 document의 node navigable로 한다.
-
navigable이 null이 아닌 parent를 가질 때 반복한다:
-
navigable을 navigable의 parent로 설정한다.
-
navigable의 active document의 origin이 origin과 동일 출처가 아니면,
false
를 반환한다.
-
-
true
를 반환한다.
2.1.2. 자격 증명 유형 레지스트리
이 레지스트리는 자격 증명 유형 (예: [[type]]
값)을 해당 유형에 연관된 다양한 값에 매핑합니다. 예시: 옵션 멤버 식별자 (공식적으로 딕셔너리 멤버 식별자)로, CredentialCreationOptions
및 CredentialRequestOptions
(즉, "options dictionaries")에서 명세됩니다.
참고: 이 레지스트리는 관련 자격 증명 인터페이스 객체 알고리즘에서 사용됩니다.
자격 증명 유형 (알파벳 순) | 옵션 멤버 식별자 | 적절한 인터페이스 객체 | Get Permissions Policy | Create Permissions Policy | 명세 | 요청자 연락처 |
---|---|---|---|---|---|---|
digital-credential | digital | DigitalCredential
| digital-credentials-get | null | [DIGITAL-CREDENTIALS] | WICG |
federated | federated | FederatedCredential
| null | null | 이 명세서: § 4 연합 자격 증명 | W3C |
identity | identity | IdentityCredential
| identity-credentials-get | null | [FEDCM] | W3C |
otp | otp | OTPCredential
| otp-credentials | null | [WEB-OTP] | WICG |
password | password | PasswordCredential
| null | null | 이 명세서: § 3 비밀번호 자격 증명 | W3C |
public-key | publicKey | PublicKeyCredential
| publickey-credentials-get | publickey-credentials-create | [WEBAUTHN] | W3C |
2.1.2.1. 등록 항목 요구사항 및 갱신 프로세스
-
각 레지스트리 항목은 딕셔너리 멤버 식별자(레지스트리에서는 옵션 멤버 식별자로 알려짐)를 명시해야 하며, 이는
CredentialCreationOptions
및CredentialRequestOptions
의 확장에서 사용됩니다. -
각 레지스트리 항목은 적절한 인터페이스 객체 식별자를 해당 자격 증명 유형에 대해 명시해야 합니다.
-
각 레지스트리 항목은 Get Permissions Policy 권한을 명시해야 하며, 이는 자격 증명 요청 시 사용하거나, 명시되지 않은 경우 null로 설정합니다.
-
각 레지스트리 항목은 Create Permissions Policy 권한을 명시해야 하며, 이는 자격 증명 생성 시 사용하거나, 명시되지 않은 경우 null로 설정합니다.
-
각 레지스트리 항목에는 자격 증명 유형 및 딕셔너리 멤버 식별자를 정의하는 공개 명세에 대한 링크가 포함되어야 합니다.
-
각 레지스트리 항목의 명세에는 요청자 연락처 정보가 포함되어야 합니다.
이 레지스트리의 갱신은 자격 증명 유형의 항목 추가, 변경 또는 삭제입니다. 누구나 webappsec-credential-management 저장소에 풀 리퀘스트로 갱신 요청을 할 수 있습니다. 웹 애플리케이션 보안 작업 그룹에서 다가오는 회의 안건에 올리고 요청자에게 알립니다. 요청의 검토 및 결정은 W3C 웹 애플리케이션 보안 작업 그룹의 합의에 따릅니다. 의장이 결과를 요청자에게 알리고 레지스트리를 갱신합니다.
2.2.
Credential
인터페이스
[Exposed =Window ,SecureContext ]interface {
Credential readonly attribute USVString id ;readonly attribute DOMString type ;static Promise <boolean >isConditionalMediationAvailable ();static Promise <undefined >willRequestConditionalCreation (); };
id
, 타입 USVString, 읽기 전용-
자격 증명의 식별자입니다. 식별자에 대한 요구사항은 각 자격 증명 유형마다 다릅니다. 예를 들어, 사용자 이름/비밀번호 쌍의 경우 사용자 이름을 나타낼 수 있습니다.
type
, 타입 DOMString, 읽기 전용-
이 속성의 getter는 객체의 인터페이스 객체의
[[type]]
슬롯의 값을 반환하며, 이 객체가 나타내는 자격 증명 유형을 지정합니다. isConditionalMediationAvailable()
-
Promise
를 반환하며, 사용자 에이전트가conditional
방식의 자격 증명 요청 중재를 해당 자격 증명 유형에 대해 지원할 때만true
로 resolve됩니다. 그렇지 않으면false
로 resolve됩니다.Credential
의 기본isConditionalMediationAvailable()
구현:-
promise resolved with
false
를 반환한다.
조건부 중재를 지원하는 자격 증명 유형 명세는 반드시 이 함수를 오버라이딩하여 resolve를
true
로 해야 합니다.참고: 이 함수가 없으면,
conditional
방식의 중재는 해당 자격 증명 유형에 대해 지원되지 않습니다. -
willRequestConditionalCreation()
-
Promise
를 반환하며, 사용자 에이전트가conditional
방식의 자격 증명 생성 중재를 해당 자격 증명 유형에 대해 등록한 후에 resolve됩니다.Credential
의 기본willRequestConditionalCreation()
구현:-
promise resolved with
undefined
를 반환한다.
참고: 이 메서드가 없으면,
conditional
방식의 자격 증명 생성 중재는 해당 자격 증명 유형에 대해 지원되지 않습니다. -
[[type]]
-
Credential
인터페이스 객체는[[type]]
이라는 내부 슬롯을 가지며, 이 슬롯에는 자격 증명 유형을 나타내는 문자열이 들어갑니다. 슬롯의 값은 별도의 명시가 없으면 빈 문자열입니다. § 2.1.2 자격 증명 유형 레지스트리에서 자격 증명 유형 목록을 확인할 수 있습니다.참고:
[[type]]
슬롯의 값은 특정 인터페이스를 구현한 모든 자격 증명에서 동일하므로, 개발자는obj.type
을 통해 항상 특정Credential
종류를 구분할 수 있습니다. [[discovery]]
-
Credential
인터페이스 객체는[[discovery]]
라는 내부 슬롯을 가지며, 이는 사용자 에이전트가 특정 유형의 자격 증명을 수집하는 메커니즘을 나타냅니다. 값은 "credential store
" 또는 "remote
"입니다. 전자는 모든 자격 증명 정보가 사용자 에이전트의 자격 증명 저장소에 저장되어 있음을 의미하고, 후자는 사용자 에이전트가 자격 증명 저장소에 명시적으로 표현되지 않은 자격 증명을 외부 기기나 서비스와의 상호작용을 통해 발견할 수 있음을 의미합니다.
Tobie/Dominic에게 인터페이스 객체 관련, 여기와 § 2.5.1 자격 증명 요청 등에서 용어가 맞는지 논의 필요. 인터페이스 프로토타입 객체일 수도?
일부 Credential
객체는 origin에 바인딩됨: 이러한 객체는 [[origin]]
내부 슬롯을 포함하며, origin 정보를 저장하여 해당 Credential
이 유효할 수 있는지
판단합니다.
2.2.1.
Credential
내부 메서드
Credential
인터페이스 객체는 여러 내부 메서드를 제공하며,
자격 증명 객체의 검색 및 저장을 지원합니다. 각 메서드는 아래에서 명시된 대로 기본 "no-op" 구현을 갖습니다.
별도의 명시가 없으면, Credential을 상속하는 인터페이스에 대해 생성된 각 인터페이스
객체는 이 내부 메서드 중 하나 이상을 반드시 구현해야 하며, Credential
의
기본 구현을 오버라이드해야 합니다. 예: § 3.2 PasswordCredential 인터페이스, § 4.1 FederatedCredential 인터페이스, [WEBAUTHN].
2.2.1.1. [[CollectFromCredentialStore]]
내부 메서드
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
는 origin, CredentialRequestOptions
,
그리고 호출자의 environment settings object가 상위와 동일 출처일 때만
true인 boolean과 함께 호출됩니다.
알고리즘은 사용자 에이전트의 자격 증명 저장소에서 옵션에 맞는 Credential
객체 집합을 반환합니다. 일치하는 객체가 없으면 빈 집합을 반환합니다.
Credential
의
기본 [[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
구현:
-
빈 집합을 반환한다.
2.2.1.2. [[DiscoverFromExternalSource]]
내부 메서드
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
는 병렬로 origin, CredentialRequestOptions
객체,
그리고 호출자의 environment settings object가 상위와 동일 출처일 때만
true인 boolean과 함께 호출됩니다.
옵션에 맞는 Credential
을
반환하거나, 자격 증명이 없으면 null
을 반환하거나, 검색 실패(예: 옵션 오류 시 TypeError
등) 시 에러를 throw합니다.
단일 사용 또는 제한된 시간만 유효한 자격 증명 유형의 경우, 이 메서드는 자격 증명 소스를 사용해 새로운 자격 증명을 생성해야 합니다.
Credential
의
기본 [[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
구현:
-
null
을 반환한다.
2.2.1.3. [[Store]]
내부 메서드
[[Store]](credential, sameOriginWithAncestors)
는
병렬로 Credential
과,
그리고 호출자의 environment settings object가 상위와 동일 출처일 때만
true인 boolean과 함께 호출됩니다.
알고리즘은 Credential
이
자격 증명
저장소에 영속화되면 반환됩니다.
Credential
의
기본 [[Store]](credential, sameOriginWithAncestors)
구현:
-
NotSupportedError
를 throw한다.
2.2.1.4. [[Create]]
내부 메서드
[[Create]](origin, options, sameOriginWithAncestors)
는 병렬로 origin, CredentialCreationOptions
,
그리고 호출자의 environment settings object가 상위와 동일 출처일 때만
true인 boolean과 함께 호출됩니다.
알고리즘은 다음 중 하나를 수행합니다:
-
Credential
을 생성하거나, -
자격 증명을 생성하지 않고
null
을 반환하거나, -
예외 상황(예: 옵션 오류 등)에서는
TypeError
등 에러를 throw합니다.
Credential
을
생성할 경우, global object를 받아 인터페이스
객체를 반환하는 알고리즘을 반환합니다. 이 알고리즘은 반드시 task에서 호출되어야 합니다.
참고: 이 알고리즘의 단계는 각 자격 증명 유형별로 정의됩니다.
Credential
의
기본 [[Create]](origin, options, sameOriginWithAncestors)
구현:
-
null
을 반환한다.
2.2.2.
CredentialUserData
믹스인
일부 Credential
객체는 자격 증명 선택기에서
사용자에게 친숙한 이름과 아이콘을 제공하여 사람에게 읽기 쉬운 식별 수단을 제공합니다:
[SecureContext ]interface mixin {
CredentialUserData readonly attribute USVString name ;readonly attribute USVString iconURL ; };
name
, 타입 USVString, 읽기 전용-
자격 증명에 연결된 이름으로, 자격 증명 선택기에 표시되는 사람이 이해할 수 있는 공개 이름입니다.
iconURL
, 타입 USVString, 읽기 전용-
자격 증명을 위한 이미지를 가리키는 URL로, 자격 증명 선택기에 표시됩니다. 해당 URL은 반드시 신뢰할 수 있는 URL이어야 합니다.
2.3.
navigator.credentials
개발자는 Credential
을
가져오고, 자격
증명 저장소와 상호작용하기 위해
CredentialsContainer
인터페이스의 메서드를 사용합니다. 이 인터페이스는 Navigator
객체에 navigator.credentials
로 연결되어 있습니다.
partial interface Navigator { [SecureContext ,SameObject ]readonly attribute CredentialsContainer credentials ; };
credentials
속성은 active document의 browsing context에 연결된 CredentialsContainer
를
반드시 반환해야 합니다.
참고: § 6.3 안전하지 않은 사이트에서 논의한 바와 같이, 자격 증명 관리 API는 Secure Contexts에서만 노출됩니다.
[Exposed =Window ,SecureContext ]interface {
CredentialsContainer Promise <Credential ?>get (optional CredentialRequestOptions options = {});Promise <undefined >store (Credential credential );Promise <Credential ?>create (optional CredentialCreationOptions options = {});Promise <undefined >preventSilentAccess (); };dictionary {
CredentialData required USVString ; };
id
get(options)
-
get()
호출 시, 사용자 에이전트는자격 증명 요청
을options
에 대해 실행한 결과를 반환해야 합니다.CredentialsContainer.get(options) 메서드의 인자. 매개변수 타입 Nullable Optional 설명 options
CredentialRequestOptions
✘ ✔ 요청 범위를 제어하는 속성 집합. store(credential)
-
store()
호출 시, 사용자 에이전트는자격 증명 저장
을credential
에 대해 실행한 결과를 반환해야 합니다.CredentialsContainer.store(credential) 메서드의 인자. 매개변수 타입 Nullable Optional 설명 credential
Credential
✘ ✘ 저장할 자격 증명. create(options)
-
create()
호출 시, 사용자 에이전트는자격 증명 생성
을options
에 대해 실행한 결과를 반환해야 합니다.CredentialsContainer.create(options) 메서드의 인자. 매개변수 타입 Nullable Optional 설명 options
CredentialCreationOptions
✘ ✔ Credential
생성을 위한 옵션. preventSilentAccess()
-
preventSilentAccess()
호출 시, 사용자 에이전트는 암묵적 접근 방지를 현재 settings object에 대해 실행한 결과를 반환해야 합니다.참고: 이 함수는 로그아웃 버튼 클릭 후 사이트가 사용자의 세션 정보를 업데이트하고
navigator.credentials.preventSilentAccess()
를 호출하는 등, origin에서 사용자가 로그아웃했음을 신호합니다. 이는 silent access 방지 플래그를 설정하여, 다음 방문 시 자격 증명이 자동으로 반환되지 않게 합니다.참고: 이 함수는 이전에는
requireUserMediation()
로 불렸으며, deprecated로 간주해야 합니다.
Navigator
객체(navigator)가 생성될 때, 사용자 에이전트는 navigator의 relevant Realm을 사용하여 새로운 CredentialsContainer
객체를 생성하고, navigator에 연결해야 합니다. 2.3.1. CredentialRequestOptions
딕셔너리
Credential
을
get()
으로
가져오기 위해, 호출자는 CredentialRequestOptions
객체에 몇 가지 매개변수를 지정합니다.
참고: CredentialRequestOptions
딕셔너리는 확장 포인트입니다. 옵션이 필요한 새로운 자격 증명 유형이 도입될 경우, 그 딕셔너리 타입이 추가되어 요청 시 전달할 수 있게 됩니다. § 8.2 확장 포인트 참고.
dictionary {
CredentialRequestOptions CredentialMediationRequirement mediation = "optional";AbortSignal signal ; };
mediation
, 타입 CredentialMediationRequirement, 기본값"optional"
-
이 속성은 특정 자격 증명 요청에 대한 중재 요구 사항을 지정합니다. 각 enum 값의 의미는 아래
CredentialMediationRequirement
에서 설명합니다. 처리 세부 내용은 § 2.5.1 자격 증명 요청에 정의되어 있습니다. signal
, 타입 AbortSignal-
이 속성을 사용하면 개발자가 진행 중인
get()
연산을 중단할 수 있습니다. 중단된 연산은 일반적으로(중단이 연산 완료 후에 수신된 경우) 정상적으로 완료되거나, 중단 이유(abort reason)와 함께 reject될 수 있습니다.
unmediated
라는 불리언 멤버를 정의했습니다. true
로 설정하면 mediation
값이
"silent
"
가 되고, false
로 설정하면
mediation
값이 "optional
"가
됩니다.
unmediated
는 deprecated로 간주해야 하며, 새로운 코드는 mediation
를
사용해야 합니다.
CredentialCreationOptions
또는 CredentialRequestOptions
(options)에 대해 관련 자격 증명 인터페이스 객체는 다음과 같이
수집된 인터페이스 객체 집합입니다:
참고: 이 알고리즘은 자격 증명 유형 레지스트리를 사용합니다.
-
settings를 현재 settings object로 한다.
-
options의 각 optionKey → optionValue에 대해:
-
credentialInterfaceObject를 적절한 인터페이스 객체(settings의 global object에서), 해당 옵션 멤버 식별자가 optionKey인 것으로 한다.
-
Assert: credentialInterfaceObject의
[[type]]
슬롯 값은 자격 증명 유형과 같아야 하며, 해당 옵션 멤버 식별자가 optionKey이다. -
credentialInterfaceObject를 relevant interface objects에 추가한다.
-
-
relevant interface objects를 반환한다.
CredentialRequestOptions
(options)이 사전에 일치
가능(matchable a priori)하려면, 다음 단계가 true
를 반환해야 합니다:
-
options의 관련 자격 증명 인터페이스 객체 각각에 대해:
-
interface의
[[discovery]]
슬롯 값이 "credential store
"가 아니면,false
를 반환한다.
-
-
true
를 반환한다.
참고: get(options)
실행 시, 사용자 중재 없이 자격 증명을
반환하는 것은
주어진 CredentialRequestOptions
이 사전에 일치 가능할 때만입니다. 외부 서비스(OAuth 토큰,
보안키 인증기 등)에서 검색이 필요한 자격 증명 유형이 요청되면, 사용자 중재가 반드시 필요하며, 연합 신원 제공자, BTLE 기기 등을 선택하여 검색 프로세스를 안내해야 합니다.
2.3.2. 중재 요구사항
get(options)
또는 create(options)
호출 시, 개발자는 사용자 중재 요구사항을
CredentialMediationRequirement
열거형 값으로 개별적으로 설정할 수 있습니다.
참고: § 5 사용자 중재에서 개념 및 origin별 요청 처리 방식에 대해 더 자세히 설명합니다.
enum {
CredentialMediationRequirement "silent" ,"optional" ,"conditional" ,"required" };
silent
-
해당 작업에 대해 사용자 중재가 억제됩니다. 사용자의 개입 없이 작업을 수행할 수 있으면 그대로 진행됩니다. 사용자의 개입이 필요하다면, 작업은 사용자를 개입시키지 않고
null
을 반환합니다.참고: 주로 "이 사이트에 계속 로그인 유지" 시나리오를 지원하기 위한 것으로, 사용자가 자동 로그인을 원할 때 자격 증명을 조용히 얻고, 로그인 창을 사용자에게 보여줄 필요가 없을 때 사용됩니다.
optional
-
사용자 중재 없이 자격 증명을 넘길 수 있으면 넘깁니다. 사용자 중재가 필요하면, 사용자 에이전트가 사용자를 개입시킵니다.
참고:
get()
의 기본 동작이며, 사용자가 로그인 작업을 시작할 것으로 기대되는 경우에 적합합니다. 예를 들어, 사용자가 "로그인"을 클릭했다면 자격 증명 선택기가 나타나도 당황하지 않습니다. conditional
-
get()
의 경우, 발견된 자격 증명은 요청하는 origin 정보를 함께 비모달 다이얼로그로 사용자에게 보여집니다. 사용자가 다이얼로그 외부에서 제스처를 취하면 다이얼로그가 닫히고,Promise
는 resolve/reject되지 않으며, 사용자에게 보이는 에러도 발생하지 않습니다. 사용자가 자격 증명을 선택하면, 해당 자격 증명이 호출자에게 반환됩니다. silent access 방지 플래그는 실제 값과 관계없이 항상true
로 간주됩니다:conditional
동작은 조건에 맞는 자격 증명이 발견된 경우 항상 사용자 중재가 포함됩니다.자격 증명이 발견되지 않으면, 사용자 에이전트는 자격 증명 유형에 따라 사용자가 행동을 취하도록 안내할 수 있습니다(예: 자격 증명이 들어있는 기기를 삽입하도록 안내). 어떤 경우든
get()
메서드는 자격 증명이 없다고 바로null
로 resolve되면 안 됩니다—웹사이트에 자격 증명 없음이 노출되지 않도록 하기 위함입니다.웹사이트는 참조하는 자격 증명 인터페이스가 모두
isConditionalMediationAvailable()
를 오버라이드하여Promise
가true
로 resolve되어야conditional
을get()
에 전달할 수 있습니다.create()
의 경우, 사용자가 이전에 자격 증명 생성에 동의했고, 사용자 에이전트가 최근에 인증을 중재한 것을 알고 있으면 추가적인 모달 인터랙션 없이create()
가 resolve될 수 있습니다. 최근 인증 중재 이력이 없거나 자격 증명 생성 동의가 없다면, 호출은 "NotAllowedError
"DOMException
을 throw해야 합니다. required
-
사용자 에이전트는 사용자 중재 없이 자격 증명을 전달하지 않습니다. 이는 origin의 silent access 방지 플래그가 해제되어 있어도 마찬가지입니다.
참고: 이 요구사항은 재인증 또는 사용자 전환 시나리오를 지원하기 위한 것입니다. 또한, 이 요구사항은 특정 작업에만 적용되며 origin의 silent access 방지 플래그에는 영향을 주지 않습니다. 해당 플래그를 설정하려면
preventSilentAccess()
를 호출해야 합니다.
2.3.2.1. 예시
get()
을 호출하고, mediation
멤버를
"silent
"로
설정하여 전달합니다.
이로써, § 5.2 사용자 중재 요구에 따라 자동 로그인을 허용한 사용자는 로그인되고, 허용하지 않은 사용자는
자격 증명 선택기가 뜨는
혼란을 겪지 않게 됩니다:
window.addEventListener('load', async () => { const credentials = await navigator.credentials.get({ ..., mediation: 'silent' }); if (credentials) { // 성공! 해당 자격 증명으로 사용자를 로그인 처리 } });
document.querySelector('#sign-in').addEventListener('click', async () => { const credentials = await navigator.credentials.get({ ..., mediation: 'optional' }); if (credentials) { // 성공! 해당 자격 증명으로 사용자를 로그인 처리 } });
참고: MegaCorp, Inc.는 mediation
멤버를 생략할 수도 있으며, 기본값은 "optional
"입니다.
get()
호출 시 mediation
멤버를
"required
"로
설정하여 반드시 사용자 중재를 요구할 수 있습니다:
참고: 브라우저나 자격 증명 유형에 따라, 사용자는 마스터 비밀번호 입력, 지문 스캔 등 인증을 해야 자격 증명이 웹사이트에 전달될 수 있습니다.
document.querySelector('#important-form').addEventListener('submit', async () => { const credentials = await navigator.credentials.get({ ..., mediation: 'required' }); if (credentials) { // |credentials|가 접근을 허용하는지 확인하고, 허용하지 않으면 제출을 취소 } else { e.preventDefault(); } });
get()
을 mediation
멤버를
"required
"로
설정하여, "계정 추가" 버튼 클릭 시 자격 증명이 자동 반환되지 않게 할 수 있습니다:
document.querySelector('#switch-button').addEventListener('click', e => { var c = await navigator.credentials.get({ ..., mediation: 'required' }); if (c) { // |c|로 사용자 로그인 처리 } });
2.4. CredentialCreationOptions
딕셔너리
Credential
을 create()
로 생성하기 위해, 호출자는 CredentialCreationOptions
객체에 몇 가지 매개변수를 지정합니다.
참고: CredentialCreationOptions
딕셔너리는 확장 포인트입니다. 새로운 자격 증명 유형이 도입되면 이 딕셔너리에 추가되어 생성 메서드에 전달할 수 있습니다. § 8.2 확장 포인트 및 이 문서에서 도입된 확장: § 3.2 PasswordCredential 인터페이스와 § 4.1 FederatedCredential 인터페이스 참고.
dictionary {
CredentialCreationOptions CredentialMediationRequirement = "optional";
mediation AbortSignal signal ; };
signal
, 타입 AbortSignal-
이 속성은 개발자가 진행 중인
create()
연산을 중단할 수 있게 합니다. 중단된 연산은 일반적으로(중단이 연산 완료 후에 수신된 경우) 정상적으로 완료되거나, 중단 이유(abort reason)와 함께 reject될 수 있습니다.
2.5. 알고리즘
2.5.1. Credential
요청
Credential
요청 알고리즘은 CredentialRequestOptions
(options)를 받아, Promise
를 반환하며, 명확하게 얻을 수 있으면 Credential
으로 resolve되고, 그렇지 않으면 null
로 resolve됩니다.
-
settings를 현재 settings object로 한다.
-
Assert: settings는 보안 컨텍스트이다.
-
document를 settings의 관련 글로벌 객체의 연결된 Document로 한다.
-
document가 완전히 활성화된 상태가 아니면, "
InvalidStateError
"DOMException
으로 promise를 reject하여 반환한다. -
options.
이 aborted 상태라면,signal
options.
의 중단 이유로 promise를 reject하여 반환한다.signal
-
interfaces를 options의 관련 자격 증명 인터페이스 객체로 한다.
-
interfaces가 빈 집합이면, "
NotSupportedError
"DOMException
으로 promise를 reject하여 반환한다. -
interfaces의 각 interface에 대해:
-
options.
mediation
이conditional
이고, interface가conditional
사용자 중재를 지원하지 않으면, "TypeError
"DOMException
으로 promise를 reject하여 반환한다. -
만약 settings의 활성 자격 증명 타입들이 포함하고 있다면 interface의
[[type]]
, "a promise rejected with" "NotAllowedError
"DOMException
을 반환한다. -
추가 interface의
[[type]]
를 settings의 활성 자격 증명 타입에.
-
-
origin을 settings의 origin으로 한다.
-
sameOriginWithAncestors를 settings가 상위와 동일 출처일 때
true
, 아니면false
로 한다. -
options의 관련 자격 증명 인터페이스 객체 각각에 대해:
-
permission을 interface의
[[type]]
Get Permissions Policy로 한다. -
permission이 null이면, 다음으로 진행.
-
document가 permission 사용 허가가 아니라면, "
NotAllowedError
"DOMException
으로 promise를 reject하여 반환한다.
-
-
p를 새 promise로 한다.
-
다음 단계를 병렬로 실행:
-
credentials를 자격 증명 저장소에서
Credential
수집의 결과로, origin, options, sameOriginWithAncestors를 인자로 호출. -
credentials가 exception이면, p를 해당 예외로 reject한다.
-
다음 모든 조건이 참이면 p를 credentials[0]으로 resolve하고 남은 단계를 생략:
-
credentials의 크기가 1이다
-
origin이 사용자 중재 필요하지 않음
-
options가 사전에 일치 가능하다.
-
options.
mediation
이 "conditional
"가 아니다.
이 모델이 잘못됐을 수 있음. username/password와 webauthn 스타일 자격 증명 중 하나를 사이트가 받아들이길 원할 때, 사용자가 전자만 쓰고 로그인 유지 원할 때 선택기를 강제하지 않을 수 있도록 하면 더 좋음.
-
-
options의
mediation
이 "silent
"라면, p를null
로 resolve하고 남은 단계를 생략. -
result를 사용자에게
Credential
선택 요청의 결과로, options와 credentials를 인자로 호출. -
result가 인터페이스 객체라면:
-
result를 result의
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
실행 결과로 설정, 인자는 origin, options, sameOriginWithAncestors.예외가 발생하면:
-
던져진 예외 e를 정의.
-
DOM 조작 작업 소스에 task를 큐잉하여 다음 하위 단계를 실행:
-
이 하위 단계를 종료.
-
-
-
Assert: result는
null
또는Credential
이다. -
result가
Credential
이면, p를 result로 resolve. -
result가
null
이고 options.mediation
이conditional
이 아니면, p를 result로 resolve.참고: options.
mediation
이conditional
이고null
자격 증명이 발견되면, promise p는 resolve되지 않습니다.
-
-
-
interfaces의 각 interface에 대해:
-
제거 interface의
[[type]]
를 settings의 활성 자격 증명 타입에서.
-
-
-
p를 반환한다.
2.5.2. 자격 증명 저장소에서 Credential
수집
origin (origin),
CredentialRequestOptions
(options), 그리고 호출 컨텍스트가 상위와 동일 출처일 때만 true
인 boolean
(sameOriginWithAncestors)이 주어지면, 사용자 에이전트는 자격 증명 저장소에서
Credential
수집을 수행할 수 있습니다.
이는 사용자 에이전트가 로컬에 저장한 Credential
객체 집합을 반환하며, options의 필터와 일치하는 객체입니다. 일치하는 Credential
객체가 없으면, 반환되는 집합은 빈 집합입니다:
-
possible matches를 빈 집합으로 한다.
-
options의 관련 자격 증명 인터페이스 객체 각각에 대해:
-
r을 interface의
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
내부 메서드를 origin, options, sameOriginWithAncestors로 실행한 결과로 한다. 예외가 발생하면 해당 예외를 다시 throw한다. -
Assert: r은 인터페이스 객체의 리스트이다.
-
r의 각 c에 대해:
-
c를 possible matches에 추가한다.
-
-
-
possible matches를 반환한다.
2.5.3. Credential
저장
Credential
저장 알고리즘은 Credential
(credential)을 받아, 해당 객체가 자격 증명 저장소에 영속화되면 resolve되는 Promise
를 반환합니다.
-
settings를 현재 settings object로 한다.
-
Assert: settings는 보안 컨텍스트이다.
-
settings의 관련 글로벌 객체의 연결된 Document가 완전히 활성화가 아니면, "
InvalidStateError
"DOMException
으로 promise를 reject하여 반환한다. -
현재 settings object가 상위와 동일 출처이면 sameOriginWithAncestors를
true
, 아니면false
로 한다. -
p를 새 promise로 한다.
-
만약 settings의 활성 자격 증명 타입이 포함하고 있다면 credential의
[[type]]
, "a promise rejected with" "NotAllowedError
"DOMException
을 반환한다. -
추가 credential의
[[type]]
를 settings의 활성 자격 증명 타입에. -
다음 단계를 병렬로 실행:
-
credential의 인터페이스 객체의
[[Store]](credential, sameOriginWithAncestors)
내부 메서드를 credential과 sameOriginWithAncestors로 실행한다.예외가 발생하면:
-
던져진 예외 e를 정의.
-
DOM 조작 작업 소스에 task를 큐잉하여 다음 하위 단계를 실행:
그 외에는, p를
undefined
로 resolve한다. -
-
-
-
제거 credential의
[[type]]
를 settings의 활성 자격 증명 타입에서.
-
-
p를 반환한다.
2.5.4. Credential
생성
Credential
생성 알고리즘은 CredentialCreationOptions
(options)를 받아, Promise
를 반환하며 옵션을 사용해 생성할 수 있으면 Credential
으로 resolve하고, 생성할 수 없으면 Credential
이 null
로 resolve됩니다. 예외적 상황에서는 Promise
가 적절한 예외로 reject될 수 있습니다:
-
settings를 현재 settings object로 한다.
-
Assert: settings는 보안 컨텍스트이다.
-
global을 settings의 global object로 한다.
-
document를 관련 글로벌 객체의 연결된 Document로 한다.
-
document가 완전히 활성화가 아니면, "
InvalidStateError
"DOMException
으로 promise를 reject하여 반환한다. -
현재 settings object가 상위와 동일 출처이면 sameOriginWithAncestors를
true
, 아니면false
로 한다. -
interfaces를 options의 관련 자격 증명 인터페이스 객체 집합으로 한다.
-
아래 항목 중 하나라도 해당되면 promise를 NotSupportedError로 reject하여 반환한다:
-
global에 연결된 Document가 없다.
-
interfaces의 크기가 1보다 크다.
참고: 미래에는 이 제한을 완화하여 여러 자격 증명 유형 중에서 사용자가 선택할 수 있도록 지원할 수 있습니다. 현재로서는 딕셔너리를 하나의 엔트리로 제한합니다.
-
-
interfaces의 각 interface에 대해:
-
permission을 interface의
[[type]]
Create Permissions Policy로 한다. -
permission이 null이면, 다음으로 진행.
-
document가 permission 사용 허가가 아니라면, "
NotAllowedError
"DOMException
으로 promise를 reject하여 반환한다.
-
-
options.
이 aborted 상태라면,signal
options.
의 중단 이유(abort reason)로 promise를 reject하여 반환한다.signal
-
type을 interfaces[0]의
[[type]]
로 한다. -
settings의 활성 자격 증명 유형이 type을 포함하면, "
NotAllowedError
"DOMException
으로 promise를 reject하여 반환한다. -
추가 type을 settings의 활성 자격 증명 타입에.
-
origin을 settings의 origin으로 한다.
-
p를 새 promise로 한다.
-
다음 단계를 병렬로 실행:
-
r을 interfaces[0]의
[[Create]](origin, options, sameOriginWithAncestors)
내부 메서드를 origin, options, sameOriginWithAncestors로 실행한 결과로 한다.예외가 발생하면:
-
던져진 예외 e를 정의.
-
DOM 조작 작업 소스에 task를 큐잉하여 다음 하위 단계를 실행:
-
이 하위 단계를 종료.
-
-
r이
Credential
또는null
이면, p를 r로 resolve하고, 이 하위 단계를 종료. -
Assert: r은 § 2.2.1.4 [[Create]] 내부 메서드에서 정의된 알고리즘이다.
-
DOM 조작 작업 소스에 task를 큐잉하여 다음 하위 단계를 실행:
-
해결 p를 promise-calling r의 결과로, global을 전달하여.
-
-
-
-
제거 type을 settings의 활성 자격 증명 타입에서.
-
-
p를 반환한다.
2.5.5. 암묵적 접근 방지
암묵적 접근 방지 알고리즘은 environment settings object (settings)를 받아,
Promise
를 반환하며 silent access 방지
플래그가 자격 증명 저장소에 영속화되면 resolve됩니다.
-
origin을 settings의 origin으로 한다.
-
settings의 관련 글로벌 객체의 연결된 Document가 완전히 활성화가 아니면, "
InvalidStateError
"DOMException
으로 promise를 reject하여 반환한다. -
p를 새 promise로 한다.
-
다음 단계를 병렬로 실행:
-
origin의 silent access 방지 플래그를 자격 증명 저장소에 설정한다.
-
-
p를 반환한다.
3. 비밀번호 자격 증명
좋든 나쁘든 많은 웹사이트가 사용자 이름/비밀번호 쌍에 인증 메커니즘을 의존합니다.
PasswordCredential
인터페이스는 이런 사용 사례를 지원하기 위한 자격 증명으로, 사용자 이름과 비밀번호를 저장하며,
사용자가 자격 증명 선택기에서
올바른 계정을 선택할 수 있도록 돕는 메타데이터도 함께 저장합니다.
3.1. 예시
3.1.1. 비밀번호 기반 로그인
navigator.credentials.get()
을
사용하여
사용자의 자격
증명 저장소에서 사용자 이름/비밀번호 쌍을 가져올 수 있습니다:
navigator.credentials .get({ 'password': true }) .then(credential => { if (!credential) { // 사용자가 이 사이트에 대한 자격 증명이 없거나 // 공유를 거부한 경우. 기본 로그인 폼으로 폴백하는 코드를 삽입. return; } if (credential.type == 'password') { var form = new FormData(); form.append('username_field', credential.id); form.append('password_field', credential.password); var opt = { method: 'POST', body: form, credentials: 'include' // 쿠키 전송. }; fetch('https://example.com/loginEndpoint', opt) .then(function (response) { if (/* |response|가 성공적인 로그인임을 나타내면 */) { // 해당 자격 증명이 유효했음을 기록합니다. 아래 참고. navigator.credentials.store(credential); // 로그인 성공을 사용자에게 알림! 다양한 로그인 후 기능 수행! // location.href = '/signed-in-experience' 등으로 랜딩 페이지로 이동? } else { // 기본 로그인 폼으로 폴백하는 코드를 삽입. } }); } });
또한, 웹사이트는 자격 증명 데이터를
form
에 복사하고 submit()
으로 제출할 수도 있습니다:
navigator.credentials .get({ 'password': true }) .then(credential => { if (!credential) { return; // 위와 동일... } if (credential.type === 'password') { document.querySelector('input[name=username_field]').value = credential.id; document.querySelector('input[name=password_field]').value = credential.password; document.getElementById('myform').submit(); } });
첫 번째 방법이 훨씬 선호되는데, store()
를 명시적으로 호출하여 자격 증명을 저장하기 때문입니다.
form
기반 방식은 폼 제출에 의존하며, 브라우징 컨텍스트를 이동시키므로 성공적인 로그인 후 store()
호출을 보장하기 어렵습니다.
참고: 사용자 에이전트가 보여주는 자격 증명 선택기는 실제로 현재 origin에 저장되지 않은 자격
증명도 선택할 수 있게 할 수 있습니다. 예를 들어, https://m.example.com
에서 로그인할 때
https://www.example.com
의 자격 증명을 제공하거나(§ 6.1 도메인 간 자격
증명 접근 참고), 사용자가 즉석에서 새로운 자격 증명을 생성할 수 있습니다. 개발자는 자격 증명을 성공적으로 사용할 때마다 store()
를 호출함으로써 이러한 불확실성을 우아하게 처리할 수 있습니다. get()
으로
자격 증명을 받아온 직후에도 마찬가지입니다:
자격 증명이 아직 origin에 저장되어 있지 않으면, 사용자가 저장 여부를 선택할 수 있게 됩니다. 이미 저장되어 있다면, 추가 프롬프트는 표시되지 않습니다.
3.1.2. 로그인 후 확인
사용자가 성공적으로 로그인한 후 새로운 자격 증명 저장을 권장하려면, store()
에 전달하면 됩니다.
fetch()
를 통해 sign-in endpoint에 자격 증명을 제출하여 로그인한 경우,
응답을 확인하여 로그인 성공 여부를 판단하고 사용자 에이전트에 알릴 수 있습니다. 다음과 같은 로그인 폼이 있을 때:
<form action="https://example.com/login" method="POST" id="theForm"> <label for="username">Username</label> <input type="text" id="username" name="username" autocomplete="username"> <label for="password">Password</label> <input type="password" id="password" name="password" autocomplete="current-password"> <input type="submit"> </form>
개발자는 다음과 같은 핸들러로 폼 제출을 처리할 수 있습니다:
document.querySelector('#theForm').addEventListener('submit', e => { if (window.PasswordCredential) { e.preventDefault(); // "submit" 이벤트가 발생한 PasswordCredential을 HTMLFormElement에서 생성: // "username" 및 "current-password" autocomplete 필드 값을 자동으로 읽어들입니다: var c = new PasswordCredential(e.target); // 폼의 action URL로 새 자격 증명을 FormData로 전송. 응답이 성공적이면 사용자 에이전트에 알려, 사용자가 비밀번호를 저장할 수 있도록 합니다: var opt = { method: 'POST', body: new FormData(e.target), credentials: 'include' // 쿠키 전송. }; fetch(e.target.action, opt).then(r => { if (/* |r|이 "성공적인" Response인 경우 */) navigator.credentials.store(c); }); } });
3.1.3. 비밀번호 변경
동일한 저장 메커니즘은 "비밀번호 변경"에도 아무런 수정 없이 재사용할 수 있습니다. 사용자가 자격 증명을 변경하면, 웹사이트는 사용자가 새 자격 증명으로 성공적으로 로그인했음을 사용자 에이전트에 알릴 수 있습니다. 그러면 사용자 에이전트는 저장된 자격 증명을 업데이트할 수 있습니다:
store()
를 새 정보와 함께 호출하여 사용자의 자격 증명을 업데이트할 수 있습니다.
다음과 같은 비밀번호 변경 폼이 있을 때:
<form action="https://example.com/changePassword" method="POST" id="theForm"> <input type="hidden" name="username" autocomplete="username" value="user"> <label for="password">New Password</label> <input type="password" id="password" name="password" autocomplete="new-password"> <input type="submit"> </form>
개발자는 다음과 같이 폼 제출을 처리할 수 있습니다:
document.querySelector('#theForm').addEventListener('submit', e => { if (window.PasswordCredential) { e.preventDefault(); // "submit" 이벤트가 발생한 PasswordCredential을 HTMLFormElement에서 생성: // "username" 및 "new-password" autocomplete 필드 값을 자동으로 읽어들입니다: var c = new PasswordCredential(e.target); // 폼의 action URL로 새 자격 증명을 FormData로 전송. 응답이 성공적이면 사용자 에이전트에 알려, 사용자가 비밀번호를 저장할 수 있도록 합니다: var opt = { method: 'POST', body: new FormData(e.target), credentials: 'include' // 쿠키 전송. }; fetch(e.target.action, opt).then(r => { if (/* |r|이 "성공적인" Response인 경우 */) navigator.credentials.store(c); }); } });
3.2.
PasswordCredential
인터페이스
[Exposed =Window ,SecureContext ]interface :
PasswordCredential Credential {constructor (HTMLFormElement );
form constructor (PasswordCredentialData );
data readonly attribute USVString password ; };PasswordCredential includes CredentialUserData ;partial dictionary CredentialRequestOptions {boolean =
password false ; };
password
, 타입 USVString, 읽기 전용-
이 속성은 자격 증명의 비밀번호를 나타냅니다.
[[type]]
-
PasswordCredential
인터페이스 객체는[[type]]
라는 내부 슬롯을 가지며, 그 값은 "password
"입니다. [[discovery]]
-
PasswordCredential
인터페이스 객체는[[discovery]]
라는 내부 슬롯을 가지며, 그 값은 "credential store
"입니다. PasswordCredential(form)
-
이 생성자는
HTMLFormElement
(form)을 받고 다음 단계를 실행합니다:-
origin을 현재 settings object의 origin으로 한다.
-
r을 HTMLFormElement에서
PasswordCredential
생성의 결과로, form과 origin을 인자로 실행한다. -
그렇지 않으면 r을 반환.
-
PasswordCredential(data)
-
이 생성자는
PasswordCredentialData
(data)를 받고 다음 단계를 실행합니다:-
r을 PasswordCredentialData에서
PasswordCredential
생성 결과로, data에 대해 실행. -
그렇지 않으면 r을 반환.
-
PasswordCredential
객체는 PasswordCredentialData
딕셔너리를 명시적으로 전달하거나,
HTMLFormElement
의
제출 가능한 요소를 기반으로 navigator.credentials.create()
로
생성할 수 있습니다.
dictionary :
PasswordCredentialData CredentialData {USVString ;
name USVString ;
iconURL required USVString ;
origin required USVString ; };
password typedef (PasswordCredentialData or HTMLFormElement );
PasswordCredentialInit partial dictionary CredentialCreationOptions {PasswordCredentialInit ; };
password
PasswordCredential
객체는 origin에
바인딩됩니다.
PasswordCredential
의
인터페이스 객체는 Credential
의
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
구현을 상속하며,
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
,
[[Create]](origin, options, sameOriginWithAncestors)
,
[[Store]](credential, sameOriginWithAncestors)
는
자체적으로 구현합니다.
3.3. 알고리즘
3.3.1.
PasswordCredential
의
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
는 origin (origin), CredentialRequestOptions
(options),
그리고 호출 컨텍스트가 상위와 동일 출처일 때만 true
인 boolean
(sameOriginWithAncestors)과 함께 호출됩니다.
알고리즘은 자격 증명 저장소에서 Credential
객체 집합을 반환합니다. 일치하는 객체가 없으면 빈 집합을 반환합니다.
sameOriginWithAncestors가 true
가 아니면 NotAllowedError
를 throw합니다.
-
sameOriginWithAncestors가
false
면, "NotAllowedError
"DOMException
을 throw한다.참고: 이 제한은 § 6.4 출처 혼동 문제를 해결하기 위한 것입니다.
-
options["
password
"]가true
가 아니면 빈 집합을 반환한다. -
자격 증명 저장소에서 자격 증명 목록 검색의 결과로, 다음 필터 조건을 만족하는 자격 증명들을 반환한다:
-
자격 증명이
PasswordCredential
이다. -
자격 증명의
[[origin]]
이 origin과 동일 출처다.
-
3.3.2. PasswordCredential
의
[[Create]](origin, options, sameOriginWithAncestors)
[[Create]](origin, options, sameOriginWithAncestors)
는 origin (origin), CredentialCreationOptions
(options), 그리고 호출 컨텍스트가 상위와 동일 출처일 때만 true
인 boolean
(sameOriginWithAncestors)과 함께 호출됩니다.
알고리즘은 생성 가능하면 PasswordCredential
을 반환하고, 아니면 null
을 반환합니다. CredentialCreationOptions
딕셔너리는 password
멤버를 반드시 포함해야 하며,
이 멤버는 HTMLFormElement
또는 PasswordCredentialData
여야
합니다.
해당 멤버 값으로 PasswordCredential
을 생성할 수 없으면, 이 알고리즘은 TypeError
예외를 throw합니다.
-
Assert: options["
password
"] 존재하며, sameOriginWithAncestors는 사용하지 않음. -
options["
password
"] 가HTMLFormElement
이면, HTMLFormElement에서PasswordCredential
생성을 options["password
"], origin으로 실행한 결과를 반환한다. 예외가 발생하면 재throw한다. -
options["
password
"] 가PasswordCredentialData
이면, PasswordCredentialData에서PasswordCredential
생성을 options["password
"]로 실행한 결과를 반환한다. 예외가 발생하면 재throw한다.
3.3.3.
PasswordCredential
의 [[Store]](credential, sameOriginWithAncestors)
[[Store]](credential, sameOriginWithAncestors)
는
PasswordCredential
(credential), 그리고 호출 컨텍스트가 상위와 동일 출처일 때만 true
인 boolean
(sameOriginWithAncestors)과 함께 호출됩니다. 알고리즘은 credential이 자격 증명 저장소에 영속화되면
undefined
를 반환합니다.
sameOriginWithAncestors가 true
가 아니면 NotAllowedError
를 반환합니다.
-
sameOriginWithAncestors가
false
면, "NotAllowedError
"DOMException
을 throw하고 사용자 에이전트의 자격 증명 저장소는 변경하지 않는다.참고: 이 제한은 § 6.4 출처 혼동 문제를 해결하기 위한 것입니다.
-
사용자 에이전트의 자격 증명 저장소에
PasswordCredential
(stored) 이 있고,id
속성이 credential의id
와 같고,[[origin]]
슬롯이 credential의[[origin]]
과 동일 출처면:-
사용자가 자격 증명 업데이트를 허용하면(사용자 중재 정의 참고):
그 외에, 사용자가 자격 증명 저장을 허용하면(사용자 중재 정의 참고):
-
자격 증명 저장소에 다음 속성을 가진
PasswordCredential
을 저장한다:id
-
credential의
id
name
,-
credential의
name
iconURL
-
credential의
iconURL
[[origin]]
-
credential의
[[origin]]
password
-
credential의
password
-
3.3.4. HTMLFormElement
에서 PasswordCredential
생성
HTMLFormElement
에서
PasswordCredential
생성 알고리즘은 HTMLFormElement
(form)과 origin (origin)이 주어지면 다음 단계를 실행합니다.
참고: § 3.1.2 로그인 후 확인 및 § 3.1.3 비밀번호 변경에서 사용 예시를 제공합니다.
-
data를 새로운
PasswordCredentialData
딕셔너리로 한다. -
data의
origin
멤버 값을 origin의 값으로 설정한다. -
formData를
FormData
생성자로 form에 대해 실행한 결과로 한다. -
elements를 form의 제출 가능한 요소 중 form owner가 form인 것의 리스트로, 트리 순서로 정렬한다.
-
newPasswordObserved를
false
로 한다. -
elements의 각 field에 대해 아래 단계를 실행:
-
field에
autocomplete
속성이 없으면, 다음 field로 건너뛴다. -
name을 field의
name
속성 값으로 한다. -
formData의
has()
메서드를 name에 대해 실행했을 때false
면, 다음 field로 건너뛴다. -
field의
autocomplete
값에 하나 이상의 자동완성 상세 토큰(tokens)이 포함된다면:-
tokens의 각 token에 대해:
-
token이 아래 문자열 중 하나와 ASCII 대소문자 구분 없이 일치한다면, 해당 절차를 실행:
- "
new-password
" -
data의
password
멤버 값을 formData의get()
메서드를 name에 대해 실행한 결과로 설정하고, newPasswordObserved를true
로 설정한다. - "
current-password
" -
newPasswordObserved가
false
이면, data의password
멤버 값을 formData의get()
메서드를 name에 대해 실행한 결과로 설정.참고: newPasswordObserved가
false
인 경우,new-password
필드가current-password
필드보다 우선함을 의미합니다. - "
photo
" -
data의
iconURL
멤버 값을 formData의get()
메서드를 name에 대해 실행한 결과로 설정. - "
name
"- "
nickname
" - "
- "
username
"
- "
-
-
-
-
c를 PasswordCredentialData에서
PasswordCredential
생성을 data에 대해 실행한 결과로 한다. 예외가 발생하면 재throw한다. -
Assert: c는
PasswordCredential
이다. -
c를 반환한다.
3.3.5. PasswordCredentialData
에서 PasswordCredential
생성
PasswordCredentialData
에서
PasswordCredential
생성 알고리즘은 PasswordCredentialData
(data)가 주어지면 다음 단계를 실행합니다.
-
c를 새로운
PasswordCredential
객체로 한다. -
c의 속성을 아래와 같이 설정한다:
-
c를 반환한다.
3.3.6.
PasswordCredential
에 대한 CredentialRequestOptions
매칭
CredentialRequestOptions
(options)이 주어지면, 아래 알고리즘은 PasswordCredential
이 get()
요청에 대해 응답으로 제공되어야 하면 "Matches
"를 반환하고, 아니면 "Does Not Match
"를 반환합니다.
-
options에
password
멤버가 있고 값이true
이면 "Matches
"를 반환. -
"
Does Not Match
"를 반환.
4. 연합 자격 증명
4.1.
FederatedCredential
인터페이스
[Exposed =Window ,SecureContext ]interface :
FederatedCredential Credential {constructor (FederatedCredentialInit );
data readonly attribute USVString provider ;readonly attribute DOMString ?protocol ; };FederatedCredential includes CredentialUserData ;dictionary {
FederatedCredentialRequestOptions sequence <USVString >;
providers sequence <DOMString >; };
protocols partial dictionary CredentialRequestOptions {FederatedCredentialRequestOptions ; };
federated
provider
, 타입 USVString, 읽기 전용-
자격 증명의 연합 신원 제공자입니다. 유효한 형식에 대한 자세한 내용은 § 4.1.1 제공자 식별를 참조하세요.
protocol
, 타입 DOMString, 읽기 전용, nullable-
자격 증명의 연합 신원 제공자가 사용하는 프로토콜(예: "
openidconnect
")입니다. 값이null
이면, 프로토콜은provider
로부터 유추할 수 있습니다. [[type]]
-
FederatedCredential
인터페이스 객체에는[[type]]
라는 내부 슬롯이 있으며, 값은 "federated
"입니다. [[discovery]]
-
FederatedCredential
인터페이스 객체에는[[discovery]]
라는 내부 슬롯이 있으며, 값은 "credential store
"입니다. FederatedCredential(data)
-
이 생성자는
FederatedCredentialInit
(data)를 받아 다음 단계를 수행합니다:-
r에 FederatedCredentialInit로부터
FederatedCredential
생성의 결과를 저장합니다. 예외(exception)가 발생하면 그 예외를 다시 던집니다. -
r을 반환합니다.
-
FederatedCredential
객체는 FederatedCredentialInit
딕셔너리를
navigator.credentials.create()
에
전달하여 생성할 수 있습니다.
dictionary :
FederatedCredentialInit CredentialData {USVString ;
name USVString ;
iconURL required USVString ;
origin required USVString ;
provider DOMString ; };
protocol partial dictionary CredentialCreationOptions {FederatedCredentialInit ; };
federated
FederatedCredential
객체는 origin에 바인딩되어 있습니다.
FederatedCredential
의
인터페이스 객체는 Credential
의
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
구현을 상속하고,
자체적으로 [[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
,
[[Create]](origin, options, sameOriginWithAncestors)
,
그리고 [[Store]](credential, sameOriginWithAncestors)
구현을 정의합니다.
참고: 앞으로 사용자 에이전트가 사용자를 대신하여 인증 토큰을 획득하도록 가르친다면,
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
구현을 통해 이를 수행할 수
있습니다.
4.1.1. 제공자 식별
모든 사이트는 특정 연합 신원 제공자를 참조할 때 동일한 식별자를 사용해야 합니다. 예를 들어, Facebook Login은 "Facebook", "Facebook Login", "FB", "FBL", "Facebook.com" 등 여러 이름이 아닌, 모두가 사용할 수 있는 표준 식별자를 가져야 합니다. 일관된 식별은 사용자 에이전트가 더 유용하게 동작할 수 있게 해줍니다.
일관성을 위해, 이 문서에서 정의된 API(예: FederatedCredentialRequestOptions
의
providers
배열 또는 FederatedCredential
의
provider
속성)에 전달되는 federation은 제공자가 로그인에 사용하는 origin의 ASCII serialization으로 식별되어야 합니다.
즉, Facebook은 https://www.facebook.com
으로, Google은 https://accounts.google.com
으로
표시됩니다.
이 origin의 serialization에는 마지막 U+002F SOLIDUS("/
")가 포함되지
않지만,
사용자 에이전트는 이를 묵인해야 합니다: https://accounts.google.com/
은 분명히
https://accounts.google.com
과 동일합니다.
4.2. 알고리즘
4.2.1.
FederatedCredential
의
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
는 origin(origin), CredentialRequestOptions
(options),
그리고 상위와 동일 origin(sameOriginWithAncestors)일
때 true
인 boolean 값을 인자로 호출됩니다.
알고리즘은 credential store에서 Credential
객체 집합을 반환합니다. 일치하는 Credential
객체가 없다면 반환된 집합은 비어 있습니다.
-
sameOriginWithAncestors가
false
면, "NotAllowedError
"DOMException
을 던집니다.참고: 이 제한은 § 6.4 Origin 혼동에서 제기된 문제를 해결하기 위함입니다.
-
options["
federated
"] 가true
가 아니면 빈 집합을 반환합니다. -
credential store에서 자격 증명 목록을 조회하여, 다음 필터에 일치하는 자격 증명들을 반환합니다:
4.2.2. FederatedCredential
의
[[Create]](origin, options, sameOriginWithAncestors)
[[Create]](origin, options, sameOriginWithAncestors)
는 origin(origin), CredentialCreationOptions
(options), 그리고 상위와 동일 origin(sameOriginWithAncestors)일
때 true
인 boolean 값을 인자로 호출됩니다.
알고리즘은 생성 가능한 경우 FederatedCredential
을
반환하며,
그렇지 않으면 null
을 반환하거나, 예외 상황에서는 exception을
던집니다:
-
단언: options["
federated
"] 존재함, 그리고 sameOriginWithAncestors는 사용되지 않음. -
FederatedCredentialInit로부터
FederatedCredential
생성을 실행한 결과를 반환합니다. 예외가 발생하면 그 예외를 다시 던집니다.
4.2.3.
FederatedCredential
의 [[Store]](credential, sameOriginWithAncestors)
[[Store]](credential, sameOriginWithAncestors)
는 FederatedCredential
(credential)과, 상위와 동일 origin(sameOriginWithAncestors)일
때 true
인 boolean 값을 인자로 호출됩니다.
알고리즘은 credential이 credential store에 저장된 후 undefined
를 반환합니다.
알고리즘은 sameOriginWithAncestors가 true
가 아니면 NotAllowedError
를 반환합니다.
-
"
NotAllowedError
"DOMException
을 던지고, 사용자 에이전트의 credential store는 변경하지 않습니다. (sameOriginWithAncestors가false
인 경우)참고: 이 제한은 § 6.4 Origin 혼동에서 제기된 문제를 해결하기 위함입니다.
-
사용자 에이전트의 credential store에
FederatedCredential
이 있고, 그id
속성이 credential의id
와 같고,[[origin]]
슬롯이 credential의[[origin]]
과 동일 origin이고,provider
가 credential의provider
와 같으면 반환합니다. -
사용자가 자격 증명 저장 권한을 부여하면(user mediation 정의 참고), 다음 속성으로 credential store에
FederatedCredential
을 저장합니다:
4.2.4.
FederatedCredentialInit로부터 FederatedCredential
생성
FederatedCredentialInit로부터
FederatedCredential
생성을 위해,
FederatedCredentialInit
(init)을 인자로 다음 단계를 수행합니다.
5. 사용자 중재
API를 통해 웹에 자격 증명 정보를 노출하는 것은 사용자 프라이버시에 잠재적인 영향을 미칠 수 있습니다. 그러므로 사용자 에이전트는 사용자가 무엇이 일어나고 있는지, 그리고 누구와 자격 증명이 공유되는지 명확히 이해할 수 있도록 여러 경우에 반드시 사용자를 참여시켜야 합니다.
특정 동작이 사용자의 명시적인 동의를 얻은 후에 발생한다면, 우리는 이를 사용자 중재됨이라고 부릅니다. 동의는 예를 들어 자격 증명 선택기 인터페이스와 같은 사용자의 직접적인 상호작용을 통해 표현될 수 있습니다. 일반적으로 사용자 중재된 동작은 사용자에게 UI를 제공하고 결정을 요청하는 과정을 포함합니다.
동작이 조용히, 명시적인 사용자 동의 없이 발생한다면 이는 중재되지 않은(unmediated) 것입니다. 예를 들어, 사용자가 브라우저를 특정 origin에 대한 지속적인 자격 증명 액세스를 허용하도록 설정한 경우, UI를 띄우거나 별도의 결정을 요청하지 않고 자격 증명이 제공될 수 있습니다.
여기서는 모든 자격 증명 타입에 적용되는 몇 가지 요구 사항을 명시하지만, 사용자 에이전트의 재량이 상당히 많다는 점에 유의하세요(사용자를 돕는 특권적 위치에 있기 때문입니다). 또한, 특정 자격 증명 타입은 여기서 일반적으로 제시된 요구 사항을 초과하는 별도의 요구 사항을 가질 수 있습니다.
5.1. 자격 증명 저장 및 갱신
자격 증명 정보는 민감한 데이터이며, 사용자는 그 정보의 저장에 대한 통제권을 반드시 가져야 합니다. 자격 증명이 의도치 않게 저장되면, 예를 들어 사용자의 특정 디바이스 로컬 프로필이 온라인상의 특정 페르소나와 예기치 않게 연결될 수 있습니다. 이러한 놀람의 위험을 줄이기 위해:
-
사용자 중재 없이 자격 증명 정보를 저장하거나 갱신해서는 안 됩니다. 예를 들어, 사용자 에이전트는
store()
호출마다 사용자에게 "이 자격 증명을 저장하시겠습니까?"라는 다이얼로그 박스를 보여줄 수 있습니다.사용자 동의는 사용자 에이전트가 "항상 비밀번호 저장" 옵션과 같은 지속적인 동의 권한을 제공하는 경우 추론될 수도 있습니다(하지만 사용자 에이전트는 좀 더 범위가 좁은 옵션, 예를 들어 "항상 _생성된_ 비밀번호 저장"이나 "이 사이트에 대해서만 비밀번호 저장" 같은 옵션을 제공하는 것이 더 안전할 것입니다).
-
사용자 에이전트는 자격 증명이 저장될 때 반드시 사용자에게 알림을 제공해야 합니다. 이는 주소 표시줄의 아이콘이나 이와 유사한 위치에 표시될 수 있습니다.
-
사용자 에이전트는 반드시 사용자가 저장된 자격 증명을 수동으로 삭제할 수 있도록 허용해야 합니다. 이 기능은 설정 페이지나 위에서 설명한 알림과의 상호작용을 통해 구현될 수 있습니다.
5.2. 사용자 중재 요구
기본적으로, 모든 사용자 중재가 모든 origin에 대해 요구됩니다. 이는 prevent
silent access flag가 자격 증명 저장소에서 true
로 설정되어 있기 때문입니다. 사용자는
origin에 대한 자격 증명에 지속적인 액세스 권한을 부여할 수 있고(예: "이 사이트에 계속 로그인 상태 유지" 옵션), 이는 이 플래그를 false
로 설정하게
됩니다. 이 경우, 사용자는 항상 해당 사이트에 로그인 상태가 되며, 이는 사용성 및 편의성 측면에서 바람직하지만(예를 들어 사용자 에이전트가 이 플래그의 상태를 디바이스 간
동기화한다면) 예상치 못한 결과를 초래할 수 있습니다.
놀람의 위험을 줄이기 위해:
-
사용자 에이전트는 반드시 특정 origin이나 모든 origin에 대해 사용자 중재를 요구하도록 사용자가 설정할 수 있도록 해야 합니다. 이 기능은 각 origin의 prevent silent access flag를
false
로 반환하도록 전역 토글을 제공하거나, 특정 origin(또는 특정 origin의 특정 자격 증명)에 대한 좀 더 세분화된 설정을 통해 구현할 수 있습니다. -
사용자 에이전트는 origin의 prevent silent access flag를
false
로 설정할 때 반드시 사용자 중재를 거쳐야 합니다. 예를 들어, 자격 증명 선택기에서 사용자가 체크박스를 통해 특정 origin에 대해 중재 없이 자격 증명을 사용할 수 있도록 설정하거나, 사용자 에이전트의 자격 증명 관리자 온보딩 과정에서 기본 설정을 물어볼 수 있습니다. -
사용자 에이전트는 반드시 자격 증명이 origin에 제공될 때 사용자에게 알림을 제공해야 합니다. 이는 주소 표시줄의 아이콘이나 유사한 위치에 표시될 수 있습니다.
-
사용자가 특정 origin에 대한 브라우징 데이터를 삭제하는 경우(쿠키, localStorage 등), 사용자 에이전트는 반드시 해당 origin의 prevent silent access flag를
true
로 설정해야 합니다.
5.3. 자격 증명 선택
get()
가
사용자 중재가 필요한 origin에서 호출될 때, 사용자 에이전트는 자격 증명 정보를 공유할 수 있도록 사용자에게 반드시 동의를 요청해야 합니다.
이는 사용자가 사이트에서 사용할 수 있는 자격 증명 목록을 보여주고, 제공할 자격 증명을 선택하거나 요청을 취소할 수 있도록 하는 자격 증명 선택기 형태의
UI로 제공되어야 합니다.
선택기의 사용자 인터페이스는 웹사이트가 직접 만들어낼 수 있는 UI와 구별될 수 있는 방식으로 구현되어야 합니다. 예를 들어, 선택기가 사용자 에이전트의 UI와 겹쳐서 위조할 수 없는 방식으로 표시될 수 있습니다.
선택기의 사용자 인터페이스에는 자격 증명을 요청하는 origin을 반드시 표시해야 합니다.
선택기의 사용자 인터페이스에는
해당 origin과 연관된 모든 Credential
객체가 포함되어야 합니다.
사용자 에이전트는 선택기의 유용성을 높이기 위해, 이 문서에서 명시된 속성 외에도 각 Credential
객체에 대한 정보를 내부적으로 저장할 수 있습니다. 예를 들어, favicon은 신원 제공자를 구별하는 데 도움이 될 수 있습니다. 추가 정보는 반드시 웹에 직접 노출되어서는 안 됩니다.
선택기의 동작은 여기서 정의되지 않습니다. 사용자 에이전트는 인증 옵션에 대해 사용자를 교육하고, 자격 증명을 선택하는 과정을 안내하는 UI 방식을 실험해볼 것을 권장합니다. 단, 선택기의 인터페이스는 다음과 같습니다:
Credential
선택을 요청할
수 있습니다. CredentialRequestOptions
(options), 그리고 자격 증명 저장소에서 얻은 Credential
객체 집합(locally discovered
credentials)을 인자로 받습니다.
이 알고리즘은 사용자가 사이트와 자격 증명을 공유하지 않기로 선택하면 null
을, 특정 자격 증명을 선택하면 Credential
객체를, 자격 증명 타입을 선택하면 Credential
인터페이스 객체를 반환합니다.
만약 제공된 options가 사전에 일치 가능한(matchable a priori) 것이 아니라면, 선택기 인터페이스에 명시적 자격 증명 목록에 포함되지 않은 관련 자격 증명 인터페이스 객체도 함께 표시하는 것이 좋을 수 있습니다. 예를 들어, 사이트가 webauthn 스타일 인증기를 허용한다면 "보안 키"가 적절한 아이콘과 함께 선택기 목록에 나타날 수 있습니다.
또한, 경우에 따라 사용자 에이전트가 선택기 UI를 건너뛰는 경우도 있을 수 있습니다. 예를 들어, 관련 자격 증명 인터페이스 객체가 하나뿐이고, 그 자체가 사용자 상호작용을 요구하는 경우, 사용자 에이전트가 해당 인터페이스를 직접 반환하고, 내부 중재 흐름을 통해 사용자 동의를 받는 방식으로 동작할 수 있습니다.
6. 보안 고려사항
다음 섹션은 다양한 보안 및 프라이버시 고려사항에 대한 가이드라인을 제시합니다. 개별 자격 증명 타입은 이 가이드라인보다 더 엄격하거나 느슨한 버전을 적용할 수 있습니다.
6.1. 도메인 간 자격 증명 접근
자격 증명은 민감한 정보이므로, 사용자 에이전트는 웹사이트와 안전하게 공유할 수 있는 시점을 신중하게 결정해야 합니다. 가장 안전한 방법은 자격 증명을 저장된 정확한 origin에서만
공유하는 것이지만, 이는 웹 환경에는 지나치게 제한적일 수 있습니다. 예를 들어 example.com
과 admin.example.com
처럼
기능을 하위 도메인으로 나누는 사이트를 생각해볼 수 있습니다.
사용자의 불편과 자격 증명 보안 사이의 절충안으로, 사용자 에이전트는 다음과 같이 동작해야 합니다:
-
보안이 하향되는 scheme 구성 요소 사이의 origin 간에는 자격 증명을 공유해서는 안 됩니다. 즉,
http://example.com/
에 저장된 자격 증명을https://example.com/
에서 사용할 수 있도록 허용하는 것은(개발자가 안전한 전송으로 마이그레이션하도록 유도하기 위함) 의미가 있지만, 그 반대는 위험합니다. -
공개 접미사 목록 [PSL]을 활용하여 자격 증명의 등록 가능한 도메인과
[[origin]]
그리고get()
이 호출된 origin을 비교하여 자격 증명의 유효 범위를 결정할 수 있습니다. 예를 들어https://admin.example.com/
과https://example.com/
에 저장된 자격 증명은https://www.example.com/
에서get()
이 호출될 때 사용자에게 제공될 수 있고, 그 반대도 마찬가지입니다. -
자격 증명의 origin이 호출 origin과 정확히 일치하지 않는 경우,
get()
에 응답하여 origin에 자격 증명을 제공할 때 사용자 중재 없이 제공해서는 안 됩니다. 즉,Credential
객체는https://example.com
에서 직접https://www.example.com
으로 반환되지 않고, 선택기를 통해 사용자에게 제공될 수 있습니다.
6.2. 자격 증명 누출
개발자는 크로스 사이트 스크립팅 공격이 사용자의 계정에 대한 지속적인 접근으로 이어지는 위험을 완화하기 위해, 데이터가 전송될 수 있는 엔드포인트를 제한하는 적절한 콘텐츠 보안 정책(Content Security Policy) [CSP]을 설정해야 합니다. 특히 다음과 같은 지시어를 명시적 또는 암시적으로 설정해야 합니다:
-
[=
script-src
=] 및 [=object-src
=]는 페이지의 스크립트 실행을 제한하여 크로스 사이트 스크립팅 공격의 성공 가능성을 줄입니다. 사이트가form
요소를 생성하는 경우, [=form-action
=] 지시어도 반드시 설정해야 합니다. -
[=
connect-src
=]는fetch()
가 데이터를 제출할 수 있는 origin을 제한하여 자격 증명이evil.com
등으로 유출되는 위험을 줄입니다. -
[=
child-src
=]는 페이지에 중첩된 탐색 컨텍스트의 임베드를 제한하여 악의적인postMessage()
대상의 삽입을 어렵게 만듭니다. [HTML]
개발자는 입력 및 출력을 반드시 적절히 이스케이프 처리하고, 위험을 더욱 줄이기 위해 Subresource Integrity [SRI]와 같은 추가적인 방어 계층도 고려해야 합니다.
특정 자격 증명 타입을 정의할 때, 관련 자격 증명 타입은 자격 증명 데이터가 네트워크로 전송되는 방식에 충분히 주의를 기울여야 합니다. 예를 들어, 전송 메커니즘을 동일 origin의 엔드포인트로만 제한하도록 정의하는 것이 합리적일 수 있습니다.
6.3. 안전하지 않은 사이트
사용자 에이전트는 보안 컨텍스트가 아닌 환경에는 여기 정의된 API를 노출해서는 안 됩니다. 사용자 에이전트가 자동 입력(autofill) 메커니즘을 구현하여 사용자의 자격 증명을 저장하고 신뢰할 수 없는 URL의 로그인 폼을 채우는 것은 가능하지만, 그러한 사이트는 자격 증명 관리자를 직접적으로 신뢰할 수 있는 방식으로 상호작용할 수 없으므로, 해당 사이트는 보안 컨텍스트에 저장된 자격 증명에 접근해서는 안 됩니다.
6.4. Origin 혼동
프레임된 페이지가 여기서 정의된 API에 접근할 수 있다면, 사용자가 최상위 탐색 컨텍스트가 아닌 다른 origin에 대한 자격 증명 접근을 허용하도록 혼란스럽게 만들 가능성이 있습니다. 사용자가 합리적으로 이해할 수 있는 유일한 보안 origin은 최상위 탐색 컨텍스트입니다.
이 문서는 Credential Management API를 해당 컨텍스트에 노출합니다. 일부 자격 증명 타입은 사용자 에이전트가 UI에 충분한 고려와 맥락을 담을 경우 쉽게 제공할 수 있을 것으로 보입니다.
그러나 특정 자격 증명 타입은 그러한 컨텍스트에서 위험 없이 노출하기 어렵습니다. 해당 자격 증명 타입은 [[Create]](origin, options, sameOriginWithAncestors)
,
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
,
[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
,
그리고 [[Store]](credential, sameOriginWithAncestors)
메서드에서 적절한 검사를 통해 제한됩니다.
예를 들어 PasswordCredential
의
[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
메서드는 Worker
나
비-최상위 탐색 컨텍스트에서 호출되는 경우 즉시 빈 집합을 반환합니다.
6.5. 로그아웃
§ 5.2 사용자 중재 요구에서 논의된 바와 같이, 사용자가 자동 로그인 선택을 한 경우, 사용자 에이전트는
origin이 자격 증명을 요청할 때마다 이를 제공하게 됩니다. 웹사이트는 CredentialsContainer
의
preventSilentAccess()
메서드를 호출하여 이 동작을 억제할 수 있으며, 이는 해당 origin의 자동 로그인을 비활성화합니다.
사용자 에이전트는 웹사이트가 올바르게 동작할 것이라 기대합니다. 부주의하거나 악의적인 웹사이트는 이 메서드를 호출하지 않아, 사용자 에이전트가 사용자의 의도와 달리 계속 자격 증명을 제공할 수 있습니다. 이는 사용자가 "로그아웃"을 클릭해도 사이트가 사용자 자격 증명을 지우지 않는 기존 상황보다 약간 더 나쁜 상황입니다. 사용자 에이전트가 인증에 관여하게 되기 때문입니다.
사용자는 반드시 이 동작을 제어할 수 있어야 합니다. § 5.2 사용자 중재 요구에서 언급한 바와 같이,
origin의 쿠키를 삭제하면 해당 origin의 prevent silent access flag가 자격 증명
저장소에서 true
로 초기화됩니다. 또한, 사용자 에이전트는 특정 origin에 대한 자동 로그인을 비활성화할 수 있는 UI 옵션도 제공해야 합니다.
예를 들어, 자격 증명이 origin에 제공되었을 때 표시되는 알림에 연동될 수 있습니다.
7. 프라이버시 고려사항
7.1. 타이밍 공격
사용자가 특정 origin에 자격 증명이 없는 경우 get()
호출은 매우 빠르게 완료됩니다. 악의적인 웹사이트는 자격 증명이 없는 사용자를, 자격 증명이 있지만 공유하지 않기로 선택한 사용자를 구별할 수 있습니다.
사용자 에이전트는 또한 자격 증명 요청을 속도 제한(rate-limit)해야 합니다. 짧은 시간에 여러 번 자격 증명 요청을 하는 것은 거의 확실히 악용에 해당합니다.
7.2. 선택기 정보 누출
사용자 에이전트의 자격 증명
선택기가 origin에서 제공한 이미지를 표시하는 경우(예: Credential
이
사이트의 favicon을 표시),
이러한 이미지 요청은 반드시 선택기 인스턴스화와 직접적으로 연결되어서는 안 됩니다. 선택기 사용이 외부에 노출되는 것을 방지하기 위함입니다. 한 가지 방법은 자격 증명을 저장하거나 갱신할
때 이미지를 백그라운드에서 가져오고, 자격 증명 생명주기 동안 캐시하는 것입니다.
이러한 이미지는 credentials mode를 "omit
",
service-workers mode를 "none
",
client를 null
로,
initiator를 빈 문자열로,
destination을 "subresource
"로 설정하여 가져와야 합니다.
또한, 사용자 에이전트가 사용자가 자격 증명에 연결된 이름이나 아이콘을 변경할 수 있도록 허용하는 경우, 해당 데이터의 변경사항은 웹사이트에 노출되어서는 안 됩니다(예: 사용자가 한 origin에 대해 "내 가짜 계정" 또는 "내 진짜 계정"이라고 이름을 지정하는 경우).
7.3. 로컬 저장 데이터
이 API는 origin이 사용자의 프로필과 함께 데이터를 영구적으로 저장할 수 있는 기능을 제공합니다. 대부분의 사용자 에이전트는 자격 증명 데이터를 "브라우징 데이터"(쿠키 등)와 다르게 처리하기 때문에, 사용자가 쿠키를 지울 때 모든 흔적이 삭제된다고 생각할 수 있지만 실제로는 자격 증명 데이터가 남아 있을 수 있습니다.
사용자 에이전트는 origin에 대해 자격 증명 데이터가 저장되어 있음을 명확하게 보여주는 UI를 제공해야 하며, 사용자가 더 이상 해당 데이터를 유지하고 싶지 않을 때 쉽게 삭제할 수 있도록 해야 합니다.
8. 구현 관련 고려사항
이 섹션은 규범적이지 않습니다.
8.1. 웹사이트 개발자
이 API를 언제, 어떻게 사용해야
하는지, 특히 mediation
와
관련된 내용을 추가하세요.
[Issue #w3c/webappsec#290]
fetch()
로 FormData
바디를 사용하여 자격 증명을 전송할 때의 인코딩 제한을 설명하세요.
특정 자격 증명 타입에 대한 기능 감지를 수행할 때, 개발자는 Credential
의
특수화가 존재하는지 확인하는 것이 좋습니다. navigator.credentals
의 존재만 확인하는 것은 API 자체의 존재 여부만 검증할 뿐, 사이트에 필요한
특정 자격 증명 타입의 지원 여부는 확인하지 못합니다. 예를 들어, 사이트가 비밀번호를 요구한다면 if (window.PasswordCredential)
로 지원
여부를 확인하는 것이 가장 효과적입니다.
8.2. 확장 포인트
이 문서는 구체적인 인증 요구를 충족하는 특정 자격 증명 타입으로 확장될 수 있도록 설계된 범용, 상위 수준의 API를 제공합니다. 확장은 다음과 같이 진행할 수 있습니다:
-
Credential
을 상속받는 새로운 인터페이스를 정의합니다: -
[[Create]](origin, options, sameOriginWithAncestors)
,[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
,[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
, 그리고[[Store]](credential, sameOriginWithAncestors)
메서드를ExampleCredential
의 interface object에 정의합니다.[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
는 자격 증명이 영구적으로 유효할 때 적합하며, 자격 증명 저장소에서 단순히 복사해올 수 있습니다. 반면,[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
는 자격 증명이 자격 증명 소스로부터 재생성되어야 할 때 적합합니다.예를 들어
PublicKeyCredential
의[[Create]](origin, options, sameOriginWithAncestors)
및[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)
와 같이 장시간 소요되는 작업은options.signal
을 사용해 개발자가 작업을 중단할 수 있도록 하는 것이 좋습니다. 자세한 내용은 DOM § 3.3 AbortController 및 AbortSignal 객체를 API에서 사용하는 방법을 참고하세요.ExampleCredential
의[[CollectFromCredentialStore]](origin, options, sameOriginWithAncestors)
내부 메서드는 origin (origin
), CredentialRequestOptions 객체(options
), 그리고 호출 컨텍스트가 상위와 동일 origin일 때true
인 boolean 값을 인자로 호출됩니다. 알고리즘은 제공된 옵션에 일치하는Credential
객체 집합을 반환합니다. 일치하는Credential
객체가 없다면 반환된 집합은 비어 있습니다.-
Assert:
options
[example
] exists. -
If
options
[example
] is not truthy, return the empty set. -
For each credential in the 자격 증명 저장소:
-
...
-
-
-
ExampleCredential
interface object의[[type]]
슬롯 값을 정의합니다: -
ExampleCredential
interface object의[[discovery]]
슬롯 값을 정의합니다: -
CredentialRequestOptions
를 확장하여 새 자격 증명 타입이get()
에 합리적으로 응답할 수 있도록 옵션을 추가합니다: -
CredentialCreationOptions
를 확장하여 새 자격 증명 타입이Credential
객체를create()
에 응답할 때 필요한 데이터를 제공하도록 합니다: -
새 자격 증명 타입이
conditional
사용자 중재를 지원한다면,ExampleCredential/isConditionalMediationAvailable()
가 true로 resolve되는 promise를 반환하도록 정의합니다. -
§ 2.1.2.1 등록 항목 요구사항 및 업데이트 절차에 따라 새 "example" 자격 증명 타입 및 이에 대응하는 다음 항목을 자격 증명 타입 레지스트리에 추가합니다:
-
CredentialCreationOptions
및CredentialRequestOptions
의 옵션 멤버 식별자(이 경우 "example") -
적절한 인터페이스 객체 식별자(이 경우
ExampleCredential
)
참고: 자격 증명 타입의 옵션 딕셔너리의 옵션 멤버 식별자는
CredentialCreationOptions
와CredentialRequestOptions
모두에서 동일해야 하며,Credential
interface object의[[type]]
슬롯의 자격 증명 타입 값과도 동일해야 합니다. -
이 외에도 새로운 프리미티브가 필요할 수 있습니다. 예를 들어, 복잡한 다중 인증(sign-in) 과정에서 하나의 Credential
객체가 아닌 여러 개를 반환해야 할 수도 있습니다. 이런 경우 getAll()
메서드를 CredentialsContainer
에
추가해 sequence<Credential>
을 반환하도록 하고, 서로 다른 타입의 자격 증명을 요청할 때의 합리적인 처리 메커니즘을 정의할 수 있습니다.
이와 같은 확장을 고려할 경우 public-webappsec@에 문의하여 협의와 검토를 받는 것이 좋습니다.
8.3. 브라우저 확장 프로그램
이상적으로, 확장 시스템을 구현한 사용자 에이전트는 써드파티가 이러한 API 엔드포인트에 연결하여 써드파티 자격 증명 관리 소프트웨어의 동작을 향상시킬 수 있도록 허용해야 하며, 이는 사용자 에이전트가 명령형(imperative) 방식으로 자체 동작을 개선하는 것과 동일합니다.
이는 사용자 에이전트가 중재하는 복잡한 새로운 API 구현부터, 확장 프로그램이 자체 목적에 맞게 get()
및 store()
엔드포인트를 덮어써서 사용할 수 있도록 하는 것까지 다양할 수 있습니다.
9. 향후 작업
이 섹션은 규범적이지 않습니다.
여기 정의된 API는 사용자 에이전트의 자격 증명 관리자를 웹에 최소한으로 노출하며, 웹이 연합 신원 제공자가 사용 중임을 자격 증명 관리자에게 알릴 수 있게 해줍니다. 다음 논리적 단계는 [WEB-LOGIN]과 같은 문서(그리고 어느 정도는 Mozilla의 BrowserID [BROWSERID])에 간략히 제시된 방향과 유사할 것입니다.
사용자 에이전트는 사용자, 신원 제공자, 그리고 웹사이트 간의 관계를 효과적으로 중재할 수 있는 독특한 위치에 있습니다. 사용자 에이전트가 일반적인 인증 흐름에 수반되는 위험과 혼란을 일부 제거할 수 있다면, 사용자는 오늘날보다 훨씬 더 나은 위치에 있게 될 것입니다.
이 정보를 노출하는 자연스러운 방법은 FederatedCredential
인터페이스에 인증 토큰과 같은 속성을 추가하거나, 제공자가 지원하는 인증 타입을 선언하는 속성을 가진 매니페스트 형식을 추가하는 것일 수 있습니다.
여기서 설명하는 API는 사용자 상호작용이 필요한 사용 사례(아마도 자격 증명을 요청한 웹사이트가 아닌 다른 웹사이트와 함께)까지 지원할 수 있도록 충분히 확장 가능하게 설계되었습니다.
Promise 기반 시스템이 여러 탐색 컨텍스트(예: idp.com
에서 중재된 활동이 rp.com
에 반환된 Promise를 해결하는 경우)나
디바이스 및 사용자 에이전트 간(예: [WEBAUTHN])의 일부
상호작용을 지원할 수 있을 만큼 충분히 확장 가능하기를 바랍니다. 이러한 흐름을 위해 API를 처음부터 다시 설계하지 않아도 되기를 희망합니다.
작은 한 걸음씩.