├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── common.js └── index.html /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in 2 | # the repo. Unless a later match takes precedence, 3 | # they will be requested for review when someone opens a 4 | # pull request. 5 | * @dlongley 6 | 7 | # See CODEOWNERS syntax here: https://help.github.com/articles/about-codeowners/#codeowners-syntax 8 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # W3C Credentials Community Group 2 | 3 | Contributions to this repository are intended to become part of 4 | Recommendation-track documents governed by the 5 | [W3C Patent Policy](https://www.w3.org/Consortium/Patent-Policy-20040205/) and 6 | [Software and Document License](https://www.w3.org/Consortium/Legal/copyright-software). 7 | To make substantive contributions to specifications, you must either participate 8 | in the relevant W3C Working Group or make a non-member patent licensing commitment. 9 | 10 | If you are not the sole contributor to a contribution (pull request), please 11 | identify all contributors in the pull request comment. 12 | 13 | To add a contributor (other than yourself, that's automatic), mark them one 14 | per line as follows: 15 | 16 | ``` 17 | +@github_username 18 | ``` 19 | 20 | If you added a contributor by mistake, you can remove them in a comment with: 21 | 22 | ``` 23 | -@github_username 24 | ``` 25 | 26 | If you are making a pull request on behalf of someone else but you had no 27 | part in designing the feature, you can remove yourself with the above syntax. 28 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | All Reports in this Repository are licensed by Contributors under the [W3C Software and Document 2 | License](https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document). 3 | 4 | Contributions to Specifications are made under the 5 | [W3C CLA](https://www.w3.org/community/about/agreements/cla/). 6 | 7 | Contributions to Software, including sample implementations, are under the 8 | [Apache 2.0 License](https://www.apache.org/licenses/LICENSE-2.0). 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # credential-handler-api 2 | Repository for the Credential Handler specification of the Credentials Community Group 3 | 4 | ## Background 5 | 6 | A Credential Handler is an event handler for credential request and 7 | credential storage events. The [Credential Handler API][] helps 8 | solve the [Nascar Problem](https://indieweb.org/NASCAR_problem). The 9 | [Credential Handler API][] enables websites to install Credential Handlers that 10 | can respond when users visit other websites that request or store credentials. 11 | 12 | For example, a user may visit a website that wants them to login using 13 | OpenIDConnect, provide an OAuth Token, authenticate using a [DID][], or present 14 | some [Verifiable Credential][]. When these other websites use the [Credential 15 | Handler API][], the user is shown an in-browser selection screen with visual 16 | representations (e.g., icons and/or origin information) of only those 17 | Credential Handlers which have been previously installed by the user and 18 | that are compatible with the website's request. Once the user makes a choice, 19 | the appropriate Credential Handler is loaded, and a credential event is sent 20 | to it. 21 | 22 | The Credential Handler receives the event via a 23 | [Service Worker](https://w3c.github.io/ServiceWorker), or, if the 24 | [Credential Handler Polyfill][] is used, a simple page with no UI elements is 25 | loaded, and it uses the polyfill to receive and respond to the event. 26 | 27 | The Credential Handler must respond to the event with a credential that 28 | fulfills the request. If necessary, the Credential Handler may open a window 29 | on its website's origin to allow the user to interact with its website prior 30 | to responding. This UI can be styled and shaped according to the website 31 | owner's brand using arbitrary JavaScript and HTML like any other webpage. 32 | 33 | ## Demo 34 | 35 | ***We provide a demo of this potential future Web feature below. Please note that the demo uses a polyfill that provides UI that emulates secure browser chrome. To repeat, this polyfill UI is an emulation and IS NOT actually implemented by the browser. Support for this API could make this UI (or most likely a much better one!) a reality in browsers in the future.*** 36 | 37 | The demo of the credential handler in action is here: 38 | 39 | 1. [Demo Wallet](https://wallet.example.chapi.io/) 40 | 2. [Demo Issuer](https://issuer.example.chapi.io/) 41 | 3. [Demo Verifier](https://verifier.example.chapi.io/) 42 | 43 | Please see the [polyfill README][] for animated GIFs of the polyfill and 44 | demo in action. 45 | 46 | The demo sites work in Chrome, Firefox, Edge, and the most recent versions of 47 | Safari/iOS. (Safari must have support for the Storage Access API.) 48 | 49 | The Storage Access API is required in Safari because the Credential Handler 50 | polyfill uses a neutral, shared, third-party website to store the credential handler 51 | registrations users create. These are not the credentials themselves, but a 52 | registration list of the credential handler(s) (i.e., digital wallet 53 | URLs) that you have previously registered. Storage of this registration list 54 | enables the browser to show the user a selector UI with the registered digital wallets that could 55 | possibly fulfill a request for credentials from a relying party website. 56 | 57 | Prior to implementing the Storage Access API, Safari partitioned its 58 | third-party storage and cookies such that the polyfill could not function 59 | without the user manually changing settings in the browser. 60 | 61 | ## Explainer 62 | 63 | ## Roles 64 | 65 | The Credential Handler API's design is such that there are four roles that are 66 | played when passing credentials over the Web: 67 | 68 | ### Credential Repository 69 | 70 | This role handles credential storage and requests for a user, acting as their 71 | "wallet". This role is responsible for providing a "Credential Handler". 72 | This role is implemented as Web App on a credential wallet website. 73 | 74 | ### Credential Issuer 75 | 76 | This role issues credentials to a user for them to put in a wallet. 77 | 78 | ### Credential Verifier 79 | 80 | This role requests credentials from a user. Users fulfill this request via a 81 | wallet of the user's choice. 82 | 83 | ### Mediator 84 | 85 | This role mediates all credential storage and credential requests for a user. 86 | It is responsible for helping the user make wallet choices and proxying 87 | requests and responses to/from relying party websites (credential issuers and 88 | credential verifiers) and the user's chosen wallet. This role is played by the 89 | user agent (browser). 90 | 91 | ## Typical Flow 92 | 93 | 1. A user visits a "credential wallet" website. 94 | 95 | 2. The wallet web app registers a "Credential Handler". 96 | 97 | During this step, the web app calls a new JavaScript API to register a piece of 98 | code (a "Credential Handler") that will execute when the user later elects to 99 | use the web app to fulfill a request for credentials or a request to store 100 | credentials. 101 | 102 | 3. The user visits a Credential Issuer website to receive a credential. 103 | 104 | The Credential Issuer website calls the Credential Management API to store a 105 | new type of Web-based credential (i.e., essentially a third-party credential, or 106 | a credential that may be used across domains). 107 | 108 | 4. The browser shows the user a UI with information (such as icons, text, or origins) 109 | representing previously registered credential handlers that can store their 110 | new credential. 111 | 112 | When the user makes a selection, the credential to be stored is forwarded to 113 | the chosen handler, which then allows the user to interact with the associated 114 | Web App from the wallet origin as needed to complete the storage request. 115 | 116 | The browser is playing the "Mediator" role here: forwarding a request from the 117 | Credential Issuer to a third-party Credential Repository of the user's choice. 118 | The Credential Issuer doesn't care which wallet is used. All the mediator needs 119 | to do is match up credential storage requests with wallets that 120 | support their storage, and present these options to the user. 121 | 122 | 5. The user visits a Credential Verifier website which requests third-party 123 | (Web-based) credentials. 124 | 125 | Here the Credential Verifier website calls the Credential Management API using 126 | a query for a new type of Web-based credential (i.e., essentially a third-party 127 | credential, or a credential that may be used across domains). 128 | 129 | 6. The browser shows the user a UI with information (icons, text, origins) 130 | representing previously registered credential handlers. 131 | 132 | When the user makes a selection, the Credential Verifier's request is forwarded 133 | to the chosen credential handler. 134 | 135 | The browser is playing the "Mediator" role here: forwarding a request from the 136 | Credential Verifier to a third-party Credential Repository of the user's 137 | choice. The Credential Verifier doesn't care which wallet is used; they have 138 | a trust relationship with Credential Issuers, not the wallet provider. All the 139 | mediator needs to do is match up requests for credentials to the 140 | user's preferred wallet(s) for fulfilling those requests. 141 | 142 | 7. The user interacts as needed with the wallet Web App, and chooses the 143 | credentials to fulfill the request. 144 | 145 | Here the Web App resolves a Promise with the user's response. If required 146 | by the specific Web credential scheme/protocol, the response 147 | may include additional authentication information to prove 148 | ownership over the credentials. 149 | 150 | 8. The browser forwards the credential response to the Credential Verifier. 151 | 152 | 9. The Credential Verifier verifies the credentials, and proceeds however 153 | it sees fit. 154 | 155 | This flow works for DID-Auth, passing Verifiable Credentials, or using other 156 | systems such as OpenID Connect (OIDC). 157 | 158 | ## IANA Considerations 159 | 160 | The following section should be submitted to the Internet Engineering Steering 161 | Group (IESG) for review, approval, and registration with IANA. 162 | 163 | #### `application/credentialquery+json` 164 | 165 |
63 | Credential Management Level 1 64 | describes an imperative API enabling a website to request a user’s 65 | credentials from a user agent, and to help the user agent correctly 66 | store user credentials for future use. User agents implementing that 67 | API prompt the user to select a way to handle a credential request, 68 | after which the user agent returns a credential to the originating 69 | site. This specification defines capabilities that enable third-party 70 | Web applications to handle credential requests and storage. 71 |
72 |75 | The Credentials Community Group maintains a list of 77 | all bug reports that the group has not yet addressed. This draft 78 | highlights some of the pending issues that are still to be discussed 79 | in the community group. No decision has been taken on the outcome of 80 | these issues including whether they are valid. Pull requests with 81 | proposed specification text for outstanding issues are strongly 82 | encouraged. 83 |
84 |90 | The mission of the Credentials Community Group is to explore the 91 | creation, storage, presentation, verification, and user control of 92 | credentials. Its focus is placed on a verifiable credential (a set of 93 | claims) created by an issuer about a subject: a person, group, or 94 | thing. It seeks solutions inclusive of approaches such as: 95 | self-sovereign identity; presentation of proofs by the bearer; data 96 | minimization; and centralized, federated, and decentralized registry and 97 | identity systems. Therefore, the Credentials Community Group presents 98 | a specification that extends the 99 | Credential Management Level 1 100 | API to allow users to designate trusted third party Web applications 101 | as handlers for credential requests and credential storage. 102 |
103 |104 | A credential repository is a Web application that can 105 | handle credential requests and credential storage on behalf of the 106 | user. This specification defines a number of new Web platform features 107 | to handle credential requests and credential storage: 108 |
109 |130 | This specification does not address how software built with 131 | operating-system specific mechanisms (e.g., "native mobile apps") 132 | handle credential requests and credential storage. 133 |
134 |137 | This specification defines one class of products: 138 |
139 |145 | A user agent MUST behave as described in this specification 146 | to be considered conformant. In this specification, user 147 | agent means a Web browser or other interactive user 148 | agent as defined in [[!HTML5]]. 149 |
150 |151 | User agents MAY implement algorithms given in this specification in 152 | any way desired, so long as the end result is indistinguishable 153 | from the result that would be obtained by the specification's 154 | algorithms. 155 |
156 |157 | A conforming Credential Handler API user agent MUST also be a 158 | conforming implementation of the IDL fragments of this 159 | specification, as described in the “Web IDL” specification. 160 | [[!WEBIDL-LS]] 161 |
162 | 166 |174 | In this document we envision the following flow for a credential 175 | request: 176 |
177 |253 | The origin information of the relying party may be blinded when 254 | received via a CredentialRequestEvent. 255 |
256 |257 | An origin may implement a credential repository with more than one 258 | service worker and therefore multiple credential handlers may 259 | be registered per origin. The handler that is invoked is determined by 260 | the selection made by the user of a 261 | credential hint. The 262 | service worker which stored the credential hint with its 264 | CredentialManager 266 | is the one that will be invoked. 267 |
268 |273 | The logic of a credential handler is driven by the WebCredential 274 | types that it supports. Some WebCredential types may require 275 | very little processing on the part of the credential handler other 276 | than retrieving a WebCredential from its storage and returning it 277 | as a response. 278 |
279 |280 | In contrast, some Web Credential types, such as 281 | VerifiableProfile include a custom query parameter that 282 | must be understood and processed by the credential handler in order 283 | for it to return an appropriate WebCredential in response. This 284 | may involve presenting a user interface to allow the user to make 285 | selections. In some cases, a credential handler may need to generate 286 | a WebCredential dynamically with the assistance of an issuer or 287 | blinding service. It may also need to generate a zero knowledge proof 288 | or use some other privacy enhancing cryptographic method. 289 |
290 |291 | Therefore, handling a credential request may include numerous 292 | interactions: with the user through a new contextual window or other 293 | APIs (such as [[!WebCryptoAPI]]) or with other services and origins 294 | through web requests or other means. 295 |
296 |297 | Once a WebCredential is returned to the relying party website, it is 298 | its job to perform whatever verification is appropriate for its type. 299 |
300 |301 | This specification does not address the activities that occur 302 | between the credential handler accepting the 303 | CredentialRequestEvent and the credential handler returning a 304 | response. All of the activities which may be required to configure 305 | the credential handler and handle the credential request are left to 306 | the implementation of the credential handler, including: 307 |
308 |320 | Thus, an origin will rely on many other Web technologies defined 321 | elsewhere for lifecycle management, security, user authentication, 322 | user interaction, and so on. 323 |
324 |330 | The logic of a credential handler is driven by the WebCredential 331 | types that it supports. Some WebCredential types may require 332 | very little processing on the part of the credential handler other 333 | than storing the WebCredential in a database and returning it 334 | as a response. 335 |
336 |337 | In contrast, some Web Credential types, such as 338 | VerifiableProfile may include multiple sub-credentials whereby 339 | the user may only elect to store some subset of them, through the use 340 | of a user interface provided by the credential handler. 341 |
342 |343 | Handling credential storage may include numerous interactions: with 344 | the user through a new contextual window or other APIs (such as 345 | [[!WebCryptoAPI]]) or with other services and origins through web 346 | requests or other means. 347 |
348 |349 | The WebCredential that is returned to the issuer website provides 350 | information on what was stored by the credential handler, enabling 351 | the issuer website to take whatever next actions are appropriate. 352 |
353 |354 | This specification does not address the activities that occur 355 | between the credential handler accepting the 356 | CredentialStoreEvent and the credential handler returning a 357 | response. All of the activities which may be required to configure 358 | the credential handler and handle credential storage are 359 | left to the implementation of the credential handler, including: 360 |
361 |373 | Thus, an origin will rely on many other Web technologies defined 374 | elsewhere for lifecycle management, security, user authentication, 375 | user interaction, and so on. 376 |
377 |401 | This specification does not address how third-party mobile credential 402 | repository apps interact (through proprietary mechanisms) with user 403 | agents, or how user agents themselves provide simple credential 404 | repository functionality. 405 |
406 |ServiceWorkerRegistration
interface
427 | 429 | This specification extends the ServiceWorkerRegistration 430 | interface with the addition of a credentialManager 431 | attribute. 432 |
433 |434 | partial interface ServiceWorkerRegistration { 435 | readonly attribute CredentialManager credentialManager; 436 | }; 437 |438 |
444 | [SecureContext, Exposed=(Window,Worker)] 445 | interface CredentialManager { 446 | [SameObject] readonly attribute CredentialHints hints; 447 | [Exposed=Window] static Promise<PermissionState> requestPermission(); 448 | }; 449 |450 |
451 | The CredentialManager is used by credential repositories 452 | to manage their associated hints and supported WebCredential types. 453 |
454 |459 | This attribute allows manipulation of credential hints associated 460 | with a service worker (and therefore its credential handler). To be 461 | a candidate credential handler, a handler must have at least one 462 | registered credential hint to present to the user. That instrument 463 | needs to match the WebCredential types and type-specific query 464 | information specified by the credential request. 465 |
466 |472 | The user agent is NOT REQUIRED to prompt the user to grant 473 | permission to the origin for each new supported WebCredential 474 | type or new credential hint. 475 |
476 |477 | When called, this method executes the following steps: 478 |
479 |507 | [SecureContext, Exposed=(Window,Worker)] 508 | interface CredentialHints { 509 | Promise<boolean> delete(DOMString hintKey); 510 | Promise<CredentialHint> get(DOMString hintKey); 511 | Promise<sequence<DOMString>> keys(); 512 | Promise<boolean> has(DOMString hintKey); 513 | Promise<void> set(DOMString hintKey, CredentialHint hint); 514 | Promise<void> clear(); 515 | }; 516 |517 |
518 | The CredentialHints interface represents a collection of 519 | credential hints, each uniquely identified by a hintKey. 520 | The hintKey identifier will be passed to the credential 521 | handler to indicate the CredentialHint selected by the user. A 522 | CredentialHint is associated with a context or aspect of the 523 | user for which they store certain credentials, similar to a digital 524 | version of a physical wallet. 525 |
526 |531 | When called, this method executes the following steps: 532 |
533 |552 | When called, this method executes the following steps: 553 |
554 |574 | When called, this method executes the following steps: 575 |
576 |593 | When called, this method executes the following steps: 594 |
595 |614 | When called, this method executes the following steps: 615 |
616 |684 | When called, this method executes the following steps: 685 |
686 |703 | dictionary CredentialHint { 704 | required DOMString name; 705 | sequence<ImageObject> icons; 706 | sequence<DOMString> enabledTypes; 707 | object match; 708 | }; 709 |710 |
756 | dictionary ImageObject { 757 | required USVString src; 758 | DOMString sizes; 759 | DOMString type; 760 | }; 761 |762 |
812 | When this algorithm with inputImages parameter is 813 | invoked, the user agent must run the following steps: 814 |
815 |856 | According to the step 2.3, it is also possible to use the relative 857 | url for image.src. The 858 | following examples illustrate how relative URL resolution works in 859 | different execution contexts. 860 |
861 |863 | <-- In this example, code is located in https://www.example.com/wallet/index.html --> 864 | <script> 865 | 866 | const hintKey = "c8126178-3bba-4d09-8f00-0771bcfd3b11"; 867 | const { registration } = await navigator.serviceWorker.register("/register/sw.js"); 868 | await registration.credentialManager.credentialHints.set({ 869 | hintKey, 870 | { 871 | name: "My social account: pat@example.com", 872 | enabledTypes: ["VerifiableProfile"], 873 | icons: [{ 874 | src: "icon/lowres.webp", 875 | sizes: "48x48", 876 | type: "image/webp" 877 | }], 878 | match: { 879 | VerifiableProfile: { 880 | id: 'did:method1:1234-1234-1234-1234' 881 | } 882 | } 883 | }); 884 | 885 | const { storedHint } = 886 | await registration.credentialManager.credentialHints.get(hintKey); 887 | 888 | // storedHint.icons[0].src == "https://www.example.com/wallet/icon/lowres.webp"; 889 | 890 | </script> 891 |892 |
894 | 895 | // In this example, code is located in https://www.example.com/register/sw.js 896 | 897 | const hintKey = "c8126178-3bba-4d09-8f00-0771bcfd3b11"; 898 | await self.registration.credentialManager.credentialHints.set({ 899 | hintKey, 900 | { 901 | name: "My social account: pat@example.com", 902 | enabledTypes: ["VerifiableProfile"], 903 | icons: [{ 904 | src: "../wallet/icon/lowres.webp", 905 | sizes: "48x48", 906 | type: "image/webp" 907 | }], 908 | match: { 909 | VerifiableProfile: { 910 | id: 'did:method1:1234-1234-1234-1234' 911 | } 912 | } 913 | }); 914 | 915 | const { storedHint } = 916 | await registration.credentialManager.credentialHints.get(hintKey); 917 | 918 | // storedHint.icons[0].src == "https://www.example.com/wallet/icon/lowres.webp"; 919 |920 |
926 | The following example shows how to register a credential handler: 927 |
928 |929 | button.addEventListener("click", async() => { 930 | if (!window.CredentialManager) { 931 | return; // not supported, so bail out. 932 | } 933 | 934 | const result = await CredentialManager.requestPermission(); 935 | if (result !== "granted") { 936 | return; 937 | } 938 | 939 | const { registration } = 940 | await navigator.serviceWorker.register('/sw.js'); 941 | 942 | // Excellent, we got it! Let's now set up the user's hints. 943 | await addInstruments(registration); 944 | }, { once: true }); 945 | 946 | function addHints(registration) { 947 | return Promise.all([ 948 | registration.credentialManager.hints.set( 949 | "dc2de27a-ca5e-4fbd-883e-b6ded6c69d4f", 950 | { 951 | name: "My social account: pat@example.com", 952 | enabledTypes: ["VerifiableProfile"], 953 | icons: [{ 954 | src: "icon/lowres.webp", 955 | sizes: "48x48", 956 | type: "image/webp" 957 | }], 958 | match: { 959 | VerifiableProfile: { 960 | id: 'did:method1:1234-1234-1234-1234' 961 | } 962 | } 963 | }), 964 | 965 | registration.credentialManager.hints.set( 966 | "c8126178-3bba-4d09-8f00-0771bcfd3b11", 967 | { 968 | name: "My business account: pat@business.example.com", 969 | enabledTypes: ["VerifiableProfile"], 970 | match: { 971 | VerifiableProfile: { 972 | id: 'did:method1:1234-1234-1234-1235' 973 | } 974 | } 975 | }), 976 | 977 | registration.credentialManager.hints.set( 978 | "new-hint", 979 | { 980 | name: "Add a new identity", 981 | enabledTypes: ["VerifiableProfile"] 982 | }), 983 | ]); 984 | }; 985 |986 |
995 | TODO: define matching algorithm here 996 |
997 |998 | After applying the matching algorithm, the user agent displays the 999 | matching credential hints for the user to make a selection. This 1000 | specification includes a limited number of display requirements; most 1001 | user experience details are left to implementers. 1002 |
1003 |1019 | The following are examples of credential hint ordering: 1020 |
1021 |1041 | The user agent MUST enable the user to 1042 | select any displayed hint. 1043 |
1044 |1055 | Users agents may wish to enable the user to select individual 1056 | displayed CredentialHints. The credential handler would receive 1057 | information about the selected hint and could take action, potentially 1058 | eliminating an extra click (first open the credential repository 1059 | app then select the hint). 1060 |
1061 |1068 | Only when a website invokes the get() 1070 | and passes a WebCredentialRequestOptions 1071 | or the store() 1073 | method and passes a WebCredential, will CredentialHints be 1074 | presented to the user for selection. 1075 |
1076 |1077 | Once the user has selected a CredentialHint, the user agent fires a 1078 | CredentialRequestEvent (or a CredentialStoreEvent if 1079 | the Credential Management method called was store()) and uses 1080 | the subsequent WebCredential as a response. 1081 |
1082 |1087 | [SecureContext, Exposed=(Window,Worker)] 1088 | interface WebCredential : Credential { 1089 | readonly attribute USVString dataType; 1090 | readonly attribute object data; 1091 | }; 1092 |1093 |
1100 | This specification extends the ServiceWorkerGlobalScope 1101 | interface. 1102 |
1103 |1104 | partial interface ServiceWorkerGlobalScope { 1105 | attribute EventHandler oncredentialrequest; 1106 | attribute EventHandler oncredentialstore; 1107 | }; 1108 |1109 |
1114 | The oncredentialrequest attribute is an event handler 1115 | whose corresponding event handler event type is 1116 | CredentialRequestEvent. 1117 |
1118 |1124 | The oncredentialstore attribute is an event handler 1125 | whose corresponding event handler event type is 1126 | CredentialStoreEvent. 1127 |
1128 |1136 | The CredentialRequestEvent represents the data and methods available 1137 | to a Credential Handler after selection by the user. The user agent 1138 | communicates the WebCredentialRequestOptions to the Credential 1139 | Handler. 1140 |
1141 |1142 | [Constructor(DOMString type, CredentialRequestEventInit eventInitDict), Exposed=ServiceWorker] 1143 | interface CredentialRequestEvent : ExtendableEvent { 1144 | readonly attribute USVString credentialRequestOrigin; 1145 | readonly attribute object credentialRequestOptions; 1146 | readonly attribute DOMString hintKey; 1147 | Promise<WindowClient?> openWindow(USVString url); 1148 | void respondWith(Promise<WebCredential>handlerResponsePromise); 1149 | }; 1150 |1151 |
1156 | This attribute is a string that indicates the origin where the [[!credential-managment-1]] 1158 | method get() was called. 1159 |
1160 |1163 | The origin information of the relying party may be blinded when 1164 | received via a CredentialRequestEvent. It would be blinded to 1165 | allow it to still be signed without revealing where the request 1166 | came from. The user agent would be responsible for indicating 1167 | the origin of the request via its user interface. 1168 |
1169 |1175 | This attribute contains WebCredentialRequestOptions 1176 | dictionary containing the WebCredential type and 1177 | type-specific query that describes the credentials requested by 1178 | the web site. 1179 |
1180 |1186 | This attribute indicates the CredentialHint selected by 1187 | the user. It corresponds to the hintKey provided to the 1189 | CredentialManager.hints interface during registration. 1190 |
1191 |1197 | This method is used by the credential handler to show a window to 1198 | the user. When called, it runs the open window algorithm. 1199 |
1200 |1207 | This method is used by the credential handler to provide a 1208 | WebCredential when the request has been fulfilled. When 1209 | called, it runs the Respond to Credential Request 1210 | Algorithm with event and 1211 | handlerResponsePromise as arguments. 1212 |
1213 |1219 | dictionary CredentialRequestEventInit : ExtendableEventInit { 1220 | USVString credentialRequestOrigin; 1221 | WebCredentialRequestOptions credentialRequestOptions; 1222 | DOMString hintKey; 1223 | }; 1224 |1225 |
1226 | The credentialRequestOrigin, 1227 | credentialRequestOptions, and 1228 | hintKey members share their definitions with those 1229 | defined for CredentialRequestEvent. 1230 |
1231 |1238 | Instances of CredentialRequestEvent are created with the 1239 | internal slots in the following table: 1240 |
1241 |1244 | Internal Slot 1245 | | 1246 |1247 | Default Value 1248 | | 1249 |1250 | Description (non-normative) 1251 | | 1252 |
---|---|---|
1255 | [[\windowClient]] 1256 | | 1257 |1258 | null 1259 | | 1260 |1261 | The currently active WindowClient. This is set if a 1262 | credential handler is currently showing a window to the user. 1263 | Otherwise, it is null. 1264 | | 1265 |
1268 | [[\fetchedImage]] 1269 | | 1270 |1271 | undefined 1272 | | 1273 |1274 | This value is a result of fetching image object 1276 | or a fallback image provided by the user agent. 1277 | | 1278 |
1281 | [[\respondWithCalled]] 1282 | | 1283 |1284 | false 1285 | | 1286 |1287 | YAHO 1288 | | 1289 |
1297 | Upon receiving a credential request by way of get() and 1299 | subsequent user selection of a credential hint, the user 1300 | agent MUST run the following steps: 1301 |
1302 |1364 | The CredentialStoreEvent represents the data and methods available to 1365 | a Credential Handler after selection by the user. The user agent 1366 | communicates the WebCredential to be stored to the 1367 | Credential Handler. 1368 |
1369 |1370 | [Constructor(DOMString type, CredentialStoreEventInit eventInitDict), Exposed=ServiceWorker] 1371 | interface CredentialStoreEvent : ExtendableEvent { 1372 | readonly attribute USVString credentialRequestOrigin; 1373 | readonly attribute object credential; 1374 | readonly attribute DOMString hintKey; 1375 | Promise<WindowClient?> openWindow(USVString url); 1376 | void respondWith(Promise<WebCredential>handlerResponsePromise); 1377 | }; 1378 |1379 |
1384 | This attribute is a string that indicates the origin where the [[!credential-managment-1]] 1386 | method store() was called. 1387 |
1388 |1394 | This attribute contains WebCredential dictionary containing 1395 | the specific credential information that the web site is requesting 1396 | the user to store. 1397 |
1398 |1404 | This attribute indicates the CredentialHint selected by 1405 | the user. It corresponds to the hintKey provided to the 1407 | CredentialManager.hints interface during registration. 1408 |
1409 |1415 | This method is used by the credential handler to show a window to 1416 | the user. When called, it runs the open window algorithm. 1417 |
1418 |1425 | This method is used by the credential handler to provide a 1426 | WebCredential when the storage request has been fulfilled. 1427 | When called, it runs the Respond to Store Credential 1428 | Algorithm with event and 1429 | handlerResponsePromise as arguments. 1430 |
1431 |1437 | dictionary CredentialStoreEventInit : ExtendableEventInit { 1438 | USVString credentialRequestOrigin; 1439 | WebCredential credential; 1440 | DOMString hintKey; 1441 | }; 1442 |1443 |
1444 | The credentialRequestOrigin, credential, and 1445 | hintKey members share their definitions with those 1446 | defined for CredentialStoreEvent. 1447 |
1448 |1455 | Instances of CredentialStoreEvent are created with the 1456 | internal slots in the following table: 1457 |
1458 |1461 | Internal Slot 1462 | | 1463 |1464 | Default Value 1465 | | 1466 |1467 | Description (non-normative) 1468 | | 1469 |
---|---|---|
1472 | [[\windowClient]] 1473 | | 1474 |1475 | null 1476 | | 1477 |1478 | The currently active WindowClient. This is set if a 1479 | credential handler is currently showing a window to the user. 1480 | Otherwise, it is null. 1481 | | 1482 |
1485 | [[\fetchedImage]] 1486 | | 1487 |1488 | undefined 1489 | | 1490 |1491 | This value is a result of fetching image object 1493 | or a fallback image provided by the user agent. 1494 | | 1495 |
1498 | [[\respondWithCalled]] 1499 | | 1500 |1501 | false 1502 | | 1503 |1504 | YAHO 1505 | | 1506 |
1514 | Upon receiving a credential storage request by way of store() 1516 | and subsequent user selection of a credential hint, the user 1517 | agent MUST run the following steps: 1518 |
1519 |1581 | An invoked credential handler may or may not need to display information 1582 | about itself or request user input. Some examples of potential 1583 | credential handler display include: 1584 |
1585 |1600 | A credential handler that requires visual display and user 1601 | interaction, may call openWindow() to display a page to the user. 1602 |
1603 |1604 | Since user agents know that this method is connected to the 1605 | CredentialRequestEvent or a CredentialStoreEvent, they 1606 | SHOULD render the window in a way that is consistent with the flow and 1607 | not confusing to the user. The resulting window client is bound to the 1608 | tab/window that initiated the request. A single 1609 | credential handler SHOULD NOT be allowed to open more than one 1610 | client window using this method. 1611 |
1612 |1617 | This algorithm resembles the Open Window Algorithm in 1619 | the Service Workers specification and mirrors the one provided in 1620 | the Payment Handler API specification. 1621 |
1622 |1623 | Should we refer to the Service Workers specification instead of 1624 | copying their steps? 1625 |
1626 |about:blank
, return a
1637 | Promise rejected with a TypeError.
1638 | 1701 | This example shows how to write a service worker that listens to the 1702 | CredentialRequestEvent and the CredentialStoreEvent. 1703 | When a CredentialRequestEvent or CredentialStoreEvent 1704 | is received, the service worker opens a window to interact with the 1705 | user. 1706 |
1707 |1709 | self.addEventListener('credentialrequest', function(e) { 1710 | e.respondWith(new Promise(function(resolve, reject) { 1711 | self.addEventListener('message', listener = function(e) { 1712 | self.removeEventListener('message', listener); 1713 | if (e.data.hasOwnProperty('name')) { 1714 | reject(e.data); 1715 | } else { 1716 | resolve(e.data); 1717 | } 1718 | }); 1719 | 1720 | e.openWindow("https://www.example.com/wallet/get") 1721 | .then(function(windowClient) { 1722 | windowClient.postMessage(e.data); 1723 | }) 1724 | .catch(function(err) { 1725 | reject(err); 1726 | }); 1727 | })); 1728 | }); 1729 | 1730 | self.addEventListener('credentialstore', function(e) { 1731 | e.respondWith(new Promise(function(resolve, reject) { 1732 | self.addEventListener('message', listener = function(e) { 1733 | self.removeEventListener('message', listener); 1734 | if (e.data.hasOwnProperty('name')) { 1735 | reject(e.data); 1736 | } else { 1737 | resolve(e.data); 1738 | } 1739 | }); 1740 | 1741 | e.openWindow("https://www.example.com/wallet/store") 1742 | .then(function(windowClient) { 1743 | windowClient.postMessage(e.data); 1744 | }) 1745 | .catch(function(err) { 1746 | reject(err); 1747 | }); 1748 | })); 1749 | }); 1750 |1751 |
1752 | Using the simple scheme described above, a trivial HTML page that is 1753 | loaded into the credential handler window might include the 1754 | following script: 1755 |
1756 |1757 | <script> 1758 | window.addEventListener("message", function(e) { 1759 | var credentialRequestOptions = event.data.credentialRequestOptions; 1760 | 1761 | // TODO: process the query found in the request options and present 1762 | // choices to the user 1763 | // await ... 1764 | 1765 | e.source.postMessage({ 1766 | type: 'response', 1767 | credential: { 1768 | dataType: 'VerifiableProfile', 1769 | data: { 1770 | '@context': 'https://w3id.org/credentials/v1', 1771 | // ... 1772 | signature: { ... } 1773 | } 1774 | } 1775 | }); 1776 | window.close(); 1777 | }); 1778 | </script> 1779 |1780 |
1793 | dictionary CredentialHandlerResponse { 1794 | DOMString dataType; 1795 | object data; 1796 | }; 1797 |1798 |
1803 | The WebCredential type for the credential that the user 1804 | selected to fulfill the request. 1805 |
1806 |1812 | A JSON-serializable object that provides a 1813 | WebCredential type specific message used by the relying 1814 | party to authenticate the user. 1815 |
1816 |1817 | The user agent receives a successful response from the credential 1818 | handler through resolution of the Promise provided to the 1819 | respondWith() 1820 | function of the corresponding CredentialRequestEvent 1821 | interface. 1822 | The application is expected to resolve the Promise with a 1823 | CredentialHandlerResponse instance containing the response. 1824 | In case of user cancellation or error, the application may signal 1825 | failure by rejecting the Promise. 1826 |
1827 |1828 | If the Promise is rejected, the user agent MUST run the 1829 | credential repository failure algorithm. The exact 1830 | details of this algorithm are left to implementers. Acceptable 1831 | behaviors include, but are not limited to: 1832 |
1833 | 1843 |1850 | When this algorithm is invoked with event and 1851 | handlerResponsePromise parameters, the user agent MUST run 1852 | the following steps: 1853 |
1854 |1968 | The following example shows how to respond to a credential request: 1969 |
1970 |1971 | credentialRequestEvent.respondWith(new Promise(function(accept,reject) { 1972 | /* ... processing may occur here ... */ 1973 | accept({ 1974 | dataType: "VerifiableProfile", 1975 | data: { 1976 | "@context": "https://w3id.org/credentials/v1", 1977 | // ... 1978 | } 1979 | }); 1980 | })); 1981 |1982 |
2075 | This specification relies on several other underlying specifications. 2076 |
2077 |
2099 | TypeError
, and JSON.stringify
are
2101 | defined by [[!ECMA-262-2015]].
2102 | 2103 | The term JSON-serialize applied to 2105 | a given object means to run the algorithm specified by the original 2106 | value of the JSON.stringify function on the supplied object, 2107 | passing the supplied object as the sole argument, and return the 2108 | resulting string. This can throw an exception. 2109 |
2110 |2156 | When this specification says to throw an error, the user agent must 2158 | throw an error as described in [[!WEBIDL]]. When this occurs in a 2159 | sub-algorithm, this results in termination of execution of the 2160 | sub-algorithm and all ancestor algorithms until one is reached that 2161 | explicitly describes procedures for catching exceptions. 2162 |
2163 |2164 | The algorithm for converting an ECMAScript value to a dictionary 2167 | is defined by [[!WEBIDL]]. 2168 |
2169 |2170 | DOMException and 2171 | the following DOMException types from [[!WEBIDL-LS]] are 2172 | used: 2173 |
2174 |InvalidAccessError
"
2177 | InvalidStateError
"
2180 | NotAllowedError
"
2183 | NotFoundError
"
2186 | OperationError
"
2189 | SecurityError
"
2192 | ServiceWorkerRegistration
,
2212 | ServiceWorkerGlobalScope
,
2214 | handle
2216 | functional event, extend lifetime
2218 | promises,pending promises
2220 | count, containing
2222 | service worker registration, uninstalling flag,
2224 | Try Clear
2226 | Registration, Try Activate, and
2228 | scope URL are
2229 | defined in [[!SERVICE-WORKERS]].
2230 | The authors would like to acknowledge the editors and authors of the 2239 | Payment Request and Payment Handler specifications as this specification 2240 | has been largely influenced by their design and language.
2241 | 2242 |TODO
2243 |