使用SimpleWebAuthn、Node.js 和react.js 使用密钥验证身份验证时出现“无数据”错误

问题描述 投票:0回答:1

我正在尝试使用我的密码登录我的react.js应用程序,使用node.js作为后端,并使用MongoDB作为我的数据库。

以下是我的后端代码:

const registerWebAuthentication = async (req, res) => {
  console.log("------------------------>>>>",req.body);
  try {
    const user = await User.findOne({ username: req.body.username });
    console.log("from registerWebauthentication: " + req.body);
    if (!user) {
      return res.status(404).json({ message: 'User not found' });
    }
    const challengePayload = await SimpleWebAuthnServer.generateRegistrationOptions({
      rpID: 'localhost',
      rpName: 'nobil localhost',
      userName: user.username,
    })
    await User.findOneAndUpdate(
      { username: req.body.username },
      { challenge: challengePayload.challenge }
    );
    return res.json({ options: challengePayload })
  } catch (e) {
    console.log(e);
  }
}

const verifyRegistration = async(req, res) => {
  console.log("inside verify registrations ===========>>", req.body);
  try {
    const user = await User.findOne({ username: req.body.username });
    if (!user) {
      return res.status(404).json({ message: 'User not found' });
    }

    const expectedChallenge = user.challenge;

    const verification = await SimpleWebAuthnServer.verifyRegistrationResponse({
      response: req.body.cred,
      expectedChallenge: expectedChallenge,
      expectedOrigin: 'http://localhost:3000', 
      expectedRPID: 'localhost',
    });

    if (!verification.verified) return res.json({ error: 'could not verify' });
    await User.findOneAndUpdate(
      { username: req.body.username },
      { passkey: verification.registrationInfo }
    );

    return res.json({ verified: true });
  } catch (e) {
    console.log(e);
  }
}

以下是我在后端登录的代码:

const registerWebAuthentication = async (req, res) => {
  console.log("------------------------>>>>",req.body);
  try {
    const user = await User.findOne({ username: req.body.username });
    console.log("from registerWebauthentication: " + req.body);
    if (!user) {
      return res.status(404).json({ message: 'User not found' });
    }
    const challengePayload = await SimpleWebAuthnServer.generateRegistrationOptions({
      rpID: 'localhost',
      rpName: 'nobil localhost',
      userName: user.username,
    })
    await User.findOneAndUpdate(
      { username: req.body.username },
      { challenge: challengePayload.challenge }
    );
    return res.json({ options: challengePayload })
  } catch (e) {
    console.log(e);
  }
}

const verifyRegistration = async(req, res) => {
  console.log("inside verify registrations ===========>>", req.body);
  try {
    const user = await User.findOne({ username: req.body.username });
    if (!user) {
      return res.status(404).json({ message: 'User not found' });
    }

    const expectedChallenge = user.challenge;

    const verification = await SimpleWebAuthnServer.verifyRegistrationResponse({
      response: req.body.cred,
      expectedChallenge: expectedChallenge,
      expectedOrigin: 'http://localhost:3000', 
      expectedRPID: 'localhost',
    });

    if (!verification.verified) return res.json({ error: 'could not verify' });
    await User.findOneAndUpdate(
      { username: req.body.username },
      { passkey: verification.registrationInfo }
    );

    return res.json({ verified: true });
  } catch (e) {
    console.log(e);
  }
}

我正在按如下方式处理前端组件中的日志记录:

