AWS 网络和移动中心应用程序

AWS web and mobile hub application

在 AWS 上,我希望创建一个允许用户通过手机、网络或两者登录的应用程序。

我创建了一个使用 API 网关、Lambdas 和 DynamoDB 作为后端的系统。我已使用 JavaScript 登录 web 工作,但在查找相同代码的 iOS 的 Swift 示例时遇到问题(仅 objective C 可用)。所以我创建了一个移动中心应用程序,导入了我现有的 API 并有一个有效的 iOS 登录。

问题是 iOS 端使用 Mobile Hub,所以我现在有 2 个不同的用户池,因此您无法在 Web 上注册并在移动设备上登录(反之亦然)。

我尝试更改 iOS 应用程序中的设置以指向我的网络应用程序 Cognito 用户池设置并删除机密,但它出错了,因为它不能为 null 或为空。

为什么移动中心需要客户端密码? JavaScript 建议的文档是不好的做法,因为可以反编译代码并提取秘密。

似乎没有任何一致的文档来解释,我猜,作为移动和网络应用程序最常见的用例!

另一个问题是我可以为我的 API 网关下载我的 API 客户端 SDK,以便与网络应用程序和 iOS 应用程序一起使用。但是,生成的移动中心应用程序包含基于 REST 的调用?我在这里要疯了吗还是官方网络方法不是 link 官方移动方法?

所以关键问题是:

是否有更好的方法来设置 iOS(后来 Android)和网络应用程序?

我花了很多时间和精力,尝试了很多方法。

"Mobile Hub" 很好地设置了用户池、身份池、IAM 角色等

密钥等主要在 Info.plist 文件中提供,尽管(不明智地)用户池 AWSSignInProvider 的开发人员使其在配置文件中具有硬编码密钥。

所以:

如果您不打算使用 "Mobile Hub" 控制台应用程序来更改您的移动应用程序配置,那么您将不需要更多下载。在那种情况下,您不必担心 Info.plist 或配置文件的更改,您可以编辑您想要的内容。

不清楚您是要使用移动中心创建的身份池并只想插入您的用户池,还是要更改两个池。显然,如果您使用相同的身份池,则不需要进行以下某些更改(它们很明显,因为您会将它们更改为完全相同)。

因此,您只需更改 ID 即可正确连接所有内容。

一般来说,您需要在Info.plist和配置文件中修复所有下载的密钥和ID,然后您需要更新服务器配置。更详细的,这里是你需要改变的地方:

在应用程序中:

将Info.plist中的所有键更新为您想要的键。 (特别是 google 的凭据提供程序和身份管理器密钥)但是如果您使用其他移动中心服务,也请检查那里的密钥。

如果您使用的是 s3 和其他一些服务,目录 names/database 名称也存储在代码中...我将其保留为 activity 以查找它们。

在文件 MySampleApp->AmazonAWS->AWSConfiguration.swift 中编辑 Mobile hub 提供的密钥以匹配您的用户群(在执行此操作时小声咒骂,因为它们不在 Info.plist )

在控制台中: 如果您的应用名称不存在,请将您的应用名称放入您的用户池应用列表中,并记录用户池 ID、应用 ID 和应用密码。

单击移动中心创建的联合身份和身份池并更新身份验证提供程序以使用您的 Cognito 用户池 ID 和应用程序 ID。

如果您也要更改身份池,那么您将需要查看您的 auth 和 unauth 用户的 IAM 角色,并专门编辑名为的策略:.....yourapp....signin_MOBILEHUB_xxxxxxx,并将该策略中的身份池 ID 更改为您要使用的身份池 ID。对 auth 和 unauth 都执行此操作。

(如果您只使用一个池,您可以更改 ID,或者如果您将有多个身份池(用于测试等),则将另一个池添加到这样的 ID 列表中)

            "Resource": [
            "arn:aws:cognito-identity:*:*:identityPool/us-east-1:8s8df8f8-sd9fosd9f0sdf-999sd99fd",
            "arn:aws:cognito-identity:*:*:identityPool/us-east-1:dfsf9099-sd9fosd9f0sdf-sd9f0sdf09f9s"
        ]

类似地,在与角色关联的信任关系中,您需要固定 ID(或者如果您希望角色服务于多个身份池,则处理多个 ID)。下面是如何指定多个 ID。

      "Condition": {
    "ForAllValues:StringLike": {
      "cognito-identity.amazonaws.com:aud": [
        "us-east-1:8s8df8f8-sd9fosd9f0sdf-999sd99fsdfdd",
        "us-east-1:dfsf9099-sd9fosd9f0sdf-sd9f0sdf09f9s"
      ]
    },

如果您也在使用 google...您需要确保在 google 的 IAM 配置中有一个 identityProvider(移动集线器为您做了)并且如果您是使用您自己的身份池,在您的联合身份池授权提供者配置中,您需要 select google 打开 id 提供者(并将 google 也放在授权提供者中(但我不认为这部分是绝对必要的))

facebook 不使用 OpenID Connect,它有一种配置到身份验证提供程序部分的专有方法,因此如果需要,请在身份池身份验证提供程序部分输入这些密钥。

这应该足以让它发挥作用。

不,您不会发疯...文档与当前的 IOS SDK 不匹配。 Mobile hub 使用构建在 sdk 顶部的 aws-mobilehub-helper-ios (github),因此文档也不适用于它! Mobile Hub Helper 设计精美,因此我建议您使用它,而不是原始 SDK。

(最后......我在这里超出了我的深度,因为我不使用 API 网关,但我的理解是 API 网关是获取凭据的一种方式使用 AWS 服务,并使用移动中心应用程序,您将使用 Cognito 获取这些凭据,因此我不确定您是否需要将 API 网关带入其中...完全)

更新

您可能不希望对 javascript 应用的用户使用客户端密码,并在同一个池中使用 IOS 移动应用。这可以通过两种方式完成:

1) 更好的方法是在用户池中创建两个不同的客户端。对于一个,您将生成一个客户端密码,对于另一个,您将取消选中 "generate client secret" 框。

然后在您的联合身份池中转到身份验证提供程序,然后单击 Cognito,并指定两个使用相同用户池 ID 的不同提供程序。 (这实际上不是两个不同的提供程序,而是控制台让您指定它的方式)。然后您将两个不同的客户端 ID 放入这些提供程序中。

现在 IOS 应用程序和 Javascript 应用程序都可以访问池并从 identityProvider 和 credentialsProvider 获取身份验证和凭据。

2) 一个不太好的方法。这种方式更糟糕的原因是因为我不知道它对您的移动应用程序安全性的影响(如果有的话)。在 AWS,如果不购买支持合同,就没有人可以提出问题。但存在另一种方式。

您所做的是在两个应用程序中使用相同的客户端 ID,并且您不生成客户端密码。为此,您将 "nil" 放在 clientSecret 中。这适用于一些警告。

首先,AWS Mobile Hub 在它的 AWSCognitoUserPoolsSignInProvider 中有一个错误。 class 要求 clientSecret 不为空。但是在SDK中,告诉SDK你不想要client secret的唯一方法就是传nil!但是有一些解决方法。
(我所做的是使用 AWSCUPIdPSignInProvider.swift(我写的),它可以正常工作,而且我有一个版本可以使用 nil 作为秘密。我这样做是因为我可以更快地测试它。如果你想使用它,你可以在 github 上找到那个登录提供商)

但更好(更适合未来)的解决方案可能是使用移动中心提供的 AWSCognitoUserPoolsSignInProvider,但更改 AWSMobileClient 中的代码以配置和注册您自己的池,而不是让 AWSCognitoUserPoolsSignInProvider 为您完成。

我懒得尝试这个,(因为我们必须这样做,因为 AWS 还没有抽出时间更新 github aws-mobilehub-helper-ios)。但基本上在 AWSMobileClient 中而不是这段代码:

    func setupUserPool() {
    // register your user pool configuration
    AWSCognitoUserPoolsSignInProvider.setupUserPoolWithId(AWSCognitoUserPoolId, cognitoIdentityUserPoolAppClientId: AWSCognitoUserPoolAppClientId, cognitoIdentityUserPoolAppClientSecret: AWSCognitoUserPoolClientSecret, region: AWSCognitoUserPoolRegion)

    AWSSignInProviderFactory.sharedInstance().registerAWSSignInProvider(AWSCognitoUserPoolsSignInProvider.sharedInstance(), forKey:AWSCognitoUserPoolsSignInProviderKey)

}

你会得到类似这样的代码

        func setupUserPool() {
        // register your user pool configuration
    // find the service configuration (we don't know if they set it as default)
             let credentialProvider = AWSCognitoCredentialsProvider(regionType: .USEast1 (or your region), identityPoolId: "YourIdentityPoolId")
             let configuration = AWSServiceConfiguration(region: .USWest2 (or your region), credentialsProvider: credentialProvider)

    // configure and put your own user pool in the service configuration
                let userPoolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: AWSCognitoUserPoolAppClientId, clientSecret: nil, poolId:AWSCognitoUserPoolId)

    // now we register that pool with the service configuration using the key they use
                AWSCognitoIdentityUserPool.register(with: configuration, userPoolConfiguration: userPoolConfiguration, forKey: AWSCognitoUserPoolsSignInProviderKey)

AWSSignInProviderFactory.sharedInstance().registerAWSSignInProvider(AWSCognitoUserPoolsSignInProvider.sharedInstance(), forKey:AWSCognitoUserPoolsSignInProviderKey)

    }

但正如我上面所说,解决方案 1,使用两个不同的客户端并指定两个不同的提供商是首选。