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

iOS应用AWS Cognito用户池迁移及Lambda触发与认证实现问题

解决Cognito用户迁移触发器在iOS登录时不触发的问题

我之前也碰到过一模一样的情况:Lambda测试正常,但iOS端登录就是不触发迁移触发器。问题根源在于Cognito默认使用的SRP(Secure Remote Password)认证流程不会触发用户迁移——因为SRP需要用户先存在于新用户池中才能完成密钥交换,而迁移触发器是在用户不存在时才会被调用。要触发迁移,必须改用USER_PASSWORD_AUTH认证流程,下面是具体的实现步骤:

第一步:开启用户池App客户端的USER_PASSWORD_AUTH流程

先在AWS控制台确认你的新用户池App客户端已经启用了该流程:

  • 进入Cognito用户池 → 选择你的新用户池 → 点击"App客户端"
  • 找到对应的App客户端,点击"显示详情"
  • 在"认证流程"部分,勾选USER_PASSWORD_AUTH(如果没勾选的话)

第二步:修改iOS端的Cognito配置,指定使用USER_PASSWORD_AUTH

关键是在初始化用户池时,将allowedAuthFlows设置为包含.userPasswordAuth,告诉SDK使用非SRP的用户名密码认证流程。

完整的代码示例

import AWSCognitoIdentityProvider

class AuthManager: NSObject, AWSCognitoIdentityPasswordAuthentication {
    var currentUsername: String?
    var currentPassword: String?
    private var passwordCompletionSource: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>?
    
    static let shared = AuthManager()
    
    private override init() {
        super.init()
        // 替换成你的用户池信息
        let poolId = "us-east-1_XXXXXXXXX"
        let clientId = "XXXXXXXXXXXXXXXXXXXXXXXXXX"
        let clientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXX" // 没有客户端密钥就传nil
        
        // 初始化用户池配置
        let poolConfig = AWSCognitoIdentityUserPoolConfiguration(
            clientId: clientId,
            clientSecret: clientSecret,
            poolId: poolId,
            endpoint: nil,
            region: .USEast1 // 替换成你的AWS区域
        )
        
        // 核心设置:指定使用USER_PASSWORD_AUTH流程
        poolConfig.allowedAuthFlows = [.userPasswordAuth]
        
        // 注册用户池
        let userPool = AWSCognitoIdentityUserPool(forKey: "MyAppUserPool", configuration: poolConfig)
        AWSCognitoIdentityUserPool.register(userPool, forKey: "MyAppUserPool")
    }
    
    // 实现AWSCognitoIdentityPasswordAuthentication协议方法
    func getDetails(_ authenticationInput: AWSCognitoIdentityPasswordAuthenticationInput, passwordAuthenticationCompletionSource: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>) {
        self.passwordCompletionSource = passwordAuthenticationCompletionSource
        
        // 这里用你之前获取的用户名密码生成认证详情
        guard let username = currentUsername, let password = currentPassword else {
            passwordAuthenticationCompletionSource.set(error: NSError(domain: "AuthError", code: -1, userInfo: [NSLocalizedDescriptionKey: "用户名或密码为空"]))
            return
        }
        
        let authDetails = AWSCognitoIdentityPasswordAuthenticationDetails(username: username, password: password)
        passwordAuthenticationCompletionSource.set(result: authDetails)
    }
    
    func didCompleteStepWithError(_ error: Error?) {
        // 处理认证过程中的错误
        if let error = error {
            print("认证步骤错误: \(error.localizedDescription)")
        }
    }
    
    // 对外暴露的登录方法
    func login(username: String, password: String, completion: @escaping (Bool, Error?) -> Void) {
        currentUsername = username
        currentPassword = password
        
        let userPool = AWSCognitoIdentityUserPool(forKey: "MyAppUserPool")
        let user = userPool.getUser(username)
        
        // 发起认证请求
        user.authenticateUser(password, passwordAuthenticationCompletion: { (session, error) in
            if let error = error {
                completion(false, error)
            } else if session != nil {
                completion(true, nil)
            } else {
                completion(false, NSError(domain: "AuthError", code: -2, userInfo: [NSLocalizedDescriptionKey: "登录失败,未获取到会话"]))
            }
        })
    }
}

关键说明

  • allowedAuthFlows的设置是核心:这会强制SDK使用USER_PASSWORD_AUTH流程,直接将用户名密码发送到Cognito,此时如果用户在新池中不存在,就会触发你配置的迁移Lambda触发器。
  • 如果你之前用的是SRP流程,修改后不需要大幅改动原有代码,只需要调整用户池配置即可。
  • 注意:USER_PASSWORD_AUTH的安全性比SRP低,所以当所有旧用户迁移完成后,建议改回SRP流程(将allowedAuthFlows改回.srp)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 16:27:34