mozilla / authenticator-rs

Rust library to interact with Security Keys, used by Firefox
https://crates.io/crates/authenticator
Mozilla Public License 2.0
273 stars 70 forks source link

Use StatusUpdate for signature selection #310

Closed jschanck closed 11 months ago

jschanck commented 11 months ago

When an authenticatorGetAssertion response includes more than one credential, we present the user with a list of the associated usernames and ask them to select one. Their choice determines which credential is returned to the RP. Firefox currently handles this "in the WebAuthn layer" as follows:

1) authenticator-rs receives a authenticatorGetAssertion response and repackages it into a GetAssertionResult that it returns to authrs_bridge. 2) authrs_bridge returns (an XPCOM wrapper around) this GetAssertionResult to WebAuthnController. 2) WebAuthnController reads user names out of the Assertions and shows a selection prompt. 3) the prompt calls back to WebAuthnController with the selection result. 4) WebAuthnController constructs a WebAuthnGetAssertionResult IPC message based on the selected Assertion and returns it to the client process.

We're planning to refactor the WebAuthnControllerauthrs_bridge boundary so that WebAuthnController will be solely responsible for IPC. That means all of the prompt generation logic needs to move into authrs_bridge.

This PR changes GetAssertionResult from

pub struct GetAssertionResult {
    pub assertions: Vec<Assertion>,
    pub extensions: AuthenticationExtensionsClientOutputs,
}

to

pub struct GetAssertionResult {
    pub assertion: Assertion,
    pub extensions: AuthenticationExtensionsClientOutputs,
}

And it adds

enum StatusUpdate {
    [...]
    SelectResultNotice(Sender<Option<usize>>, Vec<PublicKeyCredentialUserEntity>)
}

The new flow will be 1) authenticator-rs receives an authenticatorGetAssertion response and sends a SelectResultNotice to the authrs_bridge's status update handler. 2) authrs_bridge shows a selection prompt. 3) the prompt calls back to authrs_bridge with the selection result, which authrs_bridge forwards to authenticator-rs. 4) authenticator-rs repackages the appropriate response into a GetAssertionResult which it returns to authrs_bridge. 5) authrs_bridge returns the (wrapped) result to WebAuthnController.

In addition to facilitating our IPC-focused refactor of WebAuthnController, this also unblocks some work on get() extensions.