-
Notifications
You must be signed in to change notification settings - Fork 0
Authentication Flows
- Introduction
- Core Data Models
- Authentication Architecture
- Registration Flow
- Authentication Flow
- CTAP2 Command Integration
- Challenge-Response Mechanisms
- Error Handling and Timeouts
- Cross-Origin Authentication
- Test Suite Examples
- Troubleshooting Guide
- Conclusion
The PostQuantum WebAuthn Platform implements comprehensive authentication flows based on the WebAuthn standard, with enhanced support for post-quantum cryptographic algorithms. This system provides robust authentication mechanisms through both CTAP2 (Client to Authenticator Protocol Version 2) and WebAuthn APIs, enabling secure user authentication across various authenticator types including hardware security keys and platform authenticators.
The authentication system operates on a client-server model where the server generates challenges and validates responses, while the client interacts with authenticators through CTAP2 protocols. The platform supports both registration and authentication workflows, with extensive error handling and timeout management capabilities.
The PublicKeyCredentialCreationOptions class represents the configuration for credential registration, containing essential parameters for the registration process:
classDiagram
class PublicKeyCredentialCreationOptions {
+PublicKeyCredentialRpEntity rp
+PublicKeyCredentialUserEntity user
+bytes challenge
+Sequence~PublicKeyCredentialParameters~ pub_key_cred_params
+Optional~int~ timeout
+Optional~Sequence~PublicKeyCredentialDescriptor~~ exclude_credentials
+Optional~AuthenticatorSelectionCriteria~ authenticator_selection
+Optional~AttestationConveyancePreference~ attestation
+Optional~Mapping~ extensions
}
class PublicKeyCredentialRpEntity {
+str name
+Optional~str~ id
+id_hash() Optional~bytes~
}
class PublicKeyCredentialUserEntity {
+str name
+bytes id
+Optional~str~ display_name
}
class AuthenticatorSelectionCriteria {
+Optional~AuthenticatorAttachment~ authenticator_attachment
+Optional~ResidentKeyRequirement~ resident_key
+Optional~UserVerificationRequirement~ user_verification
+bool require_resident_key
}
PublicKeyCredentialCreationOptions --> PublicKeyCredentialRpEntity
PublicKeyCredentialCreationOptions --> PublicKeyCredentialUserEntity
PublicKeyCredentialCreationOptions --> AuthenticatorSelectionCriteria
Diagram sources
- fido2/webauthn.py
- fido2/webauthn.py
- fido2/webauthn.py
- fido2/webauthn.py
The PublicKeyCredentialRequestOptions class defines the parameters for authentication requests:
classDiagram
class PublicKeyCredentialRequestOptions {
+bytes challenge
+Optional~int~ timeout
+Optional~str~ rp_id
+Optional~Sequence~PublicKeyCredentialDescriptor~~ allow_credentials
+Optional~UserVerificationRequirement~ user_verification
+Optional~Mapping~ extensions
}
class PublicKeyCredentialDescriptor {
+PublicKeyCredentialType type
+bytes id
+Optional~Sequence~AuthenticatorTransport~~ transports
}
PublicKeyCredentialRequestOptions --> PublicKeyCredentialDescriptor
Diagram sources
- fido2/webauthn.py
- fido2/webauthn.py
The CollectedClientData class encapsulates the client data collected during authentication operations:
classDiagram
class CollectedClientData {
+str type
+bytes challenge
+str origin
+bool cross_origin
+create() CollectedClientData
+b64() str
+hash() bytes
}
class TYPE {
CREATE : "webauthn.create"
GET : "webauthn.get"
}
CollectedClientData --> TYPE
Diagram sources
- fido2/webauthn.py
- fido2/webauthn.py
The platform supports two primary response types for authentication operations:
classDiagram
class AuthenticatorAttestationResponse {
+CollectedClientData client_data
+AttestationObject attestation_object
+Optional~Mapping~ extension_results
}
class AuthenticatorAssertionResponse {
+CollectedClientData client_data
+AuthenticatorData authenticator_data
+bytes signature
+Optional~bytes~ user_handle
+Optional~bytes~ credential_id
+Optional~Mapping~ extension_results
}
class RegistrationResponse {
+bytes id
+AuthenticatorAttestationResponse response
+Optional~AuthenticatorAttachment~ authenticator_attachment
+Optional~AuthenticationExtensionsClientOutputs~ client_extension_results
+Optional~PublicKeyCredentialType~ type
}
class AuthenticationResponse {
+bytes id
+AuthenticatorAssertionResponse response
+Optional~AuthenticatorAttachment~ authenticator_attachment
+Optional~AuthenticationExtensionsClientOutputs~ client_extension_results
+Optional~PublicKeyCredentialType~ type
}
RegistrationResponse --> AuthenticatorAttestationResponse
AuthenticationResponse --> AuthenticatorAssertionResponse
Diagram sources
- fido2/webauthn.py
- fido2/webauthn.py
- fido2/webauthn.py
- fido2/webauthn.py
Section sources
- fido2/webauthn.py
- fido2/webauthn.py
- fido2/webauthn.py
- fido2/webauthn.py
The authentication system follows a layered architecture that separates concerns between client interaction, server validation, and authenticator communication:
graph TB
subgraph "Client Layer"
WebApp[Web Application]
WebAuthnAPI[WebAuthn API]
UserInteraction[User Interaction]
end
subgraph "Server Layer"
Server[Fido2Server]
RouteHandlers[Route Handlers]
ValidationLogic[Validation Logic]
end
subgraph "CTAP2 Layer"
Ctap2Client[CTAP2 Client]
AuthenticatorDevice[Authenticator Device]
HIDCommunication[HID Communication]
end
subgraph "Data Models"
CreationOptions[Creation Options]
RequestOptions[Request Options]
Responses[Response Objects]
end
WebApp --> WebAuthnAPI
WebAuthnAPI --> UserInteraction
UserInteraction --> Ctap2Client
Ctap2Client --> AuthenticatorDevice
AuthenticatorDevice --> HIDCommunication
RouteHandlers --> Server
Server --> ValidationLogic
ValidationLogic --> CreationOptions
ValidationLogic --> RequestOptions
ValidationLogic --> Responses
Diagram sources
- fido2/server.py
- fido2/client/init.py
- fido2/ctap2/base.py
The architecture ensures clear separation of responsibilities:
- Client Layer: Handles user interface and WebAuthn API interactions
- Server Layer: Manages authentication state and validates responses
- CTAP2 Layer: Communicates with authenticators through standardized protocols
- Data Models: Define the structure and validation rules for all authentication data
Section sources
- fido2/server.py
- fido2/client/init.py
- fido2/ctap2/base.py
The registration flow establishes new credentials with the authenticator and verifies their validity:
sequenceDiagram
participant Client as Web Client
participant Server as Fido2Server
participant Authenticator as Authenticator Device
participant Storage as Credential Storage
Client->>Server : register_begin(user, options)
Server->>Server : generate_challenge()
Server->>Server : create_creation_options()
Server-->>Client : (creation_options, state)
Client->>Authenticator : make_credential(options)
Authenticator->>Authenticator : generate_credential()
Authenticator-->>Client : registration_response
Client->>Server : register_complete(state, response)
Server->>Server : validate_client_data()
Server->>Server : validate_attestation()
Server->>Server : verify_signature()
Server->>Storage : store_credential()
Server-->>Client : authenticator_data
Diagram sources
- fido2/server.py
- fido2/server.py
- fido2/client/init.py
- Initialization: The server generates registration options and maintains state
- Challenge Generation: A cryptographically secure challenge is created
- Authenticator Interaction: The client communicates with the authenticator
- Response Validation: The server validates the attestation and signature
- Credential Storage: Validated credentials are stored securely
The server performs comprehensive validation during registration completion:
flowchart TD
Start([Registration Complete]) --> ValidateType["Validate Client Data Type"]
ValidateType --> TypeValid{"Type == CREATE?"}
TypeValid --> |No| TypeError["Raise ValueError"]
TypeValid --> |Yes| ValidateOrigin["Validate Origin"]
ValidateOrigin --> OriginValid{"Origin Valid?"}
OriginValid --> |No| OriginError["Raise ValueError"]
OriginValid --> |Yes| ValidateChallenge["Validate Challenge"]
ValidateChallenge --> ChallengeValid{"Challenge Matches?"}
ChallengeValid --> |No| ChallengeError["Raise ValueError"]
ChallengeValid --> |Yes| ValidateRP["Validate RP ID Hash"]
ValidateRP --> RPValid{"RP ID Hash Correct?"}
RPValid --> |No| RPError["Raise ValueError"]
RPValid --> |Yes| ValidateUserPresent["Validate User Present Flag"]
ValidateUserPresent --> UserPresent{"User Present?"}
UserPresent --> |No| UserError["Raise ValueError"]
UserPresent --> |Yes| ValidateUserVerification["Validate User Verification"]
ValidateUserVerification --> UVRequired{"UV Required?"}
UVRequired --> |Yes| UVValid{"UV Flag Set?"}
UVValid --> |No| UVError["Raise ValueError"]
UVValid --> |Yes| ValidateAttestation["Validate Attestation"]
UVRequired --> |No| StoreCredential["Store Credential"]
ValidateAttestation --> AttestationValid{"Attestation Valid?"}
AttestationValid --> |No| AttestationError["Raise ValueError"]
AttestationValid --> |Yes| StoreCredential
StoreCredential --> Success([Success])
TypeError --> End([End])
OriginError --> End
ChallengeError --> End
RPError --> End
UserError --> End
UVError --> End
AttestationError --> End
Success --> End
Diagram sources
- fido2/server.py
Section sources
- fido2/server.py
- fido2/server.py
- fido2/client/init.py
The authentication flow verifies existing credentials through challenge-response mechanisms:
sequenceDiagram
participant Client as Web Client
participant Server as Fido2Server
participant Authenticator as Authenticator Device
participant Storage as Credential Storage
Client->>Server : authenticate_begin(credentials, options)
Server->>Server : generate_challenge()
Server->>Server : create_request_options()
Server-->>Client : (request_options, state)
Client->>Authenticator : get_assertion(options)
Authenticator->>Authenticator : verify_user()
Authenticator->>Authenticator : select_credential()
Authenticator-->>Client : assertion_response
Client->>Server : authenticate_complete(state, credentials, response)
Server->>Server : validate_client_data()
Server->>Server : validate_authenticator_data()
Server->>Server : verify_signature()
Server-->>Client : authenticated_credential
Diagram sources
- fido2/server.py
- fido2/server.py
- fido2/client/init.py
The authentication process involves multiple validation steps to ensure security:
flowchart TD
Start([Authentication Complete]) --> ValidateType["Validate Client Data Type"]
ValidateType --> TypeValid{"Type == GET?"}
TypeValid --> |No| TypeError["Raise ValueError"]
TypeValid --> |Yes| ValidateOrigin["Validate Origin"]
ValidateOrigin --> OriginValid{"Origin Valid?"}
OriginValid --> |No| OriginError["Raise ValueError"]
OriginValid --> |Yes| ValidateChallenge["Validate Challenge"]
ValidateChallenge --> ChallengeValid{"Challenge Matches?"}
ChallengeValid --> |No| ChallengeError["Raise ValueError"]
ChallengeValid --> |Yes| ValidateRP["Validate RP ID Hash"]
ValidateRP --> RPValid{"RP ID Hash Correct?"}
RPValid --> |No| RPError["Raise ValueError"]
RPValid --> |Yes| ValidateUserPresent["Validate User Present Flag"]
ValidateUserPresent --> UserPresent{"User Present?"}
UserPresent --> |No| UserError["Raise ValueError"]
UserPresent --> |Yes| ValidateUserVerification["Validate User Verification"]
ValidateUserVerification --> UVRequired{"UV Required?"}
UVRequired --> |Yes| UVValid{"UV Flag Set?"}
UVValid --> |No| UVError["Raise ValueError"]
UVValid --> |Yes| FindCredential["Find Credential"]
UVRequired --> |No| FindCredential
FindCredential --> CredentialFound{"Credential Found?"}
CredentialFound --> |No| CredentialError["Raise ValueError"]
CredentialFound --> |Yes| VerifySignature["Verify Signature"]
VerifySignature --> SignatureValid{"Signature Valid?"}
SignatureValid --> |No| SignatureError["Raise ValueError"]
SignatureValid --> |Yes| UpdateCounter["Update Counter"]
UpdateCounter --> Success([Success])
TypeError --> End([End])
OriginError --> End
ChallengeError --> End
RPError --> End
UserError --> End
UVError --> End
CredentialError --> End
SignatureError --> End
Success --> End
Diagram sources
- fido2/server.py
Section sources
- fido2/server.py
- fido2/server.py
- fido2/client/init.py
The platform integrates closely with CTAP2 commands to facilitate authenticator communication:
The make_credential CTAP2 command initiates the registration process:
sequenceDiagram
participant Client as Web Client
participant CTAP2 as CTAP2 Protocol
participant Authenticator as Authenticator Device
Client->>CTAP2 : make_credential(client_data_hash, rp, user, key_params)
CTAP2->>Authenticator : SEND_MAKE_CREDENTIAL
Authenticator->>Authenticator : validate_parameters()
Authenticator->>Authenticator : generate_credential()
Authenticator->>Authenticator : user_verification()
Authenticator-->>CTAP2 : attestation_response
CTAP2-->>Client : AttestationResponse
Diagram sources
- fido2/ctap2/base.py
The get_assertion CTAP2 command handles authentication requests:
sequenceDiagram
participant Client as Web Client
participant CTAP2 as CTAP2 Protocol
participant Authenticator as Authenticator Device
Client->>CTAP2 : get_assertion(rp_id, client_data_hash, allow_list)
CTAP2->>Authenticator : SEND_GET_ASSERTION
Authenticator->>Authenticator : validate_parameters()
Authenticator->>Authenticator : select_credential()
Authenticator->>Authenticator : user_verification()
Authenticator->>Authenticator : generate_signature()
Authenticator-->>CTAP2 : assertion_response
CTAP2-->>Client : AssertionResponse
Diagram sources
- fido2/ctap2/base.py
The platform defines specific CTAP2 command identifiers:
| Command | Value | Purpose |
|---|---|---|
| MAKE_CREDENTIAL | 0x01 | Register new credential |
| GET_ASSERTION | 0x02 | Authenticate with existing credential |
| GET_INFO | 0x04 | Retrieve authenticator capabilities |
| CLIENT_PIN | 0x06 | Manage PIN operations |
| RESET | 0x07 | Reset authenticator state |
Section sources
- fido2/ctap2/base.py
- fido2/ctap2/base.py
- fido2/ctap2/base.py
Challenges serve as unique, unpredictable values that prevent replay attacks:
flowchart TD
Start([Generate Challenge]) --> CheckCustom{"Custom Challenge Provided?"}
CheckCustom --> |Yes| ValidateLength["Validate Length >= 16 bytes"]
CheckCustom --> |No| GenerateRandom["Generate Random 32 bytes"]
ValidateLength --> LengthValid{"Length >= 16?"}
LengthValid --> |No| LengthError["Raise ValueError"]
LengthValid --> |Yes| UseProvided["Use Provided Challenge"]
GenerateRandom --> UseGenerated["Use Generated Challenge"]
UseProvided --> Success([Success])
UseGenerated --> Success
LengthError --> End([End])
Diagram sources
- fido2/server.py
During authentication, challenges must match exactly to prevent tampering:
flowchart TD
Start([Validate Challenge]) --> ExtractExpected["Extract Expected Challenge"]
ExtractExpected --> DecodeExpected["Decode Base64URL"]
DecodeExpected --> Compare["Compare with Response Challenge"]
Compare --> Match{"Challenges Match?"}
Match --> |No| MismatchError["Raise ValueError"]
Match --> |Yes| Success([Success])
MismatchError --> End([End])
Diagram sources
- fido2/server.py
Resource Provider (RP) ID validation ensures requests come from authorized origins:
flowchart TD
Start([Validate RP ID]) --> ExtractRPID["Extract RP ID from Options"]
ExtractRPID --> CheckNull{"RP ID Null?"}
CheckNull --> |Yes| DeriveFromOrigin["Derive from Origin Host"]
CheckNull --> |No| UseProvided["Use Provided RP ID"]
DeriveFromOrigin --> ValidateOrigin["Validate Origin Format"]
UseProvided --> ValidateRP["Validate RP ID Format"]
ValidateOrigin --> OriginValid{"Origin Valid?"}
OriginValid --> |No| OriginError["Raise ValueError"]
OriginValid --> |Yes| Success([Success])
ValidateRP --> RPValid{"RP ID Valid?"}
RPValid --> |No| RPErrror["Raise ValueError"]
RPValid --> |Yes| Success
OriginError --> End([End])
RPErrror --> End
Diagram sources
- fido2/client/init.py
Section sources
- fido2/server.py
- fido2/server.py
- fido2/client/init.py
The platform implements comprehensive timeout handling for various operations:
flowchart TD
Start([Operation Start]) --> SetTimer["Set Operation Timer"]
SetTimer --> PollLoop["Poll Loop"]
PollLoop --> CheckEvent["Check Event Flag"]
CheckEvent --> EventSet{"Event Set?"}
EventSet --> |Yes| TimeoutError["Raise Timeout Error"]
EventSet --> |No| AttemptOperation["Attempt Operation"]
AttemptOperation --> OperationSuccess{"Operation Successful?"}
OperationSuccess --> |Yes| Success([Success])
OperationSuccess --> |No| CheckRetry{"Can Retry?"}
CheckRetry --> |Yes| WaitDelay["Wait Poll Delay"]
CheckRetry --> |No| OperationError["Raise Operation Error"]
WaitDelay --> PollLoop
TimeoutError --> End([End])
OperationError --> End
Diagram sources
- fido2/client/init.py
Authenticators communicate status updates through keep-alive messages:
sequenceDiagram
participant Client as Web Client
participant HID as HID Layer
participant Authenticator as Authenticator
Client->>HID : Send Keep-Alive Request
HID->>Authenticator : CTAPHID_KEEPALIVE
Authenticator-->>HID : STATUS_UPNEEDED
HID->>Client : on_keepalive(STATUS_UPNEEDED)
Client->>Client : prompt_user_presence()
Note over Client,Authenticator : User interaction required
HID->>Authenticator : Continue Operation
Authenticator-->>HID : STATUS_SUCCESS
HID->>Client : on_keepalive(STATUS_SUCCESS)
Client->>Client : Operation Continuing
Diagram sources
- fido2/hid/init.py
The platform categorizes errors into specific types for appropriate handling:
| Error Category | Description | Handling Strategy |
|---|---|---|
| OTHER_ERROR | General unexpected errors | Log and retry |
| BAD_REQUEST | Invalid request parameters | Validate input |
| CONFIGURATION_UNSUPPORTED | Unsupported features | Feature detection |
| DEVICE_INELIGIBLE | Authenticator unsuitable | Alternative authenticator |
| TIMEOUT | Operation exceeded time limit | User notification |
Section sources
- fido2/client/init.py
- fido2/hid/init.py
- fido2/client/init.py
Cross-origin authentication prevention is critical for security:
flowchart TD
Start([Validate Origin]) --> ParseOrigin["Parse Request Origin"]
ParseOrigin --> ExtractHost["Extract Hostname"]
ExtractHost --> CheckHTTPS{"Scheme == HTTPS?"}
CheckHTTPS --> |No| CheckLocalhost{"Hostname == localhost?"}
CheckHTTPS --> |Yes| ValidateRP["Validate RP ID"]
CheckLocalhost --> |No| InvalidOrigin["Invalid Origin"]
CheckLocalhost --> |Yes| ValidateRP
ValidateRP --> RPValid{"RP ID Valid for Origin?"}
RPValid --> |No| InvalidOrigin
RPValid --> |Yes| ValidOrigin([Valid Origin])
InvalidOrigin --> OriginError["Raise ValueError"]
OriginError --> End([End])
ValidOrigin --> Success([Success])
Diagram sources
- fido2/client/init.py
The system detects and prevents cross-origin requests:
flowchart TD
Start([Check Cross-Origin]) --> GetOrigin["Get Request Origin"]
GetOrigin --> ParseOrigin["Parse Origin URL"]
ParseOrigin --> CompareRP["Compare with RP ID"]
CompareRP --> SameOrigin{"Same Origin?"}
SameOrigin --> |Yes| AllowRequest["Allow Request"]
SameOrigin --> |No| CheckCrossOrigin{"Cross-Origin Allowed?"}
CheckCrossOrigin --> |Yes| AllowRequest
CheckCrossOrigin --> |No| DenyRequest["Deny Request"]
AllowRequest --> Success([Success])
DenyRequest --> CrossOriginError["Raise Cross-Origin Error"]
CrossOriginError --> End([End])
Diagram sources
- server/server/attestation.py
Section sources
- fido2/client/init.py
- server/server/attestation.py
The test suite demonstrates successful registration flows:
sequenceDiagram
participant Test as Test Case
participant Server as Fido2Server
participant Client as WebAuthn Client
Test->>Server : register_begin(user, credentials)
Server-->>Test : (options, state)
Test->>Client : make_credential(options)
Client-->>Test : registration_response
Test->>Server : register_complete(state, response)
Server-->>Test : authenticator_data
Test->>Test : Assert Success
Diagram sources
- tests/test_webauthn.py
Authentication test cases demonstrate proper validation:
sequenceDiagram
participant Test as Test Case
participant Server as Fido2Server
participant Client as WebAuthn Client
Test->>Server : authenticate_begin(credentials)
Server-->>Test : (options, state)
Test->>Client : get_assertion(options)
Client-->>Test : assertion_response
Test->>Server : authenticate_complete(state, credentials, response)
Server-->>Test : authenticated_credential
Test->>Test : Assert Success
Diagram sources
- tests/test_webauthn.py
The test suite covers various error conditions:
| Test Scenario | Expected Behavior | Validation Method |
|---|---|---|
| Invalid Challenge | ValueError | Challenge mismatch check |
| Invalid Origin | ValueError | Origin validation |
| Wrong RP ID Hash | ValueError | RP ID hash comparison |
| Missing User Present Flag | ValueError | User presence verification |
| Invalid Signature | ValueError | Signature verification |
Section sources
- tests/test_webauthn.py
- tests/test_ctap2.py
Issue: Registration fails with "Device Ineligible" error Cause: Authenticator doesn't support required features Solution: Check authenticator capabilities and adjust registration options
Issue: Challenge validation fails Cause: Challenge encoding/decoding issues Solution: Ensure proper base64url encoding and decoding
Issue: Assertion signature verification fails Cause: Incorrect public key or corrupted data Solution: Verify credential storage and key derivation
Issue: User verification required but not performed Cause: Authenticator doesn't support UV or user declined Solution: Adjust user verification requirements
Issue: Operations timeout frequently Cause: Slow authenticator response or network latency Solution: Increase timeout values and implement retry logic
Issue: Cross-origin requests blocked Cause: Origin validation failure Solution: Ensure RP ID matches origin or configure cross-origin allowance
The platform provides comprehensive logging for troubleshooting:
flowchart TD
Start([Enable Debug Logging]) --> SetLogLevel["Set Logger Level to DEBUG"]
SetLogLevel --> MonitorOperations["Monitor Operation Logs"]
MonitorOperations --> CheckErrors["Check Error Messages"]
CheckErrors --> AnalyzePatterns["Analyze Error Patterns"]
AnalyzePatterns --> IdentifyRootCause["Identify Root Cause"]
IdentifyRootCause --> ApplyFix["Apply Fix"]
ApplyFix --> VerifySolution["Verify Solution"]
VerifySolution --> Success([Success])
Section sources
- fido2/server.py
- fido2/client/init.py
The PostQuantum WebAuthn Platform provides a comprehensive authentication framework that combines WebAuthn standards with CTAP2 protocols. The system offers robust security through challenge-response mechanisms, comprehensive error handling, and support for various authenticator types.
Key strengths of the implementation include:
- Security: Multi-layered validation including challenge-response, RP ID verification, and signature checking
- Flexibility: Support for various authenticator types and configuration options
- Reliability: Comprehensive error handling and timeout management
- Extensibility: Modular design allowing for future enhancements
The platform successfully addresses the core requirements of modern authentication systems while maintaining compatibility with existing WebAuthn standards and providing enhanced security through post-quantum cryptographic algorithms.
Future enhancements could include expanded extension support, improved user experience through biometric authentication, and enhanced monitoring capabilities for production deployments.