Firebase身份验证与AWS Cognito

时间:2016-11-17 08:05:25

标签: amazon-web-services firebase google-analytics firebase-authentication amazon-cognito

我们正在使用API​​ Gateway和Lambda在AWS上构建移动和Web应用程序,目前正在评估我们是否应该使用所有AWS Mobile Servcies(Cognito,Analytics,Mobile Hub等),或者我们是否应该使用Firebase(提供远程配置等优点。

我认为使用分析,远程配置,崩溃报告,通知等firebase的非功能部分应该可以使用AWS后端。部分我不确定是身份验证层。

AWS Cognito很好地集成到API Gateway和Lamdba中,例如只有经过身份验证的用户才能执行某些API调用

如果我们使用Firebase身份验证,是否可以达到相同的行为? 对此有任何好的或坏的经历?

6 个答案:

答案 0 :(得分:27)

我们正在做同样的事情。 我们从Cognito开始,但转移到Firebase,因为我们对AWS Android SDK实现Google和Facebook的身份验证流程的方式不满意:代码很老,它使用了弃用的方法,通常需要重写。另一方面,Firebase身份验证显然可以无缝运行。 如果您不使用Cognito,则需要在AWS API Gateway中实现自定义身份验证器,这非常简单,并在https://aws.amazon.com/blogs/mobile/integrating-amazon-cognito-user-pools-with-api-gateway/中进行了描述。用于令牌验证的Firebase说明位于https://firebase.google.com/docs/auth/admin/verify-id-tokens

以下是我的身份验证员代码的摘录:

'use strict';

// Firebase initialization
// console.log('Loading function');
const admin = require("firebase-admin");
admin.initializeApp({
  credential: admin.credential.cert("xxx.json"),
  databaseURL: "https://xxx.firebaseio.com"
});
// Standard AWS AuthPolicy - don't touch !!
...
// END Standard AWS AuthPolicy - don't touch !!

exports.handler = (event, context, callback) => {
    // console.log('Client token:', event.authorizationToken);
    // console.log('Method ARN:', event.methodArn);

    // validate the incoming token
    // and produce the principal user identifier associated with the token

    // this is accomplished by Firebase Admin
    admin.auth().verifyIdToken(event.authorizationToken)
        .then(function(decodedToken) {
            let principalId = decodedToken.uid;
            // console.log(JSON.stringify(decodedToken));

            // if the token is valid, a policy must be generated which will allow or deny access to the client

            // if access is denied, the client will recieve a 403 Access Denied response
            // if access is allowed, API Gateway will proceed with the backend integration configured on the method that was called

            // build apiOptions for the AuthPolicy
            const apiOptions = {};
            const tmp = event.methodArn.split(':');
            const apiGatewayArnTmp = tmp[5].split('/');
            const awsAccountId = tmp[4];
            apiOptions.region = tmp[3];
            apiOptions.restApiId = apiGatewayArnTmp[0];
            apiOptions.stage = apiGatewayArnTmp[1];

            const method = apiGatewayArnTmp[2];
            let resource = '/'; // root resource
            if (apiGatewayArnTmp[3]) {
                resource += apiGatewayArnTmp[3];
            }


            // this function must generate a policy that is associated with the recognized principal user identifier.
            // depending on your use case, you might store policies in a DB, or generate them on the fly

            // keep in mind, the policy is cached for 5 minutes by default (TTL is configurable in the authorizer)
            // and will apply to subsequent calls to any method/resource in the RestApi
            // made with the same token

            // the policy below grants access to all resources in the RestApi
            const policy = new AuthPolicy(principalId, awsAccountId, apiOptions);
            policy.allowAllMethods();
            // policy.denyAllMethods();
            // policy.allowMethod(AuthPolicy.HttpVerb.GET, "/users/username");

            // finally, build the policy and exit the function
            callback(null, policy.build());
            })
        .catch(function(error) {
            // Firebase throws an error when the token is not valid
            // you can send a 401 Unauthorized response to the client by failing like so:
            console.error(error);
            callback("Unauthorized");
        });
};

我们还没有投入生产,但是对身份验证器的测试显示它在Google,Facebook和密码身份验证方面表现正常,而且速度非常快(60 - 200毫秒)。 我可以看到的唯一缺点是,您需要为authenticator lambda函数付费,而Cognito集成验证器是免费的。

答案 1 :(得分:18)

TL; DR; Firebase> Cognito

我们首先开始使用Cognito,但是当我们使用联合身份(例如,Google登录,Facebook登录等)时,我们最终意识到它有一种残酷的气味。对于Cognito用户池(即允许用户使用用户名和密码进行注册),您可以使用内置的API Gateway Cognito用户池授权程序,它可以很好地工作。您不需要编写自己的自定义授权程序或任何内容。

但是,如果您想支持联合身份,则需要将API网关上的身份验证更改为IAM身份验证,然后让每个客户端sigv4签署请求,这对我们来说是一个棘手的问题并且成本显着开发时间。选项2是让API Gateway为每个客户端的API调用生成代码......在我看来,这证明了与Cognito的繁琐集成。

我们让Firebase通过API Gateway的自定义授权程序工作。在所有客户端(iOS,Android和Web)上轻而易举。 API网关端点链接到Lambda函数,Lambda函数能够代表调用端点的用户与DynamoDB,S3和其他Web服务进行通信。 lambda函数知道调用用户是谁,因为自定义授权者在JWT中返回了电子邮件地址。

这是一个非常基本的Firebase自定义授权程序,它将JWT中的用户电子邮件作为principalId返回:

'use strict';
console.log('Loading function');

var admin = require('firebase-admin');
var serviceAccount = require('./my-secret-json.json');

admin.initializeApp({
    credential: admin.credential.cert(serviceAccount),
    databaseURL: 'https://my-app.firebaseio.com'
});

exports.handler = (event, context, callback) => {
    var token = event.authorizationToken;

    if (token == null) {
        callback('Invalid token');
    }
    else {
        admin.auth().verifyIdToken(token)
            .then(function (decodedToken) {
                var email = decodedToken.email;
                var policy = generatePolicy(email);
                callback(null, policy);
            }).catch(function (error) {
                console.log(error);
                callback('Unauthorized'); 
            });
    }
};

var generatePolicy = function (email) {
    return {
        principalId: email,
        policyDocument: {
            Version: '2012-10-17',
            Statement: [
                {
                    Action: 'execute-api:Invoke',
                    Effect: email ? 'allow' : 'deny',
                    Resource: '*'
                }
            ]
        }
    };
}

然后,您可以在API网关映射模板中使用$context.authorizer.principalId来检索电子邮件并将其传递给lambda X.

答案 2 :(得分:5)

Aws文档很混乱。 Firebase中更好地记录了不同身份验证步骤的回调系统。结果是更清晰的代码和更好的对身份验证流程的控制。此外,Firebase用户界面更加用户友好。如果您打算使用内容提供程序和同步适配器,我建议使用Firebase,因为您将拥有本地和远程(Firebase)数据库之间的数据同步的简单方法

答案 3 :(得分:2)

与firebase相比,aws cognito提供了更多验证用户身份的方法。特别是,如果您正在构建游戏,它可以通过谷歌和ios游戏中心登录。它提供同步排行榜和游戏中心提供的成就。 Cognito中有自动状态同步功能。但绝对是非常令人困惑的。实施需要太多时间。另一方面,firebase身份验证实现起来非常快。

答案 4 :(得分:1)

如果您使用Unity,目前Unity SDK不支持Cognito用户池。 (也就是说,AWS主持的用户列表)我因此而犹豫不决。请参阅我的帖子here他们确认这是真的,目前(26/06/2017)该功能仍然无法使用,这可能表明他们对Unity用户缺乏关注。

但是,如果我使用Firebase进行登录,我需要对这些凭据进行更多集成才能使用AWS服务。 (我想使用S3和DynamoDB,但只有登录用户才能使用它。)这也让我意识到我应该把所有内容都移到Firebase,以尽快节省我的时间和挫折。 (实时数据库比S3 / DynamoDB更昂贵,但Unity有自己的AWS MobileAnalytics替代品)

AWS S3最近获得了更好的用户界面,我认为这与谷歌的水平相近。但除此之外,我认为Firebase的UI使用起来更加快乐。

此外,Firebase身份验证是免费的,而Cognito每月最多可获得5万活跃用户。 (下一个50k将花费0.0055,这意味着如果你有100k MAU,它将是50000 * 0.0055 = 275美元https://aws.amazon.com/cognito/pricing/

还有一件事,AWS .NET documentation是我认为阅读/搜索的噩梦。

答案 5 :(得分:0)

对我而言,如果您决定转至其他身份验证服务提供商,则交易突破者可以导出所有详细信息的用户。

虽然在Firebase中可以实现,但在AWS Cognitio中不可用! 您可以输入一年中的任何时间,但永远不能离开:)。 https://forums.aws.amazon.com/thread.jspa?threadID=296932