12

Budujemy mobilną i internetową aplikację na AWS przy użyciu API Gateway i Lambda i obecnie oceniamy, czy powinniśmy używać wszystkich usług mobilnych AWS (Cognito, Analytics, Mobile Hub, itp.) Lub czy powinniśmy zamiast tego użyj Firebase (który oferuje pewne zalety, takie jak zdalna konfiguracja).Autoryzacja Firebase vs AWS Cognito

Myślę, że korzystanie z niefuntionalnej części bazy Firebase, takiej jak Analytics, Zdalna konfiguracja, Raporty o awariach, Powiadomienie powinno być w porządku z zapleczem AWS. Częścią, której nie jestem pewien, jest warstwa uwierzytelniania.

AWS Cognito ładnie integruje się z bramą API i Lamdbą, np. tylko uwierzytelnieni użytkownicy mogą wykonywać określone wywołania API.

Czy można uzyskać takie samo zachowanie, jeśli używamy uwierzytelniania Firebase? Jakieś dobre lub złe doświadczenie z tym związane?

Odpowiedz

15

robimy to samo. Zaczęliśmy od Cognito, ale przenieśliśmy się do Firebase, ponieważ nie byliśmy usatysfakcjonowani sposobem, w jaki AWS Android SDK implementuje przepływ uwierzytelniania z Google i Facebookiem: kod jest dość stary, korzysta z nieużywanych metod i generalnie wymaga przepisania. Z drugiej strony uwierzytelnianie Firebase działa bez zarzutu. Gdy nie korzystasz z Cognito, musisz zaimplementować niestandardowy usługodawca uwierzytelniający w AWS API Gateway, co jest dość łatwe i jest opisane w https://aws.amazon.com/blogs/mobile/integrating-amazon-cognito-user-pools-with-api-gateway/. Firebase instrukcje tokena walidacji są w https://firebase.google.com/docs/auth/admin/verify-id-tokens

Poniżej znajduje się fragment kodu mojego Authenticator:

'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, "https://stackoverflow.com/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"); 
     }); 
}; 

Nie jesteśmy w produkcji, jeszcze, ale testy na wystawie Authenticator, że zachowuje się poprawnie z Google Uwierzytelnianie Facebook i hasło jest bardzo szybkie (60-200 ms). Jedyną wadą, jaką widzę, jest to, że zostaniesz obciążony opłatą za funkcję lambda z uwierzytelnianiem, podczas gdy uwierzytelnianie zintegrowane Cognito jest bezpłatne.

+0

czy możesz podzielić się z innymi tym, dlaczego nie jesteś zadowolony z Cognito za uwierzytelnianie Facebooka/Google'a? – Alex

+0

Po prawie rocznej aktualizacji: - Odsunąłem się od niestandardowego wystawcy uwierzytelniającego Gateway API, głównie dlatego, że nie byłem w stanie zautomatyzować jego wdrożenia za pomocą skryptów Cloudformation. Moim rozwiązaniem jest teraz posiadanie uwierzytelnienia bezpośrednio w tokenach buforowania API przez pewien czas, tak jak robi to Authenticator, aby uniknąć nadmiernych walidacji. – pmosconi

3

Dokumentacja Aws jest dość zagmatwana. System wywołań zwrotnych dla różnych etapów uwierzytelniania jest lepiej udokumentowany w Firebase. Wynikiem jest czystszy kod i lepsza kontrola przepływu uwierzytelniania. Ponadto interfejs użytkownika Firebase jest bardziej przyjazny dla użytkownika. Jeśli planujesz korzystać z dostawców treści i synchronizowania kart, sugeruję użycie Firebase, ponieważ będziesz miał proste metody synchronizacji danych między lokalnym a zdalnym (Firebase) db

1

aws cognito daje więcej sposobów na uwierzytelnianie użytkowników niż baza ogniowa. Szczególnie, jeśli tworzysz grę, umożliwia ona logowanie się za pośrednictwem centrum gier Google i ios. Zapewnia synchronizację liderów i osiągnięć centrum gier. W Cognito dostępna jest automatyczna synchronizacja stanu. Ale na pewno jest to bardzo mylące. Realizacja wymaga zbyt wiele czasu. Z drugiej strony uwierzytelnianie firebase jest dość szybkie do wdrożenia.

9

TL; DR; Firebase> Cognito

Najpierw zaczęliśmy od Cognito, ale w końcu uświadomiliśmy sobie, że ma okropny zapach, gdy używa się tożsamości federacyjnych (np. Google Sign-in, Facebook Login itp.). W przypadku puli użytkowników Cognito (tj. Pozwalającej użytkownikowi na rejestrację/wprowadzanie przy użyciu nazwy użytkownika i hasła), można użyć wbudowanego interfejsu autoryzacji puli użytkowników interfejsu API Cognito Cognito i działa ona pięknie. Nie musisz pisać własnego niestandardowego autoryzatora ani niczego.

Jeśli jednak chcesz obsługiwać tożsamości federacyjne, musisz zmienić uwierzytelnianie na bramie interfejsu API na IAM Auth, a następnie KAŻDY klient musi podpisać żądania sigv4, co okazało się cierniem po naszej stronie i kosztem znaczny czas rozwoju. Opcja 2 polegała na generowaniu przez API Gateway kodu dla twoich wywołań API dla każdego klienta ... co moim zdaniem jest dowodem na kłopotliwą integrację z Cognito.

Usługa Firebase działa poprzez niestandardowy autoryzator bramy API. Był bryzą dla wszystkich klientów (iOS, Android i Web). Punkty końcowe bramki API zostały połączone z funkcjami Lambda, które mogły komunikować się z DynamoDB, S3 i innymi usługami sieciowymi w imieniu użytkownika wywołującego punkt końcowy. Funkcje lambda wiedziały, kto był wywołującym użytkownikiem, ponieważ niestandardowy autoryzator zwrócił adres e-mail w JWT.

Oto bardzo podstawowe Firebase zwyczaj Autoryzatora która zwraca e-mail użytkownika w JWT jako 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: '*' 
       } 
      ] 
     } 
    }; 
} 

Następnie można użyć $context.authorizer.principalId w API szablon mapowania Brama do pobierania wiadomości e-mail i przekazać go do lambda X.

+0

Dzięki za udostępnienie. Natrafiłem na blokadę drogi z Unity3d + Cognito, gdy zdałem sobie sprawę, że Pule użytkowników nie zostały tam zaimplementowane. Chciałbym wypróbować Firebase, ale nie przełączyć się całkowicie na Firebase lub GCP dla zaplecza, utrzymując bramkę AWS/API. Czy otrzymałeś także tożsamości federacyjne, np. Facebook i Google współpracują z Firebase + API Gateway? Jakieś przeszkody, które wpadłeś podczas tego? – dferraro

+1

Dostałem federacyjne tożsamości współpracujące z Firebase + API Gateway. Szczerze mówiąc, nie było nic konkretnego/niestandardowego, co musiałem zrobić po stronie zaplecza. Dla klientów upewnij się, że otrzymujesz JWT z Firebase po połączeniu tożsamości federacyjnej. Jeśli chcesz zobaczyć, jak to zrobiłem na kliencie iOS za pomocą Swift, daj mi znać, a ja opublikuję najważniejsze informacje. –

+0

@AzizCzy to jak opóźnienie wywoływania firebase auth z lambda, myślisz, że używanie Cognito byłoby znacznie szybsze, ponieważ jest to AWS? – Alex

1

W przypadku, gdy używasz Unity, obecnie Unity SDK nie obsługuje Cognito User Pool. (Oznacza to, że hostowana przez AWS lista użytkowników) obecnie się z tego powodu waham. Zobacz mój wpis here, który potwierdził, że to prawda, obecnie (26.06.2017) funkcja jest wciąż niedostępna, co może świadczyć o braku zainteresowania użytkowników Unity.

Jeśli jednak używam Bazy Firebase do logowania, potrzebowałbym więcej integracji tych danych uwierzytelniających, aby korzystać z usług AWS. (Chciałbym używać S3 i DynamoDB, ale tylko zalogowany użytkownik może z niego korzystać.) Uświadomiłem sobie również, że powinienem przenieść wszystko do Firebase, aby jak najszybciej zaoszczędzić czas i frustrację. (DB w czasie rzeczywistym jest droższe niż S3/DynamoDB, ale Unity ma własny zamiennik AWS MobileAnalytics)

AWS S3 uzyskał ostatnio ładniejszy interfejs użytkownika, który moim zdaniem jest bliski poziomu Google. Ale poza tym uważam, że interfejs użytkownika Firebase jest o wiele bardziej radosny w użyciu.

Autoryzacja Firebase jest bezpłatna, a Cognito jest dostępny do 50 000 aktywnych użytkowników miesięcznie. (Następnego 50k będzie kosztował 0,0055, co oznacza, jeśli masz 100k Mau to będzie 50000 * 0,0055 = 275 USD https://aws.amazon.com/cognito/pricing/)

Jeszcze jedna rzecz, AWS .NET documentation to koszmar do odczytu/wyszukiwanie w mojej opinii.

+1

Z łatwością mogłem używać S3 i DynamoDB z uwierzytelnianiem Firebase. Twój klient wywołuje punkt końcowy bramy API, który jest podpięty do lambda X, przekazując JWT z Firebase. Użytkownik weryfikuje token JWT w niestandardowym autoryzatorze, a następnie przekazuje wiadomość e-mail użytkownika do lambda X. Dopóki X ma dostęp do IAM do DynamoDB i S3, może uzyskać zasoby użytkownika i zwrócić je jako odpowiedź z bramy API. –