- User opens a website with username and password field.
- autofill is not enabled
- user right-clicks to open menu on the username field, browser offers "fill password..." (click 1)
- browser calls frontend "GetCredential" method, with "type: password" and origin specified
- user is presented with UI: Do you want to sign into on ? enter fingerprint/device PIN to select credentials
- user enters credentials. (interaction 2)
- user is shown a list of credentials, ordered by most relevant based on the origin provided (interaction 3)
- user scrolls and selects the relevant credential
- backend sends ID back to frontend, which pulls the corresponding credential and sends back to client
- browser receives credentials, fills in username and password.
sequenceDiagram
actor U as User
participant B as Backend
participant F as Frontend
participant C as Client
U->>C: Clicks "Fill Password.."
C->>F: GetCredential([{type: password, origin}])
F->>B: GetCredential(credRequests[])
B->>F: GetAuthToken()
F-->>B: return authToken
B->>U: Prompts for PIN/fingerprint
alt fingerprint
U->>B: Swipes fingerprint
F->>B: NotifyFingerprint({ cred })
else pin
U->>B: Enters PIN
end
B->>F: ValidateDeviceCredential(authToken, cred)
F-->>B: returns `session`
B->>F: GetCredentials(session)
F-->>B: returns `credentialList`
B->>U: Show credentials
U->>B: Select credential
B->>F: SelectCredential(session, id)
F-->>B: returns `completionToken`
destroy B
B->>F: CompleteTransaction(session, completionToken)
F->>C: returns `passwordCredential`
C->>U: Logs user in
- Can we send extra form fields (for sites that ask for other fields besides username and password)?
- User opens a website with passkey.
- autofill is not enabled
- user clicks passkey button (interaction 1)
- browser calls frontend "GetCredential" method, with "type: publicKey", origin, and assertion options specified
- user is presented with UI: Do you want to sign into on ? enter fingerprint/device PIN to select credentials
- user enters credentials. (interaction 2)
- backend sends credentials to frontend to verify
- user is shown a list of credentials, filtered by assertion options and ordered by most relevant based on the origin provided
- invalid passkeys should not be shown? (because they won't work at all, and for phishing protection), but irrelevant passwords can be shown
- This may cause issues for some origins if they're not registered properly.
- Technically, it's the responsibilty of the RP to validate the origin. If the origin is wrong, that's part of the authenticator data, and the RP can reject it. So even if a third-party phisher initiated the assertion from another site, the attacker couldn't use the credentials, because the RP wouldn't recognize the origin. So it might be OK to allow other passkeys to sign the assertion.
- user scrolls and selects the relevant credential
- backend sends ID back to frontend, which pulls the corresponding credential and sends back to client
- browser receives credentials,
sequenceDiagram
actor U as User
participant B as Backend
participant F as Frontend
participant C as Client
U->>C: Clicks "Clicks Create Passkey.."
C->>F: GetCredential([{type: publicKey, origin, publicKey: {...options}}])
F->>B: GetCredential(credRequest)
B->>F: GetAuthToken()
F-->>B: return authToken
B->>U: Prompts for PIN/fingerprint
alt fingerprint
U->>B: Swipes fingerprint
F->>B: NotifyFingerprint({ cred })
else pin
U->>B: Enters PIN
end
B->>F: ValidateDeviceCredential(authToken, cred)
F-->>B: returns `session`
B->>F: GetCredentials(session)
F-->>B: returns `credentialList`
B->>U: Show credentials
U->>B: Select credential
B->>F: SelectCredential(session, id)
F->>F: SignAssertion()
F-->>B: returns `completionToken`
destroy B
B->>F: CompleteTransaction(session, completionToken)
F->>C: returns `publicKeyCredential`
C->>U: Logs user in
- User opens a website with username and password field.
- autofill is not enabled
- user right-clicks to open menu on the username field, browser offers "fill password..." (click 1)
- browser calls frontend "GetCredential" method, with "type: password" and origin specified
- user is presented with UI: Do you want to sign into on ? enter fingerprint/device PIN to select credentials
- user enters credentials. (interaction 2)
- Backend sends credentials to frontend to validate
- this authentication must be tied to this session must be validated, and time-limtied
- user is shown a list of credentials, ordered by most relevant based on the origin provided (interaction 3)
- user scrolls, doesn't find credential, select "create credential"
- User types in username and password
- Backend sends create credential to frontend with origin, receives ID back from
- backend sends ID back to frontend, which pulls the corresponding credential and sends back to client
- browser receives credentials, fills in username and password.
sequenceDiagram
actor U as User
participant B as Backend
participant F as Frontend
participant C as Client
U->>C: Clicks "Clicks Create Passkey.."
C->>F: GetCredential([{type: password, origin}])
F->>B: GetCredential(credRequest)
B->>F: GetAuthToken()
F-->>B: return authToken
B->>U: Prompts for PIN/fingerprint
alt fingerprint
U->>B: Swipes fingerprint
F->>B: NotifyFingerprint({ cred })
else pin
U->>B: Enters PIN
end
B->>F: ValidateDeviceCredential(authToken, cred)
F-->>B: returns `session`
B->>F: GetCredentials(session)
F-->>B: returns `credentialList`
B->>U: Show credentials
U->>B: Create new credential
B->>F: CreateCredential({type: password, origin, username, password})
F-->>B: returns newCredentialId
B->>F: SelectCredential(session, id)
F-->>B: returns `completionToken`
destroy B
B->>F: CompleteTransaction(session, completionToken)
F->>C: returns `publicKeyCredential`
C->>U: Logs user in
- not supported by WebAuthn yet
- User opens a website with username and password field.
- autofill is not enabled
- browser calls frontend "GetCredential" method, with "type: publicKey" and origin specified
- User clicks passkey button (click 1)
- user is presented with UI: Do you want to sign into on ? enter fingerprint/device PIN to select credentials. (Or "use a different device (e.g., USB or mobile device)")
- user clicks on other options (click 2)
- User clicks on USB (click 3 )
- this could be done in a different order. If the frontend detects that a FIDO USB device has been connected, then it should signal the backend that it has seen that device. Then the frontend can show the USB device option immediately.
- Backend shows instructions while waiting for USB
- User plugs in USB (interaction 4)
- frontend signals backend that USB was plugged in
- backend shows instructions to press button
- user pushes button (interaction 5)
- frontend signals backend that USB was pressed and sends ref to assertion
- Backend completes assertion by sending ref back to frontend and closes the window
- frontend receives assertion ref
- frontend sends webauthn result to client
sequenceDiagram
actor U as User
participant M as Machine
participant B as Backend
participant F as Frontend
participant C as Client
U->>C: Clicks "Clicks Create Passkey.."
C->>F: GetCredential([{type: publicKey, origin, publicKey: {...options}}])
F->>B: GetCredential(credRequest)
B->>F: GetAuthToken()
F-->>B: return authToken
B->>U: Prompts for PIN/fingerprint
U->>B: Clicks "other credentials"
B->>F: CancelAuth(authToken)
U->>B: Selects "USB security key"
B->>F: StartDeviceDiscovery([{type: usb}])
F-->>M: Polls for FIDO USB devices
U->>M: Plugs in USB
M->>F: Notifies about USB device
F->>M: CTAPHID_* messages, ask for assertion
F-->>M: Poll for assertion
F->>B: NotifyDiscoveredDevice({type: usbPluggedIn, ...})
B->>U: Shows instruction "Activate security key"
B->>F: BlinkDevice(device)
F->>M: CTAPHID_WINK
U->>M: Activates security key
destroy M
M-->>F: Notifies FIDO activation/assertion
F-->>B: returns `completionToken`
destroy B
B->>F: CompleteTransaction(session, completionToken)
F->>C: returns `publicKeyCredential`
C->>U: Logs user in
- User opens a website with username and password field.
- autofill is not enabled
- browser calls frontend "GetCredential" method, with "type: publicKey" and origin specified
- User clicks passkey button (click 1)
- user is presented with UI: Do you want to sign into on ? enter fingerprint/device PIN to select credentials. (Or "use a different device (e.g., USB or mobile device)")
- user clicks on other options (click 2)
- Backend shows known mobile devices for state-assisted transactions
- User clicks on a different mobile device (click 3)
- Backend notifies frontend about hybrid-transport-start
- frontend generates QR code data, begins BLE scan
- sends back QR code data
- User scans QR code in USB (interaction 3)
- User selects "yes, sign in" (interaction 4)
- Mobile device begins BLE advert
- Frontend detects BLE advert, signals backend
- Backend shows that phone has been detected and shows "connecting to your device"
- Frontend connects to caBLE server, gets assertion from device
- Frontend
- frontend signals backend that assertion was received, sends completion handle
- Backend tells user that the transaction is done, sends handle back to the Frontend
- frontend receives assertion ref
- frontend sends webauthn result to client
sequenceDiagram
actor U as User
participant B as Backend
participant F as Frontend
participant M as Machine
participant D as Device
participant C as Client
U->>C: Clicks "Clicks Create Passkey.."
C->>F: GetCredential([{type: publicKey, origin, publicKey: {...options}}])
F->>B: GetCredential(credRequest)
B->>F: GetAuthToken()
F-->>B: return authToken
B->>U: Prompts for PIN/fingerprint
U->>B: Clicks "other credentials"
B->>F: CancelAuth(authToken)
U->>B: Selects "Other device"
B->>F: StartDeviceDiscovery([{type: ctap-hybrid}])
F-->>M: Polls for BLE devices
F-->>B: returns `qr_data`
B->>U: Displays QR code
U->>D: Scans QR code
D->>M: Sends BLE Advert
destroy M
M->>F: Notifies about BLE advert
F->>B: NotifyDiscoveredDevice({type: hybridConnected, ...})
B->>U: Shows "Connecting to your device"
F->>D: Send assertion options
U->>D: Consents to use passkey
destroy D
D->>F: Sends assertion data
F-->>B: returns `completionToken`
destroy B
B->>F: CompleteTransaction(session, completionToken)
F->>C: returns `publicKeyCredential`
C->>U: Logs user in
- User opens a website with username and password field.
- autofill is not enabled
- User clicks passkey button (click 1)
- browser calls frontend "GetCredential" method, with "type: password" and origin specified
- user is presented with UI: Do you want to sign into on ? enter fingerprint/device PIN to select credentials. (Or "use a different device (e.g., USB or mobile device)")
- The frontend has to tell the backend about available providers at some point
- user clicks on other options (click 2)
- Backend shows known mobile devices for state-assisted transactions
- User clicks on a different provider (click 3)
- Backend shows "waiting on credentials from {provider}",
- Backend signals frontend about provider request
- Frontend notifies provider about credential request
- Provider shows UI to select credential
- User selects credential (click 4+)
- Provider sends password/assertion data to frontend
- frontend sends assertion notification to backend with completion handle
- frontend signals backend that assertion was received, sends completion handle
- Backend tells user that the transaction is done, sends handle back to the Frontend
- frontend receives assertion ref
- frontend sends webauthn result to client
sequenceDiagram
actor U as User
participant P as Provider
participant B as Backend
participant F as Frontend
participant C as Client
U->>C: Clicks "Clicks Create Passkey.."
C->>F: GetCredential([{type: password, origin}])
F->>B: GetCredential(credRequest)
B->>F: GetAuthToken()
F-->>B: return authToken
B->>U: Prompts for PIN/fingerprint
U->>B: Clicks "other credentials"
B->>F: CancelAuth(authToken)
U->>B: Selects "Your Password Provider"
B->>F: LaunchProvider(id)
F->>P: Sends launch request
P->>U: Provider shows credentials
U->>P: User chooses credentials
destroy P
P->>F: SendPassword
F-->>B: returns `completionToken`
destroy B
B->>F: CompleteTransaction(session, completionToken)
F->>C: returns `password`
C->>U: Logs user in
- User opens a website with username and password field.
- autofill is not enabled
- User clicks passkey button (click 1)
- browser calls frontend "GetCredential" method, with "type: publicKey" and origin specified
- Frontend calls providers to fill credentials, within timeout period
- Provider A sends matching credentials to Frontend
- user is presented with UI: Do you want to sign into on ? enter fingerprint/device PIN to select credentials. (Or "use a different device (e.g., USB or mobile device)")
- The frontend has to tell the backend about available providers at some point
- user puts in device credentials (interaction 2)
- Backend shows known credentials, including ones from providers that sent in creds on time
- User selects provider credential (click 4+)
- Backend tells frontend about selection
- Frontend tells provider about selection
- Provider sends credential data to Frontend
- frontend sends assertion notification to backend with completion handle
- frontend signals backend that assertion was received, sends completion handle
- Backend tells user that the transaction is done, sends handle back to the Frontend
- frontend receives assertion ref
- frontend sends webauthn result to client
sequenceDiagram
actor U as User
participant P as Provider
participant B as Backend
participant F as Frontend
participant C as Client
U->>C: Clicks "Clicks Create Passkey.."
C->>F: GetCredential([{type: password, origin}])
F->>P: SearchCredentials(credRequest)
P-->>F: return matching credentials
F->>B: GetCredential(credRequest)
B->>F: GetAuthToken()
F-->>B: return authToken
B->>U: Prompts for PIN/fingerprint
alt fingerprint
U->>B: Swipes fingerprint
F->>B: NotifyFingerprint({ cred })
else pin
U->>B: Enters PIN
end
B->>F: ValidateDeviceCredential(authToken, cred)
F-->>B: returns `session`
B->>F: GetCredentials(session)
F-->>B: returns `credentialList`, including provider credentials
B->>U: Show credentials
U->>B: Select credential from Provider
B->>+F: SelectCredential(session, id)
F->>P: GetCredential(credRequest, id)
P-->>P: SignAssertion()
destroy P
P-->>F: return assertion
F-->>-B: returns `completionToken`
destroy B
B->>F: CompleteTransaction(session, completionToken)
F->>C: returns `assertion`
C->>U: Logs user in