You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用SimpleWebAuthnBrowser结合Yii2框架实现WebAuthn时,认证阶段出现NotAllowedError错误的排查求助

SimpleWebAuthnBrowser结合Yii2框架实现WebAuthn时,认证阶段出现NotAllowedError错误的排查求助

我现在想用PHP的Yii2框架配合SimpleWebAuthnBrowser库实现WebAuthn功能,注册设备的流程已经跑通了,凭证也成功保存到数据库里,但到了认证验证环节,却遇到了一个错误:

NotAllowedError: The operation either timed out or was not allowed. See: https://www.w3.org/TR/webauthn-2/#sctn-privacy-considerations-client.

下面是我的相关代码和配置,麻烦大家帮忙看看问题出在哪?

注册阶段的挑战响应(PHP代码)

注册时后端返回的挑战配置是这样的:

return [
    'challenge' => $challengeBase64,
    'rp' => [
        'name' => Yii::$app->name,
        'id' => 'x-y-z.ngrok-free.app',
    ],
    'user' => [
        'id'          => $userId,
        'name'        => $displayName,
        'displayName' => $displayName,
    ],
    'pubKeyCredParams' => [
        ['type' => 'public-key', 'alg' => -7],
        ['type' => 'public-key', 'alg' => -257],
    ],
    'authenticatorSelection' => [
        'authenticatorAttachment' => 'cross-platform',
        'requireResidentKey' => false,
        'userVerification' => 'discouraged',
    ],
    'timeout' => 60000,
    'attestation' => 'direct',
    'transports' => ['usb'],
];

注册页面的前端代码(JS)

前端注册逻辑如下,目前运行正常:

try {
    // 获取挑战
    let challengeResponse = await fetch('/user/challenge');

    if (!challengeResponse.ok) {
        throw new Error('Failed to get challenge from server');
    }
    let challengeData = await challengeResponse.json();

    const attResp = await SimpleWebAuthnBrowser.startRegistration(challengeData);

    // 获取凭证数据
    let credential_id = attResp.rawId;
    let public_key = attResp.response.publicKey;
    let sign_count = 0;
    let transports = attResp.response.transports ? attResp.response.transports : [];
    let attestation_type = attResp.type;
    // ...后续保存逻辑
} catch (error) {
    // 错误处理
}

注册成功后,数据库里的凭证信息如下:
Saved Credential

认证阶段的问题代码

前端认证逻辑(JS)

认证时调用startAuthentication就会抛出开头的错误:

try {
    const response = await fetch('/user/another-challenge', { method: 'GET' });
    const options = await response.json();

    const assertion = await SimpleWebAuthnBrowser.startAuthentication(options); // 此处抛出NotAllowedError

    // ...后续验证逻辑
} catch (error) {
    console.error(error);
}

后端认证挑战响应(PHP代码)

后端返回的认证挑战配置是这样的:

return [
    'challenge' => Base64Url::encode($challenge),
    'rp' => [
        'name' => Yii::$app->name,
        'id' => 'x-y-z.ngrok-free.app',
    ],
    'user' => [
        'id' => Base64Url::encode($user->id),
        'name' => $user->username,
        'displayName' => $user->username,
    ],
    'allowCredentials' => [
        [
            'type' => 'public-key',
            'id' => Base64Url::encode($credential->credential_id),
            'transports' => ['usb'],
        ]
    ],
    'timeout' => 60000,
    'userVerification' => 'discouraged',
];

我怀疑是不是注册阶段的挑战响应有什么问题导致后续认证失败?有没有大佬能给点排查方向或者建议?谢谢大家!

备注:内容来源于stack exchange,提问作者Prabowo Murti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 18:34:51