AWS Web和移动中心应用程序

时间:2016-12-06 11:31:51

标签: ios amazon-web-services authentication mobile aws-mobilehub

在AWS上,我希望创建一个允许用户通过移动设备,网络或两者同时登录的应用程序。

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

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

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

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

似乎没有任何一致的文档可以解释,我猜是什么,作为移动和Web应用程序的最常见用例!

另一个问题是我可以为我的API网关下载我的API客户端SDK,以便与网络应用和iOS应用一起使用。但是,生成的移动中心应用程序包括基于REST的呼叫?我在这里发疯了还是官方网络方法没有链接到官方移动方式?

所以关键问题是:

  • 可以或应该将移动应用更改为指向原始应用 Cognito?
    • 如果是这样,我应该删除客户端秘密吗?
    • 我可以在设置后有效地忽略Mobile Hub并将其纯粹用于代码生成吗?假设它正在工作,我可以将生成的客户端SDK用于我的API网关吗?

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

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

1 个答案:

答案 0 :(得分:0)

"移动中心"很好地设置用户池,身份池,IAM角色等。

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

SO:

如果您不打算使用"移动中心"控制台应用程序用于更改您的移动应用程序配置,然后您不再需要下载。在这种情况下,您不必担心Info.plist或配置文件的更改,您可以编辑您想要的内容。

目前还不清楚您是打算使用移动集线器创建的标识池,只想插入用户池,或者是否要更改两个池。显然,如果您使用相同的标识池,则不需要下面的一些更改(它们将是显而易见的,因为您将更改它们完全相同)。

所以你要做的就是更改ID以便正确连接所有内容。

通常,您需要修复Inf​​o.plist和配置文件中所有下载的密钥和ID,然后您需要更新服务器配置。更详细地说,以下是您需要更改它的地方:

在应用程序中

将Info.plist中的所有键更新为您想要的键。 (特别是谷歌的凭证提供者和身份管理员密钥)但是如果您正在使用其他移动中心服务,请检查那里的密钥。

如果您正在使用s3,并且某些其他服务的目录名称/数据库名称也存储在代码中......我将其保留为活动以查找它们。

在文件MySampleApp-> AmazonAWS-> AWSConfiguration.swift中编辑移动集线器提供的密钥以匹配您的用户池(在安静地咒骂时这样做,因为它们不在Info.plist中)

控制台中的

: 将您的应用名称放在用户池APP列表中(如果不存在),并记录用户池ID,应用ID和应用密钥。

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

如果您也要更改身份池,那么您需要查看auth和unauth用户的IAM角色,并专门编辑名为的策略:..... yourapp .... signin_MOBILEHUB_xxxxxxx,以及将该策略中的标识池ID更改为您要使用的标识池ID。为auth和unauth都这样做。

(如果您只使用一个池,则可以更改ID,或者如果您将拥有多个身份池(用于测试......等),则可以将其他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"
      ]
    },

如果你也使用谷歌...你需要确保你在谷歌的IAM配置中有一个identityProvider(移动中心为你做了这个),如果你使用自己的身份池,你的联合身份池授权提供商配置您将需要选择谷歌开放ID提供商(并将谷歌也放在授权提供商(但我不认为这部分是严格需要的))

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

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

不,你不会发疯...文档与当前的IOS SDK不匹配。移动集线器使用aws-mobilehub-helper-ios(github),它建立在sdk的TOP上,所以文档也不适用于那个! Mobile Hub Helper有一个很好的设计,所以我建议你使用它,而不是原始的SDK。

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

<强>更新

您可能希望不为javascript应用程序的用户使用客户端密钥,也可以在同一个池中使用IOS Mobile App。这可以通过两种方式完成:

1)更好的方法是在用户池中创建两个不同的客户端。对于一个你将生成一个客户机密,另一个你将检查&#34;生成客户机密码&#34;框。

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

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

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

您所做的是在两个应用中使用相同的客户端ID,并且您不会生成客户端密钥。要做到这一点,你要把&#34; nil&#34;在clientSecret中。这可以很好地解决一些问题。

首先,AWS Mobile Hub在其AWSCognitoUserPoolsSignInProvider中存在错误。该类要求clientSecret为非null。但是在SDK中,告诉SDK你想要没有客户端秘密的唯一方法就是传递nil!但是有一些解决方法 (我所做的是使用AWSCUPIdPSignInProvider.swift(我写的),这将工作正常,我有一个版本将秘密为零。我这样做是因为我测试这个更快。你可以如果你想使用它,请在github上找到signin提供者)

但更好(更具未来证明)的解决方案可能是使用移动集线器提供的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,使用两个不同的客户端并指定两个不同的提供者是首选。