w3c / webappsec-credential-management

WebAppSec Credential Management
https://w3c.github.io/webappsec-credential-management/
Other
50 stars 38 forks source link

Support programmatically filling a `<form>` with a PasswordCredential #17

Open mnoorenberghe opened 8 years ago

mnoorenberghe commented 8 years ago

To reduce the amount of client-side changes needed to implement the API on sites already using a <form> I propose adding a method to fill a <form> with the username and password using the same autocomplete attribute mapping used for the PasswordCredential <form> constructor. Currently sites are required to use fetch in order to do the login.

Section 1.2.1 specifically mentions the idea of using the credentials "in existing sign-in forms" but then goes on to use fetch instead.

Example based on section 1.2.1:

navigator.credentials.get({ "password": true }).then(
    function(credential) {
      if (!credential) {
        // The user either doesn’t have credentials for this site, or
        // refused to share them. Insert some code here to show a basic
        // login form (or, ideally, do nothing, since this API should
        // really be progressive enhancement on top of an existing form).
        return;
      }
      credential.fillForm(myForm);
      myForm.submit();
    });

(I removed the .type check as it seems like it wasn't necessary given the specified CredentialRequestOptions)

Ideally UAs would require something like @writeonly or a strong CSP policy for this to be supported but I don't think that needs to be a blocker as there are still UX and security benefits without this. Noting that in the spec would be good.

jmalonzo commented 8 years ago

It would be nice if this is possible - the PasswordCredential API as it stands it very much tied into fetch. We have some sites that use other authentication mechanisms outside of what fetch currently supports (e.g. websocket), so it would be nice to support non-fetch use-cases and I think this is the first step in helping us do that.

battre commented 7 years ago

@mikewest, this is related to our discussion yesterday.

Could we drop the dependency on writeonly by introducing credential.fillFormAndSubmit(myForm)?

One caveat though: A website that relies on "login by posting a form" will have a hard time to save / update credentials because they lack the credential object on the landing page where they can determine whether a login with typed PasswordCredentials succeeded.

mikewest commented 7 years ago

I agree with the general suggestion of making integration simpler by introducing a navigational mechanism, but it's not clear to me how we'd make this work without exposing passwords to JavaScript. I'll outline a few thoughts below:

Could we drop the dependency on writeonly by introducing credential.fillFormAndSubmit(myForm)?

How would you expect that to work without writeonly? It seems like passwords would still be exposed to JavaScript at several points:

  1. The attacker hooks the submit event for the form
  2. The attacker hooks the beforeunload event for the page
  3. The attacker adds change event handlers to the relevant input fields

MutationObserver might also work. And the data would be exposed to Service Workers. And etc.

The writeonly concept seems like it could address a number of these concerns. Service Workers aside, the feature itself is a pretty trivial implementation (even if deeper integration with the password manager for general autofill is a lot more work).

battre commented 7 years ago

My thought was that submit, beforeunload, change would all be triggered before any DOM modifications. Then a synthetic HTTP POST with corresponding navigation would be generated.

mikewest commented 7 years ago

Hrm. Ok. We might be able to make that work. Without looking at Blink's form-submission implementation, I suspect it will be complicated to implement, but that's just typing.

However, that's going to require some non-trivial changes to https://html.spec.whatwg.org/multipage/forms.html#concept-form-submit (which serializes the form's data prior to beginning navigation), and would certainly be web-visible (which might cause problems for folks who rely on validating the data in a form, or do weird JavaScripty things with it (though, let's assume we can ignore them, since this is an opt-in API)).

How would you expect that to integrate with the password manager's submission detection? Would we assume success and call store() for the developer?

battre commented 7 years ago

I think that folks who rely on validating the data in the form or doing weird JavaScripty things might have an issue with writeonly as well. Maybe the proposal is just too hacky and we need writeonly.

The issue with the need of a store() call remains also in the credential.fillForm(myForm); myForm.submit(); with readonly support case. I'll think more about it.