# FIDO2
This solution includes components that implement FIDO2 authentication, i.e. sign with Face, Touch, YubiKey, etc.:
- FIDO2 credentials are stored in an **Amazon DynamoDB** table, so that a virtual unlimited amount of credentials can be stored, with details such as: friendly name ("My iPhone"), last used date, how many times used, etc.
- **Amazon HTTP API** supports creating, updating and deleting FIDO2 credentials. This HTTP API is protected by a JWT authorizer, meaning you must already be signed-in via different means (e.g, using Magic Link) to register a FIDO2 credential.
- **AWS Lambda functions** that implement the Amazon Cognito Custom Authentication flow, reading FIDO2 credential public keys from the DynamoDB table.
- Front End library functions, to work with this Custom Auth flow––can be used in Web, React, React Native.
- Pre-built sample React component to add/update/delete authenticators.
## FIDO2 Browser Support
FIDO2 (/WebAuthn) is still a relatively new standard and not all browsers support it to the fullest yet. Currently, we recommend to use Chrome, as it best supports FIDO2 in our experience.
Here are some issues in other browsers that we know of today:
- Mobile Safari on older iOS versions (seen on 16.0, no longer on 16.3) allows users to create multiple passkeys for the same username-website combination, whereby the older passkey is implicitly replaced by the newest. This can lead to confusion, as it's not possible for the FIDO2 backend of the solution here, to detect that the newer credential should replace the old one (as iOS did itself). Thus it simply stores the new credential without removing older ones. The user will then still see the older credentials in the credential list.
- Firefox support for WebAuthn is limited (seen on 102.8, said to be fixed in 109), e.g. doesn't support security keys with PIN, nor MacOS Touch.
## AWS Architecture

## Registering new FIDO2 Authenticators
First you must sign-in with a magic link (or any other means). After that you can register a FIDO2 capable authenticator to log in with next time.
```mermaid
sequenceDiagram
autonumber
actor User
participant BJS as Browser JavaScript
participant BLS as Browser Storage
participant BC as Browser WebAuthn core
participant API as HTTP API+Lambda
participant DB as DynamoDB
BJS->>BLS: Query user FIDO2 enabled
Activate BJS
Activate BLS
BLS->>BJS: null
Deactivate BLS
BJS->>User: Show enable-face-or-touch-login dialog
Deactivate BJS
Activate User
User->>BJS: Click "Enable Face or Touch sign-in"
Activate BJS
BJS->>API: Start create-credential, include JWT (ID token)
Activate API
API->>API: Verify JWT
API->>API: Generate random challenge
API->>DB: Store challenge
Activate DB
DB->>API: OK
Deactivate DB
API->>BJS: Challenge and other FIDO2 options
Deactivate API
BJS->>BC: navigator.credentials.create()
Activate BC
BC->>User: Show register-authenticator native dialog
User->>BC: Execute gesture (e.g. touch, face)
BC->>BJS: FIDO2 public key response
Deactivate BC
BJS->>User: Show input-friendly-authenticator-name custom dialog
User->>BJS: Friendly name
BJS->>API: Complete create-credential
Activate API
API->>DB: Lookup challenge
Activate DB
DB->>API: Challenge
Deactivate DB
API->>API: Verify authenticator response
API->>DB: Store credential
Activate DB
DB->>API: OK
Deactivate DB
API->>BJS: Credential metadata
Deactivate API
BJS->>BLS: Store FIDO2 enabled user
Activate BLS
BLS->>BJS: OK
Deactivate BLS
BJS->>User: "Authenticator activated successfully"
Deactivate BJS
Deactivate User
```
## Sign-in
```mermaid
sequenceDiagram
autonumber
actor User
participant BJS as Browser JavaScript
participant BLS as Browser Storage
participant BC as Browser WebAuthn core
participant C as Cognito
participant DA as DefineAuth
participant CA as CreateAuthChallenge
participant VA as VerifyAnswer
participant DB as DynamoDB
User->>BJS: Open web app
Activate User
Activate BJS
BJS->>BLS: Query FIDO2 enabled users
Activate BLS
BLS->>BJS: FIDO2 Users
Deactivate BLS
BJS->>User: Show username sign-in buttons
Deactivate BJS
User->>BJS: Click "Sign-in as with face or touch"
Activate BJS
BJS->>C: InitiateAuth
Activate C
C->>DA: Invoke
Activate DA
DA->>C: Custom challenge
Deactivate DA
C->>CA: Invoke
Activate CA
CA->>CA: Generate challenge
CA->>DB: Query credential IDs
Activate DB
DB->>CA: Credential IDs
Deactivate DB
CA->>C: FIDO2 challenge, credential IDs, options
Deactivate CA
C->>BJS: FIDO2 challenge, credential IDs, options
Deactivate C
BJS->>BC: navigator.credentials.get()
Activate BC
BC->>User: Show sign-use-authenticator native dialog
User->>BC: Execute gesture (e.g. touch, face)
BC->>BJS: FIDO2 signature response
Deactivate BC
BJS->>C: RespondToAuthChallenge
Activate C
C->>VA: Invoke
Activate VA
VA->>VA: Verify client data
VA->>DB: Get credential public key
Activate DB
DB->>VA: Credential public key
Deactivate DB
VA->>VA: Verify signature
VA->>C: Answer correct: true
Deactivate VA
C->>DA: Invoke
Activate DA
DA->>C: Succeed Auth
Deactivate DA
C->> BJS: JWTs
Deactivate C
BJS->>BLS: Store JWTs
Activate BLS
BLS->>BJS: OK
Deactivate BLS
BJS->>User: "You are signed in"
Deactivate BJS
Deactivate User
```