odoo/odoo · error · InvalidRegistrationResponse

Unsupported credential public key alg "{decoded_credential_p

Error message

Unsupported credential public key alg "{decoded_credential_public_key.alg}", expected one of: {supported_pub_key_algs}

What it means

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.

Source

Thrown at addons/auth_passkey/_vendor/webauthn/registration/verify_registration_response.py:190

        raise InvalidRegistrationResponse("Authenticator did not provide attested credential data")

    attested_credential_data = auth_data.attested_credential_data

    if not attested_credential_data.credential_id:
        raise InvalidRegistrationResponse("Authenticator did not provide a credential ID")

    if not attested_credential_data.credential_public_key:
        raise InvalidRegistrationResponse("Authenticator did not provide a credential public key")

    if not attested_credential_data.aaguid:
        raise InvalidRegistrationResponse("Authenticator did not provide an AAGUID")

    decoded_credential_public_key = decode_credential_public_key(
        attested_credential_data.credential_public_key
    )

    if decoded_credential_public_key.alg not in supported_pub_key_algs:
        raise InvalidRegistrationResponse(
            f'Unsupported credential public key alg "{decoded_credential_public_key.alg}", expected one of: {supported_pub_key_algs}'
        )

    # Prepare a list of possible root certificates for certificate chain validation
    pem_root_certs_bytes: List[bytes] = []
    if pem_root_certs_bytes_by_fmt:
        custom_certs = pem_root_certs_bytes_by_fmt.get(attestation_object.fmt)
        if custom_certs:
            # Load any provided custom root certs
            pem_root_certs_bytes.extend(custom_certs)

    if attestation_object.fmt == AttestationFormat.NONE:
        # A "none" attestation should not contain _anything_ in its attestation statement
        any_att_stmt_fields_set = any(
            [field is not None for field in asdict(attestation_object.att_stmt).values()]
        )

        if any_att_stmt_fields_set:

View on GitHub (pinned to 1e661df964)

Solutions

  1. Align both sides: advertise the same algorithms in pubKeyCredCredParams when generating registration options and in supported_pub_key_algs when verifying
  2. If your users have RSA-only authenticators, extend supported_pub_key_algs with RS256 (-257)
  3. Never add RS1 (-35, SHA-1) unless strictly required for legacy devices; prefer Ed25519 (-8) or ES256 (-7)

Example fix

# before
verified = verify_registration_response(
    credential=credential, expected_challenge=challenge,
    expected_origin=origin, expected_rp_id=rp_id,
    require_user_verification=True,
)

# after - keep options and verification in sync
from py_webauthn import COSEAlgorithmIdentifier
algs = [COSEAlgorithmIdentifier.ECDSASHA256, COSEAlgorithmIdentifier.RSASSAPKCS1v1_5SHA256]
options = generate_registration_options(
    rp_id=rp_id, rp_name=name, user_id=uid,
    pub_key_cred_params=[{'type': 'public-key', 'alg': a.value} for a in algs],
)
verified = verify_registration_response(
    credential=credential, expected_challenge=challenge,
    expected_origin=origin, expected_rp_id=rp_id,
    require_user_verification=True,
    supported_pub_key_algs=algs,
)
Defensive patterns

Strategy: validation

Validate before calling

from py_webauthn import COSEAlgorithmIdentifier
SUPPORTED = [COSEAlgorithmIdentifier.ECDSASHA256, COSEAlgorithmIdentifier.RSASSAPKCS1v1_5SHA256]
# Use the same list for generate_registration_options(pub_key_cred_params=...) and
# verify_registration_response(supported_pub_key_algs=SUPPORTED).

Type guard

const SUPPORTED_ALGS = new Set([-7, -257]);
// after decoding the COSE key client-side (or in a shared lib):
function isSupportedAlg(alg: unknown): alg is number {
  return typeof alg === 'number' && SUPPORTED_ALGS.has(alg);
}

Try / catch

try:
    verify_registration_response(..., supported_pub_key_algs=SUPPORTED)
except InvalidRegistrationResponse as e:
    if 'Unsupported credential public key alg' in str(e):
        return user_error('Your device uses a key type this service does not support')
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of odoo/odoo@1e661df964 (2026-08-15). Data as JSON: /api/errors/43eea84c4068dd5d. Report an issue: GitHub.