const handlePasskeyLogin = async () => {
      try {
        const res = await Axios.post('/generate-login-options', { username: passkeyUsername });
        console.log("following are the options: ", res);
        const options = res.data.options;
        const loginRes = await startAuthentication(options);
        console.log(loginRes);
        const verifyRes = await Axios.post('/verify-passkey-login', { username: passkeyUsername, cred: loginRes });
        console.log("response from server on verification of passkey login: ", verifyRes);
  
        // if (verifyRes.data.verified) {
        //   setAdvertiser(verifyRes.data.user);
        //   setSigned(true);
        //   navigate("/home");
        // } else {
        //   notify("Passkey login failed");
        // }

        if(verifyRes.data.role === "display-provider"){
          localStorage.setItem("Dp_token", verifyRes?.data?.token);
        }
        else{
          localStorage.setItem("token", verifyRes?.data?.token);
        }
        
        console.log(verifyRes?.data?.token);
  
        sessionStorage.setItem("role", verifyRes.data);
        localStorage.setItem("Admin", verifyRes.data.DpUsername);
         console.error("An error occurred:", verifyRes?.status);
        if (verifyRes?.status === 200) {
          setAdvertiser(verifyRes.data)
          sessionStorage.setItem("role", verifyRes.data.role);
          setSigned(true);
          navigate("/home");
  
        } 
       
         else if (verifyRes?.status === 202) {
          setSigned(true);
          
          if (verifyRes.data.role === "Manager") {
            sessionStorage.setItem("role", verifyRes.data.role);
            navigate("/Manager");
          } else if (verifyRes.data.role === "Publisher") {
            sessionStorage.setItem("role", verifyRes.data.role);
            navigate("/Publisher");
          } else if (verifyRes.data.role === "Viewer") {
            sessionStorage.setItem("role", verifyRes.data.role);
            navigate("/Viewer");
          }
        }
      } catch (error) {
        console.error(error);
        notify("Error during passkey login");
      }
    };

每当我尝试登录时,我的后端服务器中都会显示以下错误:

Error: No data
    at Object.decodePartialCBOR (C:\Users\nobil\OneDrive\Desktop\MOLOG\EveridoorBackend2.0\node_modules\@levischuck\tiny-cbor\script\cbor\cbor.js:355:15)
    at Object.decodeFirst (C:\Users\nobil\OneDrive\Desktop\MOLOG\EveridoorBackend2.0\node_modules\@simplewebauthn\server\script\helpers\iso\isoCBOR.js:25:40)
    at decodeCredentialPublicKey (C:\Users\nobil\OneDrive\Desktop\MOLOG\EveridoorBackend2.0\node_modules\@simplewebauthn\server\script\helpers\decodeCredentialPublicKey.js:6:84)
    at verifySignature (C:\Users\nobil\OneDrive\Desktop\MOLOG\EveridoorBackend2.0\node_modules\@simplewebauthn\server\script\helpers\verifySignature.js:20:86)
    at Object.verifyAuthenticationResponse (C:\Users\nobil\OneDrive\Desktop\MOLOG\EveridoorBackend2.0\node_modules\@simplewebauthn\server\script\authentication\verifyAuthenticationResponse.js:157:66)
    at async verifyLogin (C:\Users\nobil\OneDrive\Desktop\MOLOG\EveridoorBackend2.0\controllers\user.controller.js:147:26)
POST /verify-passkey-login 500 52.308 ms - 35

我正在根据此处的官方文档进行所有操作:https://simplewebauthn.dev/docs/packages/server

请帮助我

javascript reactjs node.js mongodb passkey
1个回答
0
投票

我认为实施过程中存在一些问题。

  1. 您的登录应调用

    SimpleWebAuthnServer.generateAuthenticationOptions
    而不是
    SimpleWebAuthnServer.generateRegistrationOptions
    (https://simplewebauthn.dev/docs/advanced/passkeys#generateauthenticationoptions)。与验证部分相同。它应该是
    ~.verifyAuthenticationResponse
    而不是
    ~.verifyRegistrationResponse
    (https://simplewebauthn.dev/docs/advanced/passkeys#verifyauthenticationresponse)。

  2. 您需要将您为用户保存的 passKeys 详细信息传递给

    verifyAuthenticationResponse
    ,因此它应该如下所示:

    const verification = await SimpleWebAuthnServer.verifyRegistrationResponse({
    response: req.body.cred,
    expectedChallenge: expectedChallenge,
    expectedOrigin: 'http://localhost:3000', 
    expectedRPID: 'localhost',
    authenticator: {
      credentialID: user.passkey.credentialID,
      credentialPublicKey: user.passkey.credentialPublicKey.buffer,
      counter: passkey.counter,
      transports: passkey.transports
    }
  });
  1. 注意它是
    user.passkey.credentialPublicKey.buffer
    (缓冲区)而不是
    user.passkey.credentialPublicKey
    。 MongoDB 会将 PublicKey 值 (Unit8Array) 保存为 Binary,因此您需要将其转换回来。
© www.soinside.com 2019 - 2024. All rights reserved.