将 Cognito 中的用户信息与 AWS Amplify GraphQL 关联

chi*_*ro2 5 amazon-web-services swift amazon-cognito graphql aws-amplify

我使用的是 xcode 11.4、Swift 4。目标是:

  1. 在 Cognito 用户池中注册新用户,然后使用 Amplify GraphQL 保存关联的用户记录。

  2. 使用 Cognito 用户池登录后对用户记录进行 CRUD。

问题是我不知道如何将 Cognito 与 Amplify GraphQL 关联起来。例如,在 Google Firebase 身份验证和 Firestore 中,我会UID在注册后获得一个唯一的用户 ID,然后我会Firestore使用 key 创建一个关联的用户记录 this UID。然后在用户登录/身份验证时,我可以UID从 firebase auth 获取此信息并在 firestore 中找到相关记录。

目前,我使用 AWS 堆栈创建了一个用户模型schema.graphql

type User @model @auth(rules: [{ allow: owner, ownerField: "id", operations: [create, update, delete]}]){
    id: ID!
    firstName  : String
    lastName   : String
    handle     : String
    email      : String!
}
Run Code Online (Sandbox Code Playgroud)

这样只有经过身份验证的用户才能创建、更新和删除。接下来我在某处SignUpController创建一个新用户:

AWSMobileClient.default().signUp( username: email
                                , password: password
                                , userAttributes: ["email": email]) { (signUpResult, error) in
    if let signUpResult = signUpResult {

        switch(signUpResult.signUpConfirmationState) {
            case .confirmed:
                self.showAlert(msg: "You already have an account. Please go back and press log in")
            case .unconfirmed:
                break 
            case .unknown:
                self.showAlert(msg: "Network error")
        }
    } else if let error = error { ... }
Run Code Online (Sandbox Code Playgroud)

然后使用代码确认用户:

AWSMobileClient.default().confirmSignUp(username: email, confirmationCode: code) { (signUpResult, error) in
    if let signUpResult = signUpResult {
        switch(signUpResult.signUpConfirmationState) {
            case .confirmed:
               // This is where I need to create an associated user account
               break
            case .unconfirmed:
                self.showAlert(title: "Error", msg: "User is not confirmed and needs verification via \(signUpResult.codeDeliveryDetails!.deliveryMedium) sent at \(signUpResult.codeDeliveryDetails!.destination!)")
            case .unknown:
                self.showAlert(title: "Error", msg: "Network error")
        }
    } else { //if let error = error {
        self.showAlert(title: "Error", msg: "Network error")
    }
Run Code Online (Sandbox Code Playgroud)

现在我的解决方案case .confirmed是立即登录,然后通过以下方式获取用户client token

class CognitoPoolProvider : AWSCognitoUserPoolsAuthProviderAsync {

    /// this token may not be what you want ...
    func getLatestAuthToken(_ callback: @escaping (String?, Error?) -> Void) {

        AWSMobileClient.default().getTokens { (token, error) in
            if let error = error {
                callback(nil,error)
            }
            callback(token?.accessToken?.tokenString, error)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

事实证明这是错误的解决方案,因为用户的客户端令牌一直在变化。

总的来说,这是一个标准的 hello-world 问题,AWS 应该提供一个标准的开箱即用解决方案。我搜索了文档和github,但找不到满意的答案。

Pha*_*iệt 3

正确的方法是不要信任客户端从 Cognito 创建关联用户信息,您必须在服务器端执行此操作。

您应该为 Cognito 创建一个新的 Lambda 后确认触发器并对其进行编码以创建关联账户。您可以使用event.userName或创建自定义属性 uuid 类型custom:id来链接您的关联帐户。

参考: https: //docs.aws.amazon.com/cognito/latest/developerguide/user-pool-lambda-post-confirmation.html

  • 我们可能有多个客户端,那么我们如何确保/信任客户端应用程序之间的代码/工作流程一致?--> 我们必须强迫他们使用独特的工作流程,确保如果您注册了我的应用程序,您必须拥有关联帐户。如果客户端代码注册错误/错误工作流程,然后重试并且由于我们没有关联帐户而无法使用旧帐户,会发生什么情况? (2认同)