Odoo18-Base/addons/auth_passkey/_vendor/webauthn/helpers/structs.py
2025-01-06 10:57:38 +07:00

535 lines
18 KiB
Python

from enum import Enum
from dataclasses import dataclass, field
from typing import List, Literal, Optional, Union
from .cose import COSEAlgorithmIdentifier
################
#
# Fundamental data structures
#
################
class AuthenticatorTransport(str, Enum):
"""How an authenticator communicates to the client/browser.
Members:
`USB`: USB wired connection
`NFC`: Near Field Communication
`BLE`: Bluetooth Low Energy
`INTERNAL`: Direct connection (read: a platform authenticator)
`CABLE`: Cloud Assisted Bluetooth Low Energy
`HYBRID`: A combination of (often separate) data-transport and proximity mechanisms
https://www.w3.org/TR/webauthn-2/#enum-transport
"""
USB = "usb"
NFC = "nfc"
BLE = "ble"
INTERNAL = "internal"
CABLE = "cable"
HYBRID = "hybrid"
class AuthenticatorAttachment(str, Enum):
"""How an authenticator is connected to the client/browser.
Members:
`PLATFORM`: A non-removable authenticator, like TouchID or Windows Hello
`CROSS_PLATFORM`: A "roaming" authenticator, like a YubiKey
https://www.w3.org/TR/webauthn-2/#enumdef-authenticatorattachment
"""
PLATFORM = "platform"
CROSS_PLATFORM = "cross-platform"
class ResidentKeyRequirement(str, Enum):
"""The Relying Party's preference for the authenticator to create a dedicated "client-side" credential for it. Requiring an authenticator to store a dedicated credential should not be done lightly due to the limited storage capacity of some types of authenticators.
Members:
`DISCOURAGED`: The authenticator should not create a dedicated credential
`PREFERRED`: The authenticator can create and store a dedicated credential, but if it doesn't that's alright too
`REQUIRED`: The authenticator MUST create a dedicated credential. If it cannot, the RP is prepared for an error to occur.
https://www.w3.org/TR/webauthn-2/#enum-residentKeyRequirement
"""
DISCOURAGED = "discouraged"
PREFERRED = "preferred"
REQUIRED = "required"
class UserVerificationRequirement(str, Enum):
"""The degree to which the Relying Party wishes to verify a user's identity.
Members:
`REQUIRED`: User verification must occur
`PREFERRED`: User verification would be great, but if not that's okay too
`DISCOURAGED`: User verification should not occur, but it's okay if it does
https://www.w3.org/TR/webauthn-2/#enumdef-userverificationrequirement
"""
REQUIRED = "required"
PREFERRED = "preferred"
DISCOURAGED = "discouraged"
class AttestationConveyancePreference(str, Enum):
"""The Relying Party's interest in receiving an attestation statement.
Members:
`NONE`: The Relying Party isn't interested in receiving an attestation statement
`INDIRECT`: The Relying Party is interested in an attestation statement, but the client is free to generate it as it sees fit
`DIRECT`: The Relying Party is interested in an attestation statement generated directly by the authenticator
`ENTERPRISE`: The Relying Party is interested in a statement with identifying information. Typically used within organizations
https://www.w3.org/TR/webauthn-2/#enum-attestation-convey
"""
NONE = "none"
INDIRECT = "indirect"
DIRECT = "direct"
ENTERPRISE = "enterprise"
class PublicKeyCredentialType(str, Enum):
"""The type of credential that should be returned by an authenticator. There's but a single member because this is a specific subclass of a higher-level `CredentialType` that can be of other types.
Members:
`PUBLIC_KEY`: The literal string `"public-key"`
https://www.w3.org/TR/webauthn-2/#enumdef-publickeycredentialtype
"""
PUBLIC_KEY = "public-key"
class AttestationFormat(str, Enum):
"""The "syntax" of an attestation statement. Formats should be registered with the IANA and include documented signature verification steps.
Members:
`PACKED`
`TPM`
`ANDROID_KEY`
`ANDROID_SAFETYNET`
`FIDO_U2F`
`APPLE`
`NONE`
https://www.iana.org/assignments/webauthn/webauthn.xhtml
"""
PACKED = "packed"
TPM = "tpm"
ANDROID_KEY = "android-key"
ANDROID_SAFETYNET = "android-safetynet"
FIDO_U2F = "fido-u2f"
APPLE = "apple"
NONE = "none"
class ClientDataType(str, Enum):
"""Specific values included in authenticator registration and authentication responses to help avoid certain types of "signature confusion attacks".
Members:
`WEBAUTHN_CREATE`: The string "webauthn.create". Synonymous with `navigator.credentials.create()` in the browser
`WEBAUTHN_GET`: The string "webauthn.get". Synonymous with `navigator.credentials.get()` in the browser
https://www.w3.org/TR/webauthn-2/#dom-collectedclientdata-type
"""
WEBAUTHN_CREATE = "webauthn.create"
WEBAUTHN_GET = "webauthn.get"
class TokenBindingStatus(str, Enum):
"""
https://www.w3.org/TR/webauthn-2/#dom-tokenbinding-status
"""
PRESENT = "present"
SUPPORTED = "supported"
@dataclass
class TokenBinding:
"""
https://www.w3.org/TR/webauthn-2/#dictdef-tokenbinding
"""
status: TokenBindingStatus
id: Optional[str] = None
@dataclass
class PublicKeyCredentialRpEntity:
"""Information about the Relying Party.
Attributes:
`name`: A user-readable name for the Relying Party
(optional) `id`: A unique, constant value assigned to the Relying Party. Authenticators use this value to associate a credential with a particular Relying Party user
https://www.w3.org/TR/webauthn-2/#dictdef-publickeycredentialrpentity
"""
name: str
id: Optional[str] = None
@dataclass
class PublicKeyCredentialUserEntity:
"""Information about a user of a Relying Party.
Attributes:
`id`: An "opaque byte sequence" that uniquely identifies a user. Typically something like a UUID, but never user-identifying like an email address. Cannot exceed 64 bytes. These bytes should be stored internally alongside your normal user identifier and only used for WebAuthn.
`name`: A value which a user can see to determine which account this credential is associated with. A username or email address is fine here.
`display_name`: A user-friendly representation of a user, like a full name.
https://www.w3.org/TR/webauthn-2/#dictdef-publickeycredentialuserentity
"""
id: bytes
name: str
display_name: str
@dataclass
class PublicKeyCredentialParameters:
"""Information about a cryptographic algorithm that may be used when creating a credential.
Attributes:
`type`: The literal string `"public-key"`
`alg`: A numeric indicator of a particular algorithm
https://www.w3.org/TR/webauthn-2/#dictdef-publickeycredentialparameters
"""
type: Literal["public-key"]
alg: COSEAlgorithmIdentifier
@dataclass
class PublicKeyCredentialDescriptor:
"""Information about a generated credential.
Attributes:
`type`: The literal string `"public-key"`
`id`: The sequence of bytes representing the credential's ID
(optional) `transports`: The types of connections to the client/browser the authenticator supports
https://www.w3.org/TR/webauthn-2/#dictdef-publickeycredentialdescriptor
"""
id: bytes
type: Literal[PublicKeyCredentialType.PUBLIC_KEY] = PublicKeyCredentialType.PUBLIC_KEY
transports: Optional[List[AuthenticatorTransport]] = None
@dataclass
class AuthenticatorSelectionCriteria:
"""A Relying Party's requirements for the types of authenticators that may interact with the client/browser.
Attributes:
(optional) `authenticator_attachment`: How the authenticator can be connected to the client/browser
(optional) `resident_key`: Whether the authenticator should be able to store a credential on itself
(optional) `require_resident_key`: DEPRECATED, set a value for `resident_key` instead
(optional) `user_verification`: How the authenticator should be capable of determining user identity
https://www.w3.org/TR/webauthn-2/#dictdef-authenticatorselectioncriteria
"""
authenticator_attachment: Optional[AuthenticatorAttachment] = None
resident_key: Optional[ResidentKeyRequirement] = None
require_resident_key: Optional[bool] = False
user_verification: Optional[
UserVerificationRequirement
] = UserVerificationRequirement.PREFERRED
@dataclass
class CollectedClientData:
"""Decoded ClientDataJSON
Attributes:
`type`: Either `"webauthn.create"` or `"webauthn.get"`, for registration and authentication ceremonies respectively
`challenge`: The challenge passed to the authenticator within the options
`origin`: The base domain with protocol on which the registration or authentication ceremony took place (e.g. "https://foo.bar")
(optional) `cross_origin`: Whether or not the the registration or authentication ceremony took place on a different origin (think within an <iframe>)
(optional) `token_binding`: Information on the state of the Token Binding protocol
https://www.w3.org/TR/webauthn-2/#dictdef-collectedclientdata
"""
type: ClientDataType
challenge: bytes
origin: str
cross_origin: Optional[bool] = None
token_binding: Optional[TokenBinding] = None
################
#
# Registration
#
################
@dataclass
class PublicKeyCredentialCreationOptions:
"""Registration Options.
Attributes:
`rp`: Information about the Relying Party
`user`: Information about the user
`challenge`: A unique byte sequence to be returned by the authenticator. Helps prevent replay attacks
`pub_key_cred_params`: Cryptographic algorithms supported by the Relying Party when verifying signatures
(optional) `timeout`: How long the client/browser should give the user to interact with an authenticator
(optional) `exclude_credentials`: A list of credentials associated with the user to prevent them from re-enrolling one of them
(optional) `authenticator_selection`: Additional qualities about the authenticators the user can use to complete registration
(optional) `attestation`: The Relying Party's desire for a declaration of an authenticator's provenance via attestation statement
https://www.w3.org/TR/webauthn-2/#dictdef-publickeycredentialcreationoptions
"""
rp: PublicKeyCredentialRpEntity
user: PublicKeyCredentialUserEntity
challenge: bytes
pub_key_cred_params: List[PublicKeyCredentialParameters]
timeout: Optional[int] = None
exclude_credentials: Optional[List[PublicKeyCredentialDescriptor]] = None
authenticator_selection: Optional[AuthenticatorSelectionCriteria] = None
attestation: AttestationConveyancePreference = AttestationConveyancePreference.NONE
@dataclass
class AuthenticatorAttestationResponse:
"""The `response` property on a registration credential.
Attributes:
`client_data_json`: Information the authenticator collects about the client/browser it communicates with
`attestation_object`: Encoded information about an attestation
(optional) `transports`: The authenticator's supported methods of communication with a client/browser
https://www.w3.org/TR/webauthn-2/#authenticatorattestationresponse
"""
client_data_json: bytes
attestation_object: bytes
# Optional in L2, but becomes required in L3. Play it safe until L3 becomes Recommendation
transports: Optional[List[AuthenticatorTransport]] = None
@dataclass
class RegistrationCredential:
"""A registration-specific subclass of PublicKeyCredential returned from `navigator.credentials.create()`
Attributes:
`id`: The Base64URL-encoded representation of raw_id
`raw_id`: A byte sequence representing the credential's unique identifier
`response`: The authenticator's attesation data
`type`: The literal string `"public-key"`
https://www.w3.org/TR/webauthn-2/#publickeycredential
"""
id: str
raw_id: bytes
response: AuthenticatorAttestationResponse
authenticator_attachment: Optional[AuthenticatorAttachment] = None
type: Literal[PublicKeyCredentialType.PUBLIC_KEY] = PublicKeyCredentialType.PUBLIC_KEY
@dataclass
class AttestationStatement:
"""A collection of all possible fields that may exist in an attestation statement. Combinations of these fields are specific to a particular attestation format.
https://www.w3.org/TR/webauthn-2/#sctn-defined-attestation-formats
TODO: Decide if this is acceptable, or if we want to split this up into multiple
format-specific classes that define only the fields that are present for a given
attestation format.
"""
sig: Optional[bytes] = None
x5c: Optional[List[bytes]] = None
response: Optional[bytes] = None
alg: Optional[COSEAlgorithmIdentifier] = None
ver: Optional[str] = None
cert_info: Optional[bytes] = None
pub_area: Optional[bytes] = None
@dataclass
class AuthenticatorDataFlags:
"""Flags the authenticator will set about information contained within the `attestationObject.authData` property.
Attributes:
`up`: [U]ser was [P]resent
`uv`: [U]ser was [V]erified
`be`: [B]ackup [E]ligible
`bs`: [B]ackup [S]tate
`at`: [AT]tested credential is included
`ed`: [E]xtension [D]ata is included
https://www.w3.org/TR/webauthn-2/#flags
"""
up: bool
uv: bool
be: bool
bs: bool
at: bool
ed: bool
@dataclass
class AttestedCredentialData:
"""Information about a credential.
Attributes:
`aaguid`: A 128-bit identifier indicating the type and vendor of the authenticator
`credential_id`: The ID of the private/public key pair generated by the authenticator
`credential_public_key`: The public key generated by the authenticator
https://www.w3.org/TR/webauthn-2/#attested-credential-data
"""
aaguid: bytes
credential_id: bytes
credential_public_key: bytes
@dataclass
class AuthenticatorData:
"""Context the authenticator provides about itself and the environment in which the registration or authentication ceremony took place.
Attributes:
`rp_id_hash`: A SHA-256 hash of the website origin on which the registration or authentication ceremony took place
`flags`: Properties about the user and registration, where applicable
`sign_count`: The number of times the credential was used
(optional) `attested_credential_data`: Information about the credential created during a registration ceremony
(optional) `extensions`: CBOR-encoded extension data corresponding to extensions specified in the registration or authentication ceremony options
https://www.w3.org/TR/webauthn-2/#sctn-attestation
https://www.w3.org/TR/webauthn-2/#sctn-attested-credential-data
"""
rp_id_hash: bytes
flags: AuthenticatorDataFlags
sign_count: int
attested_credential_data: Optional[AttestedCredentialData] = None
extensions: Optional[bytes] = None
@dataclass
class AttestationObject:
"""Information about an attestation, including a statement and authenticator data.
Attributes:
`fmt`: The attestation statement's format
`att_stmt`: An attestation statement to be verified according to the format
`auth_data`: Contextual information provided by authenticator
https://www.w3.org/TR/webauthn-2/#sctn-attestation
"""
fmt: AttestationFormat
auth_data: AuthenticatorData
att_stmt: AttestationStatement = field(default_factory=AttestationStatement)
################
#
# Authentication
#
################
@dataclass
class PublicKeyCredentialRequestOptions:
"""Authentication Options.
Attributes:
`challenge`: A unique byte sequence to be returned by the authenticator. Helps prevent replay attacks
(optional) `timeout`: How long the client/browser should give the user to interact with an authenticator
(optional) `rp_id`: The unique, constant identifier assigned to the Relying Party
(optional) `allow_credentials`: A list of credentials associated with the user that they can use to complete the authentication
(optional) `user_verification`: How the authenticator should be capable of determining user identity
https://www.w3.org/TR/webauthn-2/#dictionary-assertion-options
"""
challenge: bytes
timeout: Optional[int] = None
rp_id: Optional[str] = None
allow_credentials: Optional[List[PublicKeyCredentialDescriptor]] = None
user_verification: Optional[
UserVerificationRequirement
] = UserVerificationRequirement.PREFERRED
@dataclass
class AuthenticatorAssertionResponse:
"""The `response` property on an authentication credential.
Attributes:
`client_data_json`: Information the authenticator collects about the client/browser it communicates with
`authenticator_data`: Contextual information provided by authenticator
`signature`: A byte sequence signed by the authenticator's private key, to be verified with a user's public key
(optional) `user_handle`: The user ID specified for the user during attestation
https://www.w3.org/TR/webauthn-2/#authenticatorassertionresponse
"""
client_data_json: bytes
authenticator_data: bytes
signature: bytes
user_handle: Optional[bytes] = None
@dataclass
class AuthenticationCredential:
"""An authentication-specific subclass of PublicKeyCredential. Returned from `navigator.credentials.get()`
Attributes:
`id`: The Base64URL-encoded representation of raw_id
`raw_id`: A byte sequence representing the credential's unique identifier
`response`: The authenticator's assertion data
`type`: The literal string `"public-key"`
https://www.w3.org/TR/webauthn-2/#publickeycredential
"""
id: str
raw_id: bytes
response: AuthenticatorAssertionResponse
authenticator_attachment: Optional[AuthenticatorAttachment] = None
type: Literal[PublicKeyCredentialType.PUBLIC_KEY] = PublicKeyCredentialType.PUBLIC_KEY
################
#
# Credential Backup State
#
################
class CredentialDeviceType(str, Enum):
"""A determination of the number of devices a credential can be used from
Members:
`SINGLE_DEVICE`: A credential that is bound to a single device
`MULTI_DEVICE`: A credential that can be used from multiple devices (e.g. passkeys)
https://w3c.github.io/webauthn/#sctn-credential-backup (L3 Draft)
"""
SINGLE_DEVICE = "single_device"
MULTI_DEVICE = "multi_device"