{"record":{"id":"43eea84c4068dd5d","repo":"odoo/odoo","slug":"unsupported-credential-public-key-alg-decoded-cr","errorCode":null,"errorMessage":"Unsupported credential public key alg \"{decoded_credential_public_key.alg}\", expected one of: {supported_pub_key_algs}","messagePattern":"Unsupported credential public key alg \"(.+?)\", expected one of: (.+?)","errorType":"validation","errorClass":"InvalidRegistrationResponse","httpStatus":null,"severity":"error","filePath":"addons/auth_passkey/_vendor/webauthn/registration/verify_registration_response.py","lineNumber":190,"sourceCode":"        raise InvalidRegistrationResponse(\"Authenticator did not provide attested credential data\")\n\n    attested_credential_data = auth_data.attested_credential_data\n\n    if not attested_credential_data.credential_id:\n        raise InvalidRegistrationResponse(\"Authenticator did not provide a credential ID\")\n\n    if not attested_credential_data.credential_public_key:\n        raise InvalidRegistrationResponse(\"Authenticator did not provide a credential public key\")\n\n    if not attested_credential_data.aaguid:\n        raise InvalidRegistrationResponse(\"Authenticator did not provide an AAGUID\")\n\n    decoded_credential_public_key = decode_credential_public_key(\n        attested_credential_data.credential_public_key\n    )\n\n    if decoded_credential_public_key.alg not in supported_pub_key_algs:\n        raise InvalidRegistrationResponse(\n            f'Unsupported credential public key alg \"{decoded_credential_public_key.alg}\", expected one of: {supported_pub_key_algs}'\n        )\n\n    # Prepare a list of possible root certificates for certificate chain validation\n    pem_root_certs_bytes: List[bytes] = []\n    if pem_root_certs_bytes_by_fmt:\n        custom_certs = pem_root_certs_bytes_by_fmt.get(attestation_object.fmt)\n        if custom_certs:\n            # Load any provided custom root certs\n            pem_root_certs_bytes.extend(custom_certs)\n\n    if attestation_object.fmt == AttestationFormat.NONE:\n        # A \"none\" attestation should not contain _anything_ in its attestation statement\n        any_att_stmt_fields_set = any(\n            [field is not None for field in asdict(attestation_object.att_stmt).values()]\n        )\n\n        if any_att_stmt_fields_set:","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/odoo/odoo/blob/1e661df964b1b264c9cef3ab28430d4785be3fda/addons/auth_passkey/_vendor/webauthn/registration/verify_registration_response.py#L172-L208","documentation":"Raised when the decoded COSE credential public key's algorithm (alg) is not in supported_pub_key_algs (default ES256=-7, RS256=-257, and in newer versions Ed25519=-8). The RP only stores keys it can verify later, so unsupported algorithms are rejected at registration time.","triggerScenarios":"A credential created with an algorithm the RP did not list in publicKey.parameters ('alg') in the creation options, e.g. ES384, RS1 (SHA-1 RSA), or PS256; a custom supported_pub_key_algs argument that omits the algorithm the browser chose.","commonSituations":"Mistmatch between the algorithms advertised in the registration options (publicKey.pubKeyCredParams) and the supported_pub_key_algs passed to verification; older Windows Hello or Android devices emitting RS1; explicitly restricting to ES256 while the user's device only supports RSA.","solutions":["Align both sides: advertise the same algorithms in pubKeyCredCredParams when generating registration options and in supported_pub_key_algs when verifying","If your users have RSA-only authenticators, extend supported_pub_key_algs with RS256 (-257)","Never add RS1 (-35, SHA-1) unless strictly required for legacy devices; prefer Ed25519 (-8) or ES256 (-7)"],"exampleFix":"# before\nverified = verify_registration_response(\n    credential=credential, expected_challenge=challenge,\n    expected_origin=origin, expected_rp_id=rp_id,\n    require_user_verification=True,\n)\n\n# after - keep options and verification in sync\nfrom py_webauthn import COSEAlgorithmIdentifier\nalgs = [COSEAlgorithmIdentifier.ECDSASHA256, COSEAlgorithmIdentifier.RSASSAPKCS1v1_5SHA256]\noptions = generate_registration_options(\n    rp_id=rp_id, rp_name=name, user_id=uid,\n    pub_key_cred_params=[{'type': 'public-key', 'alg': a.value} for a in algs],\n)\nverified = verify_registration_response(\n    credential=credential, expected_challenge=challenge,\n    expected_origin=origin, expected_rp_id=rp_id,\n    require_user_verification=True,\n    supported_pub_key_algs=algs,\n)\n","handlingStrategy":"validation","validationCode":"from py_webauthn import COSEAlgorithmIdentifier\nSUPPORTED = [COSEAlgorithmIdentifier.ECDSASHA256, COSEAlgorithmIdentifier.RSASSAPKCS1v1_5SHA256]\n# Use the same list for generate_registration_options(pub_key_cred_params=...) and\n# verify_registration_response(supported_pub_key_algs=SUPPORTED).","typeGuard":"const SUPPORTED_ALGS = new Set([-7, -257]);\n// after decoding the COSE key client-side (or in a shared lib):\nfunction isSupportedAlg(alg: unknown): alg is number {\n  return typeof alg === 'number' && SUPPORTED_ALGS.has(alg);\n}","tryCatchPattern":"try:\n    verify_registration_response(..., supported_pub_key_algs=SUPPORTED)\nexcept InvalidRegistrationResponse as e:\n    if 'Unsupported credential public key alg' in str(e):\n        return user_error('Your device uses a key type this service does not support')\n    raise","preventionTips":["Keep one shared constant for algorithms and use it in both options generation and verification","Advertise at least ES256 (-7) and RS256 (-257) so virtually all devices can enroll","Add a regression test that enrolls with each advertised alg"],"tags":["webauthn","authentication","passkey","cose","algorithm"],"backgroundTag":null,"analyzedSha":"1e661df964b1b264c9cef3ab28430d4785be3fda","analyzedAt":"2026-08-15T05:22:16.142Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}