next.js AWS Cognito -注册流程-本地存储缺少ID令牌,请进行身份验证

mfpqipee  于 2023-06-05  发布在  其他
关注(0)|答案(1)|浏览(324)

bounty还有4天到期。回答此问题可获得+200声望奖励。DevOverflow希望引起更多注意这个问题:需要一个解决方案来在注册时将用户添加到cognito用户池组

我有一个非常简单的注册表(电子邮件和密码),工作正常,直到我尝试添加新用户到一个用户池组。这是我的代码;我正在使用Next.js和Typescript以及AWS(Amplify / Cognito)。

import { Auth, Hub } from 'aws-amplify';
import { useRouter } from 'next/router';
import { useState } from 'react';

const SignupForm = () => {
  const router = useRouter();
  const [formState, setFormState] = useState({
    email: '',
    password: '', // Initialize with an empty string
  });

  const handleChange = e => {
    const { name, value } = e.target;

    setFormState(prevState => ({
      ...prevState,
      [name]: value,
    }));
  };

  const handleSubmit = async e => {
    e.preventDefault();

    try {
      const { email, password } = formState;

      const signUpResponse = await Auth.signUp({
        username: email,
        password,
        attributes: {
          email,
        },
      });

      const user = signUpResponse.user;

      await Auth.updateUserAttributes(user, {
        'cognito:groups': ['members'],
      });

      console.log('User added to the group:', userGroupResponse);

      router.push('/registered');
    } catch (error) {
      console.error('Error registering user:', error);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label htmlFor="email">
          Email
        </label>
        <input
          type="email"
          id="email"
          name="email"
          value={formState.email}
          onChange={handleChange}
          required
        />
      </div>
      <div>
        <label htmlFor="password">
          Password
        </label>
        <input
          type="password"
          id="password"
          name="password"
          value={formState.password}
          onChange={handleChange}
          required
        />
      </div>
      <button type="submit">
        Register
      </button>
    </form>
  );
};

export default SignupForm;

请注意,它是

const user = signUpResponse.user;

      await Auth.updateUserAttributes(user, {
        'cognito:groups': ['members'],
      });

我可以注解掉,没有问题,但我想将其添加到用户池组“members”。错误显示在页面上,如下所示:

Unhandled Runtime Error
Error: Local storage is missing an ID Token, Please authenticate

Source
src/components/signup/SignupForm.tsx (37:12) @ Auth

  35 | const user = signUpResponse.user;
  36 | 
> 37 | await Auth.updateUserAttributes(user, {
     |      ^
  38 |   'cognito:groups': ['members'],
  39 | });

在控制台中:

CognitoUser.js:1148 Uncaught (in promise) Error: Local storage is missing an ID Token, Please authenticate
    at CognitoUser.getSession (CognitoUser.js:1148:1)
    at eval (Auth.js:1652:1)
    at new Promise (<anonymous>)
    at AuthClass.eval (Auth.js:1651:1)
    at step (tslib.es6.js:100:1)
    at Object.eval [as next] (tslib.es6.js:81:46)
    at eval (tslib.es6.js:74:1)
    at new Promise (<anonymous>)
    at __awaiter (tslib.es6.js:70:1)
    at AuthClass._userSession (Auth.js:1637:25)
    at AuthClass.userSession (Auth.js:1708:1)
    at eval (Auth.js:1254:1)
    at new Promise (<anonymous>)
    at AuthClass.updateUserAttributes (Auth.js:1253:1)
    at handleSubmit (SignupForm.tsx:37:13)

我已经检查了我的cognito设置,并启用了完整的读/写权限。用户池组“members”存在。并且用户是在没有用户池组代码的情况下创建的,所以我相信所有aws-exports等都是正确的。如果找不到解决方案,我可能不得不添加一个组作为属性,尽管这并不理想。
我相信可以通过设置一个lambda函数在注册后将用户添加到组中,但如果这是推荐的方法,我会感到惊讶,因为它似乎更复杂。

qgelzfjb

qgelzfjb1#

如果我正确理解“Amazon Cognito / Signing up and confirming user accounts”,用户注册后,通常会由管理员手动确认,或通过电子邮件或短信代码自动确认,具体取决于您的配置。

确认后,用户需要登录才能开始会话。登录后,他们的ID令牌可用,并且可以更新用户属性。
但在您的示例中,Auth.updateUserAttributes()正在尝试访问用户的当前身份验证会话,该会话在注册后立即不存在。用户需要在会话可用之前登录,并且可以更新用户属性。
因此,出现类似Local storage is missing an ID Token, Please authenticate的错误
注册用户时,他们不会自动登录。
因此,如果您想在注册后立即更新用户属性,您有两个选项:
1.注册后立即登录用户:(至少用于测试它是否工作)这将启动会话并使ID令牌可用。
例如,handleSubmit函数是:

const handleSubmit = async e => {
  e.preventDefault();

  try {
    const { email, password } = formState;

    const signUpResponse = await Auth.signUp({
      username: email,
      password,
      attributes: {
        email,
      },
    });

    // Sign the user in after sign up
    const signInResponse = await Auth.signIn(email, password);

    const user = signInResponse.user;

    await Auth.updateUserAttributes(user, {
      'cognito:groups': ['members'],
    });

    console.log('User added to the group:', userGroupResponse);

    router.push('/registered');
  } catch (error) {
    console.error('Error registering user:', error);
  }
};

我提到“至少用于测试”,因为这种方法可能是一个安全问题:它在用户注册后自动登录而无需任何确认。
1.使用确认后触发器:您可以使用AWS Lambda添加在用户确认后运行的触发器。此触发器可以将用户添加到组。这种方法比前一种方法更安全,因为它不涉及在用户注册后自动登录。如果您选择此选项,则需要设置AWS Lambda函数并配置Cognito以在用户确认后调用它。
您可以在“
How do I automatically confirm users in Amazon Cognito?
”中看到示例
简短的描述是:
当用户注册Amazon Cognito用户池时,他们通常必须验证其电子邮件地址或电话号码。
这通常是通过向用户的电子邮件地址或电话号码发送OTP来进行验证。
用户也可以在没有OTP验证的情况下被自动确认。
以下是自动确认用户的高级步骤,而无需使用带有用户电子邮件地址或电话号码的OTP:

  • 创建AWS Lambda函数。
  • 使用预注册Lambda触发器创建Amazon Cognito用户池。
  • 在Amazon Cognito中注册用户。使用AWS管理控制台或AWS API验证用户属性。

相关问题