64 votes

Authentification Firebase vs AWS Cognito

Nous construisons une application mobile et web sur AWS en utilisant API Gateway et Lambda et nous évaluons actuellement si nous devrions utiliser AWS Cognito o Firebase Auth .

AWS Cognito s'intègre bien dans API Gateway et Lamdba, par exemple, seuls les utilisateurs authentifiés peuvent exécuter certains appels API. Est-il possible d'obtenir le même comportement en utilisant Firebase Authentication à la place ? Avez-vous une bonne ou une mauvaise expérience en la matière ?

50voto

pmosconi Points 231

Nous faisons de même.

Nous avons commencé avec Cognito, mais nous sommes passés à Firebase parce que nous n'étions pas satisfaits de la façon dont le SDK Android d'AWS met en œuvre le flux d'authentification avec Google et Facebook : le code est assez ancien, il utilise des méthodes obsolètes et nécessite généralement une réécriture. En revanche, l'authentification Firebase fonctionne manifestement de manière transparente.

Si vous n'utilisez pas Cognito, vous devez mettre en œuvre votre authentificateur personnalisé dans AWS API Gateway, ce qui est assez facile et est décrit dans le document suivant https://aws.amazon.com/blogs/mobile/integrating-amazon-cognito-user-pools-with-api-gateway/ . Les instructions de Firebase pour la validation des jetons se trouvent à l'adresse suivante https://firebase.google.com/docs/auth/admin/verify-id-tokens

Voici un extrait du code de mon authentificateur :

'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");
        });
};

Nous ne sommes pas encore en production, mais les tests sur l'authentificateur montrent qu'il se comporte correctement avec Google, Facebook et l'authentification par mot de passe et qu'il est également très rapide (60 - 200 ms). Le seul inconvénient que je vois est que vous serez facturé pour la fonction lambda de l'authentificateur, alors que l'authentificateur intégré de Cognito est gratuit.


Mise à jour après presque 1 an

Je me suis éloigné de l'authentificateur personnalisé API Gateway, principalement parce que je n'ai pas été en mesure d'automatiser son déploiement avec cloudformation scripts. Ma solution est maintenant d'avoir l'authentification directement dans l'API en mettant en cache les tokens pendant un certain temps, comme le fait l'Authenticator, afin d'éviter des validations excessives.

0 votes

Pouvez-vous nous expliquer pourquoi vous n'étiez pas satisfait de Cognito pour l'authentification Facebook/Google ?

2 votes

Mise à jour après presque 1 an : - Je me suis éloigné de l'authentificateur personnalisé API Gateway, principalement parce que je n'ai pas été en mesure d'automatiser son déploiement avec cloudformation scripts. Ma solution est maintenant d'avoir l'authentification directement dans l'API en mettant en cache les tokens pendant un certain temps, comme le fait l'Authenticator, afin d'éviter des validations excessives.

0 votes

Bibliothèque jwt tierce firebase.google.com/docs/auth/admin/ La solution pour éviter les allers-retours pour vérifier le compte firebase ?

37voto

Aziz Javed Points 1526

TL;DR ; Firebase > Cognito

Nous avons commencé par Cognito, mais nous avons finalement réalisé qu'il avait une odeur atroce lorsqu'il s'agissait d'utiliser des identités fédérées (par exemple, Google Sign-in, Facebook Login, etc.). Pour les pools d'utilisateurs Cognito (c'est-à-dire permettant à un utilisateur de s'inscrire avec un nom d'utilisateur et un mot de passe), vous pouvez utiliser l'API Gateway Cognito User Pool Authorizer et cela fonctionne à merveille. Vous n'avez pas besoin d'écrire votre propre Authorizer personnalisé ou quoi que ce soit d'autre.

Cependant, si vous souhaitez prendre en charge les identités fédérées, vous devez modifier l'authentification sur votre passerelle API en IAM Auth, puis demander à CHAQUE client de signer les requêtes avec Sigv4, ce qui s'est avéré être une épine dans notre pied et a coûté beaucoup de temps de développement. L'option 2 consistait à demander à API Gateway de générer votre code pour vos appels API pour chaque client... ce qui, à mon avis, témoigne de la lourdeur de l'intégration avec Cognito.

Nous avons fait fonctionner Firebase via l'autorisateur personnalisé pour API Gateway. C'était un jeu d'enfant sur tous les clients (iOS, Android et Web). Les points de terminaison API Gateway ont été reliés à des fonctions Lambda, qui ont pu communiquer avec DynamoDB, S3 et d'autres services Web au nom de l'utilisateur appelant le point de terminaison. Les fonctions Lambda savaient qui était l'utilisateur appelant parce que l'autorisateur personnalisé renvoyait l'adresse électronique dans le JWT.

Voici un autorisateur personnalisé Firebase assez basique qui renvoie l'email de l'utilisateur dans le JWT en tant que 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: '*'
                }
            ]
        }
    };
}

Vous pouvez alors utiliser $context.authorizer.principalId dans votre modèle de mappage API Gateway pour récupérer l'e-mail et le transmettre à lambda X.


J'ai d'abord pensé que la latence serait un problème, mais cela ne semble pas être le cas. Toutes les latences que j'ai rencontrées sont dues à la latence de la lambda qui est appelée en raison du démarrage à froid. J'ai remarqué que les lambdas d'autorisation vivent beaucoup plus longtemps que les autres lambdas.


Ce lambda est appelé pour chaque requête du backend. Il y a cependant deux choses à faire :

  1. La mise en cache est activée pendant 1 heure pour chaque JWT, ce qui simplifie grandement les appels.
  2. Le lambda est appelé en permanence, de sorte qu'il ne devrait pas y avoir de démarrage à froid.
  3. Les premiers MILLIONS de requêtes lambda/mois sont gratuits, puis 0,20 $ par million de requêtes/mois. Ainsi, à moins que votre API ne soit appelée des MILLIONS de fois par mois, vous n'aurez pas à supporter des coûts exorbitants.

0 votes

Merci de nous avoir fait partager votre expérience. Je viens de rencontrer un obstacle avec Unity3d + Cognito lorsque j'ai réalisé que les pools d'utilisateurs n'étaient pas implémentés. J'aimerais essayer Firebase mais ne pas passer complètement à Firebase ou GCP pour le backend, en gardant AWS/API Gateway. Avez-vous également obtenu des identités fédérées, par exemple Facebook et Google fonctionnant avec Firebase+API Gateway ? Avez-vous rencontré des problèmes lors de cette opération ?

3 votes

J'ai réussi à faire fonctionner les identités fédérées avec Firebase+API Gateway. Honnêtement, il n'y avait rien de spécifique/personnalisé que je devais faire du côté du backend. Pour les clients, assurez-vous simplement que vous obtenez le JWT de Firebase après avoir connecté l'identité fédérée. Si vous voulez voir comment je l'ai fait dans le client iOS en utilisant Swift, faites-le moi savoir et je posterai un gist.

0 votes

@AzizizJaved comment est la latence pour appeler firebase auth à partir d'une lambda, pensez-vous que l'utilisation de Cognito serait beaucoup plus rapide puisque c'est AWS ?

10voto

Nicola Gallazzi Points 702

La documentation d'Aws est assez confuse. Le système de callbacks pour les différentes étapes de l'authentification est mieux documenté dans Firebase. Le résultat est un code plus propre et un meilleur contrôle du flux d'authentification. En outre, l'interface utilisateur de Firebase est plus conviviale. Si vous envisagez d'utiliser des fournisseurs de contenu et des adaptateurs de synchronisation, je vous suggère d'utiliser Firebase car vous disposerez de méthodes simples pour la synchronisation des données entre la base de données locale et la base de données distante (Firebase).

6voto

sn.anurag Points 103

Aws cognito offre plus de possibilités d'authentifier les utilisateurs que firebase. En particulier, si vous construisez un jeu, il offre la possibilité de se connecter via les centres de jeux de Google et d'ios. Il permet de synchroniser les classements et les réalisations des centres de jeux. La fonctionnalité de synchronisation automatique des états est présente dans Cognito. Mais en définitive, c'est très déroutant. Sa mise en œuvre prend trop de temps. D'un autre côté, l'authentification firebase est assez rapide à mettre en œuvre.

4voto

5argon Points 448

Au cas où vous utiliseriez Unity, le SDK Unity ne prend pas en charge le Cognito User Pool. (C'est à dire la liste d'utilisateurs hébergée par AWS) J'hésite actuellement à cause de cela. Voir mon post aquí qu'ils ont confirmé que c'est vrai, actuellement (26/06/2017) la fonctionnalité n'est toujours pas disponible ce qui pourrait montrer un manque d'attention pour les utilisateurs d'Unity de leur part.

Cependant, si j'utilise Firebase pour les identifiants, j'aurais besoin de quelques intégrations supplémentaires pour ces identifiants afin d'utiliser les services AWS. (J'aimerais utiliser S3 et DynamoDB mais seul l'utilisateur connecté peut les utiliser.) Cela m'a également fait réaliser que je devrais tout transférer vers Firebase pour gagner du temps et éviter les frustrations dès que possible. (La base de données en temps réel est plus chère que S3/DynamoDB, mais Unity a son propre remplacement d'AWS MobileAnalytics).

L'interface utilisateur d'AWS S3 a été récemment améliorée et je pense qu'elle est proche de celle de Google. Mais à part cela, je pense que l'interface utilisateur de Firebase est beaucoup plus agréable à utiliser.

De plus, l'authentification Firebase est gratuite tandis que Cognito est gratuit jusqu'à 50 000 utilisateurs actifs mensuels. (Les 50k suivants coûteront 0,0055, ce qui signifie que si vous avez 100k MAU, cela vous coûtera 50000 * 0,0055 = 275 USD). https://aws.amazon.com/cognito/pricing/ )

Une dernière chose, le Documentation AWS .NET est à mon avis un cauchemar pour la lecture et la recherche.

3 votes

J'ai pu facilement utiliser S3 et DynamoDB avec Firebase Authentication. Votre client appelle un point d'extrémité API Gateway qui est relié à lambda X, en passant le JWT de Firebase. Vous vérifiez le jeton JWT dans un autorisateur personnalisé, puis vous transmettez l'email de l'utilisateur à lambda X. Tant que X a un accès IAM à DynamoDB et S3, il peut obtenir les ressources de l'utilisateur et les renvoyer en tant que réponse de l'API Gateway.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X