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

配置auto_verified_attributes=["email"]后,Cognito注册用户仍未验证?

LocalStack Cognito用户池自动验证邮箱不生效问题

问题背景

我通过Terraform配置了LocalStack的Cognito用户池,设置了auto_verified_attributes = ["email"],期望注册用户时邮箱自动完成验证,用户状态同步变为已确认。但实际注册后,查看用户信息发现email_verified为false,UserStatus仍处于UNCONFIRMED状态。

我的Terraform用户池配置

provider "aws" {
  region                  = "us-east-1"  # 可修改为需要的区域
  access_key              = "test"       # LocalStack访问密钥
  secret_key              = "test"       # LocalStack秘密密钥
  skip_credentials_validation = true
  skip_requesting_account_id = true
  skip_metadata_api_check     = true

  endpoints {
    iam           = "http://localhost:4566"
    cognitoidp   = "http://localhost:4566"
  }
}
resource "aws_cognito_user_pool" "main_user_pool" {
  name = "main_user_pool"

  account_recovery_setting {
    recovery_mechanism {
      name     = "verified_email"
      priority = 1
    }

    recovery_mechanism {
      name     = "verified_phone_number"
      priority = 2
    }
  }

  # 定义用户池属性,仅标准属性设为必填
  schema {
    name                = "email"
    attribute_data_type = "String"
    mutable             = true
    required            = true
  }

  password_policy {
    minimum_length    = 6
    require_lowercase = true
    require_numbers   = true
    require_symbols   = true
    require_uppercase = true
  }

  email_configuration {
    email_sending_account = "COGNITO_DEFAULT"
  }

  username_attributes = ["email"]
  auto_verified_attributes = ["email"]
# 允许用户用邮箱或用户名登录

  username_configuration {
    case_sensitive = true
  }
}

resource "aws_cognito_user_pool_client" "userpool_client" {
  name                          = "my-client"
  user_pool_id                  = aws_cognito_user_pool.main_user_pool.id
  generate_secret               = false  # 移动端等公开客户端无需密钥
}

output "user_pool_client_id" {
  value = aws_cognito_user_pool_client.userpool_client.id
}

Swift应用注册代码

func registerUser(email: String, password: String) {
        let serviceConfiguration = AWSServiceConfiguration(region: .USEast1,
                                                           credentialsProvider: nil)
        AWSServiceManager.default().defaultServiceConfiguration = serviceConfiguration

        let signUpRequest = AWSCognitoIdentityProviderSignUpRequest()!
        signUpRequest.clientId = CognitoConfig.clientId
        signUpRequest.username = email
        signUpRequest.password = password
        
        // 定义用户属性(邮箱)
        let emailAttribute = AWSCognitoIdentityUserAttributeType()
        emailAttribute?.name = "email"
        emailAttribute?.value = email
        
        signUpRequest.userAttributes = [emailAttribute!]
        
        // 获取服务提供者实例
        let cognitoProvider = AWSCognitoIdentityProvider(forKey: "LocalStackCognito")
        
        // 执行注册
        cognitoProvider.signUp(signUpRequest).continueWith { task -> AnyObject? in
            DispatchQueue.main.async {
                if let error = task.error {
                    print("注册错误: \(error)")
                    errorMessage = error.localizedDescription
                } else {
                    print("注册成功")
                    
                    loginUser(email: email, password: password)
                }
            }
            return nil
        }
    }

配置验证与用户状态

通过awslognito-idp describe-user-pool --user-pool-id "<userpoolid>"确认用户池已正确设置AutoVerifiedAttributes: ["email"],但注册后执行awslocal cognito-idp list-users --user-pool-id "<userpoolid>",用户状态如下:

{
    "Users": [
        {
            "Username": "141bd541-2d8a-4c55-8ebd-83296e1ff99b",
            "Attributes": [
                {
                    "Name": "cognito:username",
                    "Value": "test99@gmail.com"
                },
                {
                    "Name": "email",
                    "Value": "test99@gmail.com"
                },
                {
                    "Name": "sub",
                    "Value": "141bd541-2d8a-4c55-8ebd-83296e1ff99b"
                },
                {
                    "Name": "email_verified",
                    "Value": "false"
                }
            ],
            "UserCreateDate": 1710631590.379655,
            "UserLastModifiedDate": 1710631590.379655,
            "Enabled": true,
            "UserStatus": "UNCONFIRMED"
        }
    ]
}

问题原因及解决方法

核心原因:LocalStack与真实AWS Cognito的行为差异

真实AWS Cognito中,设置auto_verified_attributes后,注册时会自动发送验证邮件/短信,用户完成验证后状态自动变更;但LocalStack的Cognito模拟逻辑默认不会自动触发验证流程,也不会主动标记email_verified为true。

解决办法

方法一:手动触发用户确认与邮箱验证状态更新

注册成功后,通过命令行或代码调用Admin API完成两步操作:

  1. 命令行方式:
# 标记邮箱已验证
awslocal cognito-idp admin-update-user-attributes --user-pool-id <userpoolid> --username <用户sub或邮箱> --attributes Name=email_verified,Value=true
# 确认用户注册
awslocal cognito-idp admin-confirm-sign-up --user-pool-id <userpoolid> --username <用户sub或邮箱>
  1. Swift代码方式(需确保客户端有对应Admin API权限):
// 确认用户注册
let confirmRequest = AWSCognitoIdentityProviderAdminConfirmSignUpRequest()!
confirmRequest.userPoolId = CognitoConfig.userPoolId
confirmRequest.username = email
cognitoProvider.adminConfirmSignUp(confirmRequest).continueWith { task in
    if let error = task.error {
        print("确认用户失败: \(error)")
    } else {
        print("用户已确认")
        // 更新邮箱验证状态
        let updateAttrsRequest = AWSCognitoIdentityProviderAdminUpdateUserAttributesRequest()!
        updateAttrsRequest.userPoolId = CognitoConfig.userPoolId
        updateAttrsRequest.username = email
        let verifiedAttr = AWSCognitoIdentityUserAttributeType()
        verifiedAttr?.name = "email_verified"
        verifiedAttr?.value = "true"
        updateAttrsRequest.userAttributes = [verifiedAttr!]
        cognitoProvider.adminUpdateUserAttributes(updateAttrsRequest).continueWith { updateTask in
            if let err = updateTask.error {
                print("更新邮箱验证状态失败: \(err)")
            } else {
                print("邮箱已标记为验证")
                loginUser(email: email, password: password)
            }
        }
    }
    return nil
}

方法二:使用LocalStack Lambda触发器自动化

配置PostConfirmation类型的Lambda触发器,在用户注册完成后自动执行确认操作并更新email_verified状态。该方式适合需要全自动化的场景,但需额外配置LocalStack的Lambda环境。

方法三:检查用户池客户端配置

确保用户池客户端未限制验证流程,比如explicit_auth_flows设置正常,当前你的客户端generate_secret = false配置无问题,无需修改。

总结

LocalStack的Cognito模拟实现与真实AWS存在差异,自动验证不会自动完成,需手动触发用户确认和邮箱验证状态更新,或通过Lambda触发器实现自动化。

内容的提问来源于stack exchange,提问作者Runeaway3

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 10:47:08