Coder Social home page Coder Social logo

w3c / webappsec-credential-management Goto Github PK

View Code? Open in Web Editor NEW
47.0 62.0 35.0 2.25 MB

WebAppSec Credential Management

Home Page: https://w3c.github.io/webappsec-credential-management/

License: Other

Makefile 0.06% HTML 55.32% CSS 5.25% Bikeshed 39.37%

webappsec-credential-management's Introduction

Specification 'webappsec-credential-management'

This is the repository for webappsec-credential-management. You're welcome to contribute! Let's make the Web rock our socks off!

webappsec-credential-management's People

Contributors

autokagami avatar axelnennker avatar battre avatar dret avatar equalsjeffh avatar hillbrad avatar jakearchibald avatar johannhof avatar jyasskin avatar lukewarlow avatar marcoscaceres avatar martinthomson avatar miketaylr avatar mikewest avatar nidhijaju avatar npm1 avatar nsatragno avatar plehegar avatar saschanaz avatar sideshowbarker avatar stephenmcgruer avatar tyoshino avatar vabr-g avatar wseltzer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

webappsec-credential-management's Issues

Example 3 has wrong input type

In

<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="text" id="password" name="password" autocomplete="current-password">
  <input type="submit">
</form>

(see https://w3c.github.io/webappsec-credential-management/#examples-post-signin) the type of the password field is "text", but should be "password".

Support deleting credentials.

Should we support an API call to delete stored credentials?

If a credential delivered by the API does not work anymore, there is little use in trying to log the user in with that credential. This is particularly the case for credentials that don't require mediation: It's possible that on every page load, the user sees a banner indicating that the user is being logged in but every time the attempt fails.

On the downside, this may be abused by websites that try to circumvent the user's decision to store credentials in the local password manager.

Android has a similar CredentialsApi.delete() method.

Feature request: Add API for android finger print reader

Steps to reproduce the problem:
So, I wanted to develop a progressive web app where the user can log in with his finger print. But unfortunately there is no API on how to check the users finger is valid.

----- DISCLAIMER -----
I know that this is the wrong place to post a feature request. But I didn't find the right place. So if you could point me in the right direction, that would be awesome :)

What is the expected behavior?
So I see different very helpful use cases for this API:

  • Provide strong authentication with two factor authentication for an web app
  • Simple sign on process for web app

The registration process probably would look similar to the subscription process for web push notifications.

Saving PSL matched credentials

If a website retrieves a PSL matched credential via a user mediated get() and then calls store() on the credential, the credential can become eligible for unmediated provisioning.

Assume the user is on www.example.com and has a password stored for m.example.com. In this case, an account chooser dialog can offer the credential for m.example.com. Assume the user clicks on it and the site calls store(). Should the user be asked whether to store the credential in this case?

It may feel strange because the credential appeared to be stored already. At the same time, https://w3c.github.io/webappsec-credential-management/#user-mediated-storage prescribes that all stores need consent. Should we add an exception that PSL matched credentials may be persisted silently to https://w3c.github.io/webappsec-credential-management/#security-cross-origin-leakage ?

PSL issue: only PSL match on unmediated==false

Regarding the Passwords Cross Origin Leakage section:

I think that we should have a statement that "MAY use the Public Suffix List [PSL] to determine the effective scope of a credential by comparing the registerable domain of the credential’s [[origin]] with the origin in which get() is called." requires that unmediated is false.

Otherwise a bad situation can be that

This would happen because PasswordCredential's [CollectFromCredentialStore] would return two credentials.

@mikewest WDYT?

Clarify storage of a SiteBoundCredential

In the following step: "Store SiteBoundCredential"

The spec suggests it can accept SiteBoundCredential's but "Store a Credential" also suggests that types that extend from SiteBoundCredential also can be passed into the algo.

For example PasswordCredential permits the use of AditionalData and FederatedCredential accepts provider and protocol.

To me the storage algorithm isn't clear when it is storing this aditional data as I think the following statements are true:

  • FederatedCredential store provider and protocol data into the store
  • PasswordCredential stores idName, passwordName but not AditionalData into the store
    • Storing AditionalData would lead to the CSRF example replaying that field always
    • Storing files and arbitary amounts of data to the store doesn't seem the goal of the specification

unify with existing fetch credential system

Currently a fetch Request has a .credentials value indicating whether or not cookies should be sent with the request. These cookies are added as headers at the network layer. So the cookie headers are not available to script anywhere.

The currently proposed API in this repo, however, works completely differently. Instead of setting the credentials at the network layer they are set as the body up front in the constructor. The API then adds additional mechanisms for hiding the body from script.

As an alternative I'd like to suggest that we try to unify with the current fetch credentials systems:

  1. A CredentialRequestOptons object can be provided to the Request() constructor. It gets attached as some internal value. Providing both this value and a separate body would throw synchronously in the constructor.
  2. The Request functions normally to script. The body can be inspected, but simply shows an empty body. This is consistent with a Request with cookie credentials where the headers are simply not exposed.
  3. At the network layer the CredentialRequestOptions from (1) is used to lookup any credentials which are then serialized to the body. (Not sure if we should fail the request or proceed without credentials if the lookup fails. This could be controlled by an option to Request().)

This would directly map to our current fetch credential system. Step (1) is like passing { credentials: 'include' } to Request(). Step (2) is mirrors how we simply hide cookie headers today. Step (3) looks up and attaches the credentials at the same time that cookies are handled today.

In addition to being more consistent with the current system, this approach would also work better with the Cache API. If we serialize the actual Credential object into Cache and then the password is changed, using that Request out of the Cache will fail. With this alternate approach, however, we would look up the new password at the network layer and everything would continue to work.

Finally, I prefer this approach because I think adding an opaque variant of Request adds unnecessary complexity. Creating an opaque Request type can break existing libraries working with Request objects. Previously they could consistently access the body without throwing, but not if a Request is marked opaque at construction time.

CREDENTIAL: Use a generic matching algorithm that would work for custom Credentials types

From @adrianhopebailie on April 17, 2015 11:50

The spec defines custom matching algorithms for the different sub-classes of Credential. If this could be restructured into a single-generic algorithm it could be used for custom sub-classes of Credential.

Possible use-case illustrated below but suggests that options could be elevated/merged to the parent as types is also just a filter OR type could be a property of options.

Matching algorithm would be something like:
For each property of options eliminate all possible credentials where the Credential has a property with the same name and the value is not in the set of values provided.

//Store a FederatedCredential
navigator.credentials.store(
  new FederatedCredential({
    "id": "username",
    "federation": "https://federation.com"
  })
);

//Get a FederatedCredential filtered on the 'federation' property
navigator.credentials.get({
  "types": [ "FederatedCredential" ],
  "options": {
      "federation": [ "https://federation.com" ] //NOTE: This is no-longer called 'federations'
  }
});

// Assume we have defined an AgeVerificationCredential class which extends Credential
//  and defines it's type to be "ageVerification". There are some extra properties we might use
//  to do things like verification that are out of scope of this API

//Store a custom credential
navigator.credentials.store(
  new AgeVerificationCredential({
    "id": "person_12345_age",
    "isOlderThan18": true,
    "isOlderThan21": true,
    "issuer": "http://credentialissuer.com",
    "signature": { ... },
  })
);

//Get this custom credential filtered on some properties specific to this credential type
navigator.credentials.get({
  "types": [ "ageVerification" ],
  "options": {
      "isOlderThan18" : [ true ],
      "issuer" : [ "http://credentialissuer.com", "http://othertrustedissuer.com" ]
  }
});

Copied from original issue: w3c/webappsec#274

PasswordCredential(HTMLFormElement form) may destroy data on updating credentials

Assume the user has stored the following PasswordCredential:

{
 "id": "user",
 "type": "PasswordCredential",
 "name": "Example user",
 "iconURL": "http://example.com/user.png",
 "password": "p",
 "idName": "user",
 "passwordName": "password"
}

The user sees the following form:

<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="old-password">Old Password</label>
  <input type="text" id="old-password" name="old-password" autocomplete="current-password">
  <label for="new-password">New Password</label>
  <input type="text" id="new-password" name="new-password" autocomplete="new-password">
  <input type="submit">
</form>

Now the user changes the password to p2 in the form above and we create a new PasswordCredential object from the form as in Example 5 (see https://w3c.github.io/webappsec-credential-management/#examples-change-password). This would be:

{
 "id": "user",
 "type": "PasswordCredential",
 "name": "",
 "iconURL": "",
 "password": "p2",
 "idName": "username",
 "passwordName": "new-password"
}

This means that the navigator.credentials.store(c) call in example 5 would destroy the fields "name", "iconURL", "idName" and "passwordName", correct?

I see two options:

Option 1: put the burden on the web developer

In this case, we would need to update Example 5 with something like

  // Override c.name, c.iconURL to known information about the user.
  // Override c.idName, c.passwordName with values that are expected when logging the user in.

Option 2: special casing updates

In this case, we would make the following change.

  • If navigator.credentials.store(new_credential) is called and no previous credential exists that matches in the origin, id and type, this is a regular save operation and nothing changes.
  • Otherwise:
    • Assume that old_credential is an existing credential, navigator.credentials.store(new_credential) is called, and old_credential and new_credential match in their origin, id and type. This means new_credential is an update to old_credential.
    • If old_credential contains an attribute that is not contained in new_credential (like "name" and "iconURL" in the previous example), these attributes are not modified in the persisted credential.
    • If new_credential is derived from a form with a autofill="new-password" attribute, don't modify the persisted idName and passwordName.

@mikewest @vabr-g What do you think of these solutions?

PSL issue: Unify collected credentials

I think that we should have a unification step in PasswordCredential's [[CollectFromCredentialStore]](options).

Imagine the following steps:

A related case is the following:

Imagine the following:

  • User has {name: foo, password: bar} on https://www.example.com
  • User has {name: foo, password: baz} on https://admin.example.com
  • User goes to https://www.example.com. Even in the mediated case, only {name: foo, password: bar} should be offered. This comes for free if issue 66 is fixed.
  • User goes to https://test.example.com. In this case, either only one credential should be offered (because the visible identifier ("foo") is the same for both credentials and there is no UI that can explain the difference between the two credentials), or no credential should be offered.

@mikewest WDYT?

Enforce cross sub domain credential sharing

MAY use the Public Suffix List [PSL] to determine the effective scope of a credential by comparing the registerable domains of the credential’s [[origin]] with the origin in which get() is called. That is: credentials saved on https://admin.example.com/ and https://example.com/ MAY be offered to users when get() is called from https://www.example.com/.

I propose we should change the "MAY" to "MUST", so that enforces the implementation of cross subdomain credential sharing.

Reasonings:

  • Many websites breaks themselves into different sub websites each having a sub domain. For sites implemented single point authentication, they usually have a standalone sub domain for that. If user agent doesn't implement cross sub domain credential sharing, this API will not work for those sites.
  • Many websites have a separate mobile site apart from their desktop site, which usually have different sub domains. By enforcing credential sharing across sub domains, user experiences are reinforced because they always get seamless sign-in workflow between desktop browser and mobile browser.

Should PasswordCredential accept `id` of the form elements if the `name` is missing?

https://w3c.github.io/webappsec-credential-management/#passwordcredential-form-constructor requires that form input elements have name attributes, and derives the credential metadata based on those. It ignores the id attribute. In the absence of name, could it fall back to accepting id as the source for the name in the metadata? (This is what happens in the particular case of Chrome and form-based autofill (see HTMLFormControlElement::nameForAutofill in https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/HTMLFormControlElement.cpp?sq=package:chromium&dr=C&rcl=1482394814&l=625-632).

PasswordCredential(HTMLFormElement form) Constructor not very robust

If the PasswordCredential(HTMLFormElement form) constructor gets the following form

<form action="https://example.com/login" method="POST" id="theForm">
  <label for="username">Username</label>
  <input type="text" id="username" autocomplete="username">
  <label for="password">Password</label>
  <input type="text" id="password" autocomplete="current-password">
  <input type="submit">
</form>

the formData object will be empty (because the input elements have attributes id instead of name). The resulting PasswordCredential will have no id element and therefore will be invalid. As a result of that, storing the credential will generate an error message that the credential has no id.

Wouldn't it be better if the PasswordCredential constructor performed some kind of validation and throw an exception if the form had no username/password field to fail early? A PasswordCredential, which is derived from Credential, has a readonly id field. Therefore, I think it is impossible to create a partially initialized PasswordCredential that is finished later.

Documentation for `unmediated` option unclear

I'm having trouble understanding what the unmediated element of CredentialRequestOptions actually does:

https://w3c.github.io/webappsec-credential-management/#interfaces-credentialrequestoptions

In particular, I'm unclear which part of the documentation deals with the true case and which is covering the false case. I also don't completely understand the different options.

Here's an attempt to rewrite the paragraph into something that's more clear (if not actually correct).

Before:

If true, the user agent will only attempt to provide a Credential without user interaction. It MUST NOT present the user with any visible prompt to grant access to a Credential: if the user has opted-into always giving a particular site access to a particular set of credentials, they will be provided. If not, the promise will resolve with undefined. For processing details, see the algorithm defined in §4.1.1 Request a Credential.

After:

If true, the user agent will only attempt to provide a Credential if the user agent allows credentials to be provided without user interaction. That is, it MUST NOT present the user with any visible prompt to grant access to a Credential (unless the user has overridden this setting and opted-into always giving a particular site access to a particular set of credentials). If false, the promise will resolve with undefined. [??? false is the default]

5.3. Credential Selection could make it clearer which credentials are allowed to be presented

§ 5.3. Credential Selection says that the chooser UI SHOULD include all credentials from the requesting origin, but does not comment on what credentials it should not contain. §
6.1. Cross-origin Credential Leakage
hints that other credentials to be included are PSL-matched ones.

My questions:
(1) Should 5.3 mention PSL-matched credentials explicitly as appropriate to be shown?
(2) Is the omission of other potential types of credentials to be shown on purpose, to allow extending the implementations without the need to change the spec?

@mikewest, what do you think?

CREDENTIAL: requestAutocomplete can already provide local credentials

From @mnoorenberghe on August 4, 2015 20:15

The LocallyStoredCredential aspect of the spec duplicates functionality provided by requestAutocomplete with autocomplete="(username/new-password/current-password)" and doesn't seem to be adding enough value to justify having duplicate UI. As an implementer of a password manager and requestAutocomplete, I don't want to have to maintain separate UI for these two specs as there is significant overlap and I believe the differences/inconsistency could confuse users.

I also think the user experience is much better building local credential support on top of requestAutocomplete (rAc) as it can fill complete forms with one button click and already has a good fallback story for browsers that don't support it where they simply show the

they already created. Browsers can already indicate if they can't support rAc for some fields in the form. Being able to complete a whole registration form (e.g. Name, Email, Address, Username, & Password) with one rAc dialog would be much better than having to use rAc followed/preceded by a separate credential management API call and UI.

I propose that the local credential support be specified atop the existing requestAutocomplete specification instead of a standalone spec. I haven't looked at the federated credential aspects recently to know if they could also be easily mapped into rAc but I suspect they could using new autocomplete values and <input type="hidden">.

Copied from original issue: w3c/webappsec#445

Update body-extraction algorithm to match Fetch spec

The steps to generate the request body, found in https://w3c.github.io/webappsec-credential-management/#body-extraction, should match the pattern used in the spec for fetch: https://fetch.spec.whatwg.org/#concept-bodyinit-extract.

In particular, in addition to describing the body and the Content-Type, it should also use action to describe the transformations.

This came up in https://github.com/w3c/webappsec-credential-management/pull/48/files/4989e07d182bf017954954bbe6d0980fbb7c54dc#diff-117d6498d2aa8019cc0abf5eeb87a9fa (look at line 1400), and it seemed like worth clarifying before introducing new text in that section of the CM API spec.

storeCredentials() method on HTMLFormElement

One of my concerns with this API is that it may encourage behaviour which isn't backwards-compatible with UAs who don't implement it even though there are compatible ways to do the same thing. The spec doesn't even provide any examples of using .store() with a <form> so authors are going to end up not using a form submit event with preventDefault() when they want to use this API to store credentials meaning existing UAs will need to use heuristics to detect the "submission".

One of the benefits that this spec provides is an imperative API to store a credential. I think such an API should (instead) be on <form> to encourage best practices since <form> has benefits for accessibility and UX. When this method (e.g. storeCredentials()) is called, the UA would store credential-related fields (determined based on the autocomplete attribute, no heuristics) similar to 4.1.2. Store a Credential. Ideally this would be the only way to store compatible credentials to ensure this backwards-compatible API is used. As I mentioned before, I think this could work for federated credentials with rAc too.

If wanted, additional restrictions can be placed on this new method e.g. requiring that rAc was successful on it and/or that the <form> submit event has occurred.

This combined with #2 would remove the need for the LocalCredential interface.

Example:

<script>
document.forms[0].addEventListener("submit", function(evt) {
  evt.preventDefault();
  var formData = new FormData(evt.target);
  fetch("https://example.com/loginEndpoint", { method: "POST", body: formData })
    .then(function (response) {
      if (evt.target.storeCredentials) {
        evt.target.storeCredentials();
      }
      // Notify the user that signin succeeded! Do amazing, signed-in things!
    });
});
</script>
<form>
  <input name="un" autocomplete="username">
  <input name="pw" autocomplete="current-password">
  <input type="submit" value="Login">
</form>

PasswordCredential(HTMLFormElement form) may fail in valid password change form cases

The following form is a valid change password form that fails to be parsed by the PasswordCredential(HTMLFormElement form) constructor

<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="new-password">New Password</label>
  <input type="text" id="new-password" name="new-password" autocomplete="new-password">
  <label for="old-password">Old Password</label>
  <input type="text" id="old-password" name="old-password" autocomplete="current-password">
  <input type="submit">
</form>

The PasswordCredential(HTMLFormElement form) constructor is sensitive to the order of "current-password" and "new-password" fields. It takes the last one and stores it in the credential. In the example above, the old password gets saved, not the new one.

CREDENTIAL: Generic matching algorithm

From @adrianhopebailie on April 22, 2015 23:25

This change updates the model for Credential to include an isMatch() function hook which is called during processing of the Credential request algorithm. The hook can be overridden by developers designing their own Credential classes in script therefor making the API flexible and extensible through ECMAScript.

Resolves #274

Copied from original issue: w3c/webappsec/pull/292

CREDENTIAL: Credential scope should not be limited to login

From @dlongley on April 15, 2015 13:58

Credentials may be used for more than just login, and a credential may not represent a user's entire identity. This means that browsers can't just take a list of credentials and throw them up in a UI when someone is attempting to log into a website. It also means the API should support more complex queries for the types of credentials desired. This likely means redefining what a credential is -- and making changes to the Credential base class.

There are at least two ways to proceed:

  1. Consider some credentials to be "LoginCredentials" (or username+password legacy credentials) and others to be of a more generalized sort. The browser only bothers displaying "LoginCredentials" in a special way. Browsers can defer to IdPs for displaying non-LoginCredentials.
  2. Consider that all credentials are of a generalized sort, and browsers will have to inspect a variety of properties about them to determine how to best display them to users. Browsers could also simply defer to IdPs to handle specialized display.

In the Credentials CG work, we don't consider "login" to be a special use case. A relying party may ask for whatever credential they want to in order to authorize a user to take some action or to simply collect information about that user for later review, etc. For example, "login" can be implemented by requesting a "Verified Email Credential" from a user. It could be implemented in another way as well.

The current Credential Management API sees the "login use case" as a special first class citizen, which makes perfect sense, considering that it is scope-limited to making incremental improvements to "login" via a new imperative password manager API. I don't see any conflict with the Credentials CG in this respect.

The conflict arises from the fact that the spec aims to do more than just provide an API for password managers, it suggests there is "future work" and attempts to define an extensible API to try and cover it. Again, it makes perfect sense that you'd want such an API to support a broader range of credentials if it can. Fortunately, the Credentials CG has spent years working on designs and technologies in the "future work" space the Credentials Management API refers to. Unfortunately, the current design feels a bit inverted to those of us that have spent that time. I don't have a quick fix for this particular issue -- but it's clear to me that how we want credentials to work in the future doesn't quite mesh with the existing "login" paradigm.

Obviously, it would be nice to make a minimal number of changes to the API now to future proof it -- and then simply list these goals out in the future work section.

Copied from original issue: w3c/webappsec#256

Request a Credential algorithm is confusing

https://w3c.github.io/webappsec-credential-management/#request-credential has some confusing parts:

  • It declares |types| as an argument, then resets it in step 4. It also references |possible types| once.
  • It iterates over all "|key|[s] in |options|" and looks for interfaces which are named as the keys; it mentions PasswordCredential and FederatedCredential as examples. However, https://w3c.github.io/webappsec-credential-management/#interfaces-credentialrequestoptions defines the |options| and none keys are the names of any of those interfaces.

My guess is that to fix the first item, |types| should not be part of arguments (they don't seem to be in the implementation in Chrome, if I read the code starting in CredentialsContainer::get of [1] correctly). Also, |possible types| should be just |types|, fixing the remaining part of #39.

To derive the credential type from |options| one currently needs to consider the value of the |password| field, and the presence of the |federated| field. I don't see a way to phrase this in a general way.

@battre and @mikewest please correct me if I'm missing something.

[1] https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/credentialmanager/CredentialsContainer.cpp?q=CredentialRequestOptions&sq=package:chromium&dr=C&l=160

CREDENTIAL: Reconsider the top-level browsing context limitation.

From @mikewest on May 20, 2015 18:54

Step 3.2 of https://w3c.github.io/webappsec/specs/credentialmanagement/#request-credential rejects the Promise returned by get() if it's called from a nested browsing context. @hillbrad suggested that this limitation would be a problem; I argued with him a bit on the last call (http://www.w3.org/2015/05/18-webappsec-minutes.html#item01), but now I think he might be right.

I'd suggest changing the text to prevent returning credentials without user mediation in a nested browsing context, but allowing the user to choose to grant access to credentials in a nested context. @hillbrad's argument that this actually increases security (for all the reasons that the API/password managers in general increase security in the top-level frame) seem reasonable.

I am still a bit worried about confusing the user with a popup that refers to a frame inside the document they're looking at, but I'm working on convincing myself that it's fesiable.

/cc @devd, @terriko, @dveditz who also participated in the discussion.

Copied from original issue: w3c/webappsec#380

Remove the `PasswordCredential` constructor taking a `PasswordCredentialData` in favour of the form version

from /issues/13#issuecomment-200872210

But you're right that that scenario wouldn't require a broken-up constructor as long as we have setters on the object. I'll go back to the developers we're talking with to see how they're using the method. shrug Maybe you're right that we can get rid of it.

Removing support for the PasswordCredential constructor taking a PasswordCredentialData would make be feel better about this API for the following reasons:

  • it wouldn't tempt developers to have the server put the plaintext password back into the page landed on after a login submission just to call the constructor and save the password (which obviously would be bad for security).
  • it wouldn't encourage usage of non-form login experiences (keeping it backwards compatible with existing password managers as there's not a good reason to break them)

We can add the PasswordCredentialData constructor in a later version if the carrot of the API ends up not being enough for adoption.

Security Considerations section should contain additional guidance

CM API offers protection against a class of XSS attacks to obtain passwords. However, there are still some attacks not prevented by CM API itself. One is described in https://crbug.com/686487 and one more in a particular comment on that bug https://crbug.com/686487#c10. (Not listing those scenarios here until that bug is public.)

We could add a non-normative section in the Security Consideration, listing suggested additional security measures to be used in combination with CM API to provide the best protection against XSS attacks on passwords.

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

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.

Fix bikeshed warnings

Currently, bikeshed spews a couple of warnings when processing index.src.html, about unique instances of variables. Those need to be checked and marked as ignore or fixed.

User agent should/may not allow overriding "store" and "get"

If a malicious party is able to inject script into an origin, they could (among many other things you wouldn’t like) overwrite the behavior of store() to steal a user’s credentials as they’re written into the credential store.

I propose the following changes.

User agents *MAY*/*MUST* prevent overriding following methods.

- navigator.credentials.store
- navigator.credentials.get

This is doable, just like the non overridable location.origin. Ignoring this feature imposes users to the leak of personal credentials due to poor security implementations.

I also want to point out strongly that we at least say user agents MAY implement this feature.

CREDENTIAL: could we make it easier to extend?

From @jonathanKingston on September 29, 2015 0:59

Hey all,

So I was taking a closer look at the Credential Management API and CredentialRequestOptions struck me as not very extensible.

Initial thoughts:

  • Does CredentialRequestOptions make sense as an object, an array of typed objects may make sense
  • Having a separate meta/options object may make more sense:
  • Does having a two part interface to Credential make more sense for their API?
    • Constructor could be separated from a create() method.
      • FederatedCredential constructor would stay the same
      • PasswordCredential would move it's arguments to: .create({id: 'myid', password: 'mypassword'})

For example:

  navigator.credentials.get([
    new PasswordCredential(),
    new FederatedCredential({
       "providers": [ "https://identity.example.com/" ]
    })
  ], {
    suppressUI: true
  })

And:

  navigator.credentials.get([
    new PasswordCredential()
  ], {
    suppressUI: true,
    credentialClass: 2 
  })

Extensible methods:

Copied from original issue: w3c/webappsec#490

should incumbent settings object be relevant settings object?

incumbent settings object is utilized in several places in the spec, although there's this warning in the HTML spec here (scroll down below the example):

Warning: The incumbent and entry concepts should not be used by new specifications, as they are excessively complicated and unintuitive to work with. We are working to remove almost all existing uses from the platform:​ see issue #1430 for incumbent, and issue #1431 for entry.

Should this spec be using the relevant settings object instead?

Allow a site to specify a JSON template with a placeholder for the credential

Currently, to post the request with credential for authentication, the site needs to initialise the request with the opaque PasswordCredential object. The goal is to avoid leaking the credential to the potentially compromised JavaScript on the site.

Some frameworks might require a specific format of the request, e.g., JSON. That cannot currently be achieved, because the CM API implementation formats the body as multipart/form-data.

To allow more flexibility, while preserving the leak protection, could we make it an option to create the request with a JSON template with a placeholder, which the CM API implementation would replace with the serialisation of the credential upon sending the request off?

Unclear how to distinguish between: no credentials versus user dismisses login window (clicks X)

It is unclear how to distinguish between: no credentials versus user dismisses login window (clicks X)

In this example the else if statement is triggerd for both

  • no credentials stored
  • or when unmediated & more than 1 credentials stored
  • or when users clicks cross/dismisses login

for the first two the flow is fine. But for the latter we would want to set a cookie or at least do something to not disturb the user again if he/she refreshes the page or moves to a seocnd page on our website

navigator.credentials.get({password: true, }).then(function(cred) { 
            if (cred) {
                } else if (typeof cred === "undefined") {

Dealing with failed logins

The spec does not give precise guidelines for dealing with failed logins.

Assume the following setup:

  • User has one credential stored with required user mediation being false.
  • The website contains the following code on every page:
    if (user not logged in) {
      navigator.credentials.get({"password": true}).then(login_user);
    }
    

As a result of this, the user will be notified about a login attempt on every navigation that will always fail.

What should we do about this?

  • Tell the developer to
    • Call requireUserMediation() on a failed login.
    • Only call navigator.credentials.get({"password": true, "unmediated": true}) on every page.
  • Allow the website to call navigator.credentials.get({"password": true}) on every page but introduce a navigator.credentials.delete(c) function that tells the user "The website asked to delete the credential (probably due to a failed login). Do you want to delete it? [yes] [no]"

Credential terminology and Fetch

#11 made me realize that if "Credential" becomes a thing, the existing "credentials mode" of Fetch will be very confusing. Note that Request and fetch() already accept credentials member in a dictionary. Request also exposes it as a property.

Is it too late to use "Login" or some such instead of "Credential"?

Consider assigning an `HTMLFormElement` to `.additionalData`

Code like https://github.com/guardian/identity-frontend/pull/142/files#diff-219191b73f6f83d39ebf4d2c59e68eadR50 seems like it's going to be a fairly common pattern. Rather than writing:

c.additionalData = new FormData(document.querySelector('#signin_form'));

Perhaps we could write:

c.additionalData = document.querySelector('#signin_form');

And run that form element through the same algorithm we use for new PasswordCredential(form). That would remove the cognitive load of deciding whether to use FormData or URLSearchParams (as we'd do whatever the form would do on its own), and encourage folks to have a fallback form on their pages for users to fill out in UAs that don't support the API.

Note that a UA may create a new credential from the selection UI

I think it may be useful to note in "Request a SiteBoundCredential with user mediation" step 2 and/or "Credential Selection" that a UA could provide UI to allow the user to use a PasswordCredential that isn't already stored by the UA.
This would improve:

  • the UX for cases where the user wants to use a credential other than one that is currently saved (perhaps without saving it permanently this time either) so the user can use the trusted UI consistently for the site
  • security for the initial capture of the password credential which is otherwise usually captured from regular <input> which could be read by an attacker via XSS

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.