-
Notifications
You must be signed in to change notification settings - Fork 178
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Signal API #2093
Add Signal API #2093
Conversation
index.bs
Outdated
1. If the result of [=base64url encoding | base64url decoding=] | ||
<code>|options|.{{PublicKeyCredentialSignalOptions/unknownCredentialId}}</code> | ||
is an error, then throw a {{TypeError}}. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need anything here, in the name of avoiding abuse of this call (either by RP or malicious JS), to have the client remember the credential ID in the last resolved .get()
response and only allow the RP to specify that ID in a subsequent unknownCredentialId
report? The idea being, if an RP receives a response with an id
of "credA", they shouldn't ever set anything but "credA"
in their unknown credential Report.
Thinking one step further, I'd say if that idea has merit then what's the point in the RP specifying a credential ID? The RP could more simply signal "I didn't recognize that credential" and the client uses its own knowledge of the last used credential's ID to deprecate that credential. No value validation needs to go on, the RP passes a simpler value for this specific report... 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In terms of abuse, malicious JS can do way more nasty things, such as steal assertions and intercept credential creation requests that we can't meaningfully defend against so I would consider it outside the threat model. I lack the imagination to see what a malicious RP could do with this endpoint as specified, do you have an example?
The RP could more simply signal "I didn't recognize that credential" and the client uses its own knowledge of the last used credential's ID to deprecate that credential. No value validation needs to go on, the RP passes a simpler value for this specific report... 🤔
I think this is conceptually fine, but significantly more complicated in terms of implementation for no discernible benefit. We'd have to specify how long we remember the credential id for, whether we do it across navigations, and what the remembered credential id is keyed to (the frame? the global browser object?). I would prefer not to go this route unless we find a good reason to avoid RPs from specifying arbitrary credential ids.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd have to specify how long we remember the credential id for, whether we do it across navigations, and what the remembered credential id is keyed to
Maybe it could be tied by exposing the signal as a callback method exposed on the PublicKeyCredential
instance, but I agree this seems overcomplicated for little benefit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also thank you very much for applying Base64URLString
as abundantly as you have, this will save RPs so much time and effort 🙏
This is ready for initial review, with the understanding that we might want to tweak things as we progress with the implementation. |
index.bs
Outdated
dictionary CurrentCredentialsReport { | ||
required USVString rpId; | ||
required Base64URLString userId; | ||
CurrentCredentialUserDetails user; | ||
sequence<Base64URLString> allAcceptedCredentialIds; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be argued that this report identifies itself as an exhaustive list of recognized credential IDs. If we accept that, could we shorten allAcceptedCredentialIds
to credentialIds
? Make it look more like UnknownCredentialIdReport.credentialId
for brevity 🤔
dictionary CurrentCredentialsReport { | |
required USVString rpId; | |
required Base64URLString userId; | |
CurrentCredentialUserDetails user; | |
sequence<Base64URLString> allAcceptedCredentialIds; | |
}; | |
dictionary CurrentCredentialsReport { | |
required USVString rpId; | |
required Base64URLString userId; | |
CurrentCredentialUserDetails user; | |
sequence<Base64URLString> credentialIds; | |
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you suggesting that "Current" in "CurrentCredentialsReport" is enough of an indication that the RP must put all credential ids in here, and that it's superfluous to reinforce that with "allAccepted"?
My initial reaction is to keep it as is, because the consequences can be drastic: A provider may, and likely will delete any credential it has that is not included on the list. I.e. the meaning of the field here is very different from the credentialId field in the UnknownCredentialIdReport.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, we could go a slightly different route here and rename CurrentCredentialsReport
to AllAcceptedCredentialsReport
? Paired with a rename of allAcceptedCredentialIds
to credentialIds
it might be more explicit 🤔
To keep the bikeshedding going, there might also be a possibility of leaving it called CurrentCredentialsReport
but renaming allAcceptedCredentialIds
to allCurrentCredentialIds
.
Having said this I think what I'm trying to do is unify the wording here. I don't particularly care if we go with "current" or "accepted", but I do feel as though there should be one word used for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From RP perspective: Nothing in the name suggests the implicit "deletion" of non-listed Credentials - while this is the most critical part of this operation. It could also be a separate parameter (credentialIds
and deleteOtherCredentials
) or maybe something hinting in that direction onlyAcceptedCredentialIds
. It feels awkward to me because, on the one hand, this is a selector in the style of allowCredentials like a WHERE
clause for the updated fields, but at the same time it is also an implicit DELETE
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could also be a separate parameter (credentialIds and deleteOtherCredentials)
It should not be an explicit list of credentials to be deleted because otherwise the relying party has to keep that list ~forever.
Hmm, we could go a slightly different route here and rename CurrentCredentialsReport to AllAcceptedCredentialsReport?
How about AllAcceptedCredentialsReport
and keep allAcceptedCredentialIds
? That way we get consistency and an explicit string. I'll also add a warning that this will remove or hide all credentials not in the list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a note warning of deletion. Splitting the username / displayname updates should help avoid the deletion footgun when a developer is only interested in updating that.
The way to invoke the API now is:
PublicKeyCredential.signalAllAcceptedCredentialIds({
rpId: "example.com",
userId: "aabbcc", // user handle, base64url.
allAcceptedCredentialIds: [
"bb",
]
});
I cannot think of something more obvious short of credentialsNotPresentInTheFollowingListShouldBeDeletedIKnowWhatImDoing
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I cannot think of something more obvious short of credentialsNotPresentInTheFollowingListShouldBeDeletedIKnowWhatImDoing.
No good idea myself. There are only good ones when inverted .... RemoveUnlistedCredentialIds
DeleteNonListedCredentialIds
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about
AllAcceptedCredentialsReport
and keepallAcceptedCredentialIds
? That way we get consistency and an explicit string. I'll also add a warning that this will remove or hide all credentials not in the list.
I think this is probably the way to go. An issue with potential names like RemoveUnlistedCredentialIds
and DeleteNonListedCredentialIds
could be that different providers do different things. As suggested earlier, maybe a provider wants to tag a not in the list passkey vs delete it outright. "Accepted" vs "Remove" or "Delete" gives providers greater flexibility to handle such a signal without making it confusing to explain to RP's the impact of making such a call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My only high level comment is that this structure allows combination of the two defined report types, which there is probably never a reason to do, but not a combination say two CurrentCredentialsReports with different RP-Ids, which there may be a reason to do (e.g. 'www.example.com' and 'example.com').
I don't think that's a major problem though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks pretty good to me!
This commit adds a `PublicKeyCredential.signal` method that relying parties can call to notify authenticators of changes on the applicability or metadata of credentials. Closes w3c#1967
This is ready for another pass. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
RP perspective: This looks great overall and should solve some real usability needs in some areas that are a little clumsy today. Looking forward to adding support here!
Thought: is it worth adding anything into getClientCapabilities()
output, or is it enough to feature-detect on the new methods directly?
Co-authored-by: Emil Lundberg <[email protected]>
Notes are not normative. Co-authored-by: Emil Lundberg <[email protected]>
Co-authored-by: Emil Lundberg <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @nsatragno!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
mostly editorial suggestions
Co-authored-by: Tim Cappalli <[email protected]>
I've filed #2121 to track whether we want to deprecate @akshayku, please take a look! |
Update the Signal API IDL to match the current specification. This also adds tests for the context detached detection code. See w3c/webauthn#2093 Bug: 361751877 Change-Id: Ie04b937f78b9d831562d470e5b66582b85c97016 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5812756 Commit-Queue: Nina Satragno <[email protected]> Reviewed-by: Ken Buchanan <[email protected]> Cr-Commit-Position: refs/heads/main@{#1347668}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great to me!
This PR adds a
PublicKeyCredential.signal*
set of methods that relying parties can call to notify authenticators of changes on the applicability or metadata of credentials.PublicKeyCredential.signalUnknownCredentialId
This lets the relying party notify the authenticator that a request with a given credential id would be rejected.
PublicKeyCredential.signalAllAcceptedCredentialIds
This lets the relying party send a snapshot of all the credential IDs it will accept for a user, allowing the authenticator to hide or remove credentials not present.
PublicKeyCredential.signalCurrentUserDetails
This lets the relying party update a user's
name
anddisplayName
.Please see the explainer for more details.
Closes #1967. Closes #2038.
Preview | Diff