-
Notifications
You must be signed in to change notification settings - Fork 172
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
devicePubKey → supplementalPubKeys #1957
Conversation
What kind of "supplemental keys" will this be used for ? |
The PR is rather extensive, but it does have updated examples if you'll permit me just to quote them:
|
Thanks for the explanation! |
Couldn't this be solved by assertion-time attestation? "Hey I didn't get attestation during registration; please prove this key is hardware bound; my policy changed" sounds simpler from an implementation-POV |
Assertion-time attestation is for the primary key, but the primary key might not be hardware bound, nor have the other properties that sites are interested in. Also, assertion-time attestation closes over the challenge, meaning that it has to be calculated for every assertion. The assertion for a supplemental key can be fixed and cached. (Doing an online assertion for every sign-in is a little fraught from both privacy and reliability perspectives. If a site wants a remote assertion for every sign in, they might want federation.) |
This raises the question of if we want to keep the added complexity of attestation over the challenge for the primary key on get? |
I'm not really understanding the usecase why you would have multiple keys per credential. It sounds complicated. Why not ask the user to register a new credential that does satisfy the assurance levels if their old one doesn't satisfy the new assurance level anymore? |
I don't think there are any implementations of assertion-time attestation at the moment so I'm fine with that. But I think some enterprise-focused passkey providers might want to put device integrity signals in there and thus do want to close over the challenge.
Multi-device credentials currently don't have any attestation and, for the vast majority of cases, that is sufficient. If you're worrying about supplemental keys you should probably be a bank with a large fraud and compliance department, otherwise you're probably making a mistake. So, in some sense, the complexity might be a useful guide for people. But, in that context, the thinking roughly goes that, as a bank, there's only so much that you can depend on a passkey for: you may be subject to inflexible requirements about authentication in particular regions. So while you might accept a passkey for sign-in, an additional signal is needed before allowing, say, money transfers. So if we can staple a device-bound signal to a passkey perhaps you can avoid bothering the user with additional factors quite so often if you have built up trust in the device. This was the motivation for devicePubKey. But that leaves a gap when the user is on a new device. A passkey provider likely has useful information about how the user authenticated themselves on that new device but we don't want to tie that to the primary key because you'll probably see import/export interoperability start to appear between passkey providers in the coming year. Thus we add another key, a provider-scoped supplemental key. The basic idea is the same as with a devicePubKey, but it might signal something like “this supplemental key is only synced after a specified level of 2FA authentication has been performed”. (Where the definition and evaluation of that claim is probably deferred to FIDO in many cases.) So it's possible that an assertion comes with three keys (primary, provider-scoped, device-bound). Some providers will likely skip one of the latter two even if they support supplemental public keys at all. That's a lot and the vast majority of RPs should never bother with any of this. But sign-ins to regulated sectors account for a lot of sign-ins because they make people sign-in so often. |
I understand the use-case now. I have some thoughts on solving this another way though. Maybe this doesn't belong as a discussion on this PR. We can move this discusison elsewhere. The central problem here is that "multi-device credentials do not have attestation because they're not device-bound". I think device-bound keys are compatible with moving between secure elements. HSMs and TPMs have supported this usecase for ages using key-wrapping. For example:
The key-wrapping and unwrapping is part of the sync-fabric between hooli devices and hooli servers. The RP doesn't have to care. It also has the added benefit that we cryptographically know that Hooli can not access the Passkeys in unencrypted form. Reason why I want to move this logic into the Passkey sync fabric is to keep implementation for RPs easy. If we drop the notion of "multi-device credentials aren't device-bound" I think this simplifies things for RPs. |
We continue to strongly recommend that regular sites use passkeys as is and don't bother with any supplemental key stuff. Given that, your suggestion to do imports into enclaves is a good one in general(*) for security. (Although with the caveat that, taking two major platforms as examples, Android Keystore doesn't support the import of asymmetric keys at all, and Apple still supports devices that don't have a secure enclave.) In your example, the provider is the one that seemingly blesses the import/export operation. The provider will need to authenticate the new device before instructing the old one to move keys into it and the details of that level of authentication are what needs to be included in the attestation. E.g. if the provider always does two-factor authentication, that's the sort of fact that sites may be able to use. Now, to motivate using multiple keys: We can't call keys that can be exported from a device "device bound", because they aren't! Storing them in the enclave protects against local attacks, which is great, but a site that wants device bound properties for compliance reasons isn't satisfied by any key that the provider can cause to be exported, even if it can only be moved to another hardware enclave. So, to meet any device-bound requirements we need a second key. And, if the provider is going to build a system that only moves keys between devices based on its attested two-factor authentication, then that precludes ever supporting moving passkeys between providers. But we don't want to preclude that because we don't want to exclude 3rd-party providers. And thus we split that key off and we end up with the supplementalPubKeys design. |
This extension is very similar the previous `devicePubKeys` extension. The difference is that `supplementalPubKey` allows for one _or two_ supplemental keys, and while supplemental keys can be device bound, they can also have "provider" scope, which is defined by their attestation statement.
From the call of 2023-09-06, there was a request to split this change into a) a change that removed devicePubKey and b) a change that added |
Are there requirements for an RP to know if the user in control of the credential has changed? I know that in native mobile apps its typically possible to get signals when enrolled biometrics changes, and in some cases apps require reauthentication (i.e. re-identity-proofing) when such a thing happens. If so, is it practical or possible for a provider to signal whether or not, from that provider's perspective, the user account (belonging to the passkey provider) exercising the credential has changed? The point here is, are we satisfying real RP policy requirements with the proposals in this extension. |
@sbweeden I wasn't thinking of signaling a change of control based on device biometrics. I think that explicitly moving the credential into another subscribers account should not carry with it the provider scope key. Or if it is carried arcoss we need a user scope where the supplemental key is unique to the combination of Account, RP, Provider. I think that a lot of RP will be forced via regulation to do some additional step up each login if they can't detect a change of subscriber account. |
index.bs
Outdated
|
||
Then, if this same user credential is copied to a different [=authenticator=] ("authenticator 2"), the [=[RP]=]'s first {{CredentialsContainer/get()|get()}} call on "authenticator 2" (that includes the `devicePubKey` extension) will produce an [=assertion=] including a signature by a <i>new</i> [=device-bound key=] ("dpk 2"). Note that such a [=multi-device credential=] can be exercised on "authenticator 2" without a {{CredentialsContainer/create()|create()}} having been performed on "authenticator 2". The [=[RP]=]'s subsequent {{CredentialsContainer/get()|get()}} calls on "authenticator 2", using the `devicePubKey` extension and the same user credential, yield further signatures by "dpk 2". | ||
When a [=[RP]=] uses the `supplementalPubKeys` extension with a {{CredentialsContainer/create()|create()}} call to create a new [=user credential=], a signature by one or more new supplemental keys may be returned along with the new supplemental public keys themselves. For the sake of example, assume that a single supplemental public key is returned, called “SPK1”. For as long as the [=user credential=] is exercised within the scope of the supplemental key, the [=[RP]=]'s subsequent {{CredentialsContainer/get()|get()}} operations for that credential will generate [=assertions=] including further signatures by “SPK1”. |
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.
Should this be "may generate [=assertions=]"? instead of will?
There is no guarantee that the authenticator will continue generating an SPK, is there? Or this is something we should explicitly define?
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 went with "will likely", how does that feel? I thought that "may" was too soft because we want to communicate that sites should generally expect that an SPK will persist, although you're correct that there will be mechanisms to reset them.
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.
WFM!
(Addressing Tim's comment.)
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.
LGTM
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.
Sorry for the delay!
Co-authored-by: Emil Lundberg <emil@yubico.com>
The extension name uses "PubKeys" but some of the structures said "PublicKeys". Be consistent.
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.
Thank you @agl for your patience!
SHA: f8163ea Reason: push, by agl Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
SHA: f8163ea Reason: push, by VoltrexKeyva Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
SHA: f8163ea Reason: push, by nsatragno Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This change removes the
devicePubKey
extension but adds the very similarsupplementalPubKeys
extension. The major difference between the two is that the latter allows for one or two supplemental keys, and while supplemental keys can be device bound, they can also have "provider" scope, which is defined by their attestation statement.Added by @timcappalli:
Here is a visual that (hopefully) helps to depict how this all comes together. This diagram assumes that the RP has requested both a provider SPK and device SPK, and that the passkey provider supports.
Preview | Diff