Аутентификация Firebase против AWS Cognito
Мы создаем мобильное и веб-приложение на AWS с использованием API Gateway и Lambda и в настоящее время оцениваем, следует ли использовать все мобильные сервисы AWS (Cognito, Analytics, Mobile Hub и т.д.) или использовать вместо этого Firebase предлагает некоторые преимущества, такие как удаленная конфигурация).
Я думаю, что использование безфункционной части firebase, такой как Analytics, Remote Config, Crash Reports, Notification должно быть хорошо с бэкэндом AWS. Часть была я не уверен, это уровень аутентификации.
AWS Cognito прекрасно интегрируется в API Gateway и Lamdba, например. только аутентифицированные пользователи могут выполнять определенные вызовы API.
Может ли такое же поведение быть достигнуто, если мы будем использовать Firebase Authentication вместо этого?
Любой хороший или плохой опыт с этим?
Ответы
Ответ 1
мы делаем то же самое.
Мы начали с 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 мс).
Единственный недостаток, который я вижу, - это то, что вы будете платить за функцию лямбда-аутентификатора, а встроенный аутентификатор Cognito свободен.
Ответ 2
TL; DR; Firebase > Cognito
Сначала мы начали с Cognito, но в итоге мы поняли, что у него есть ужасный запах, когда он приходит с использованием Federated Identities (например, вход в Google, вход в систему Facebook и т.д.). Для пулов пользователей Cognito (т.е. Позволяя пользователю регистрироваться/вводиться с именем пользователя и паролем), вы можете использовать встроенный авторизованный пул пользователей Cognito API Gateway, и он прекрасно работает. Вам не нужно писать свой собственный авторизатор или что-то еще.
Однако, если вы хотите поддерживать Federated Identities, вам нужно изменить аутентификацию на своем шлюзе API на IAM Auth, а затем пусть каждый клиент sigv4 подпишет запросы, которые оказались шипами на нашей стороне и стоили значительных время разработки. Вариант 2 заключался в том, чтобы API Gateway генерировал код для ваших вызовов API для каждого клиента... который, на мой взгляд, является свидетельством громоздкой интеграции с Cognito.
Мы получили Firebase, работающую через специальный авторизатор для API Gateway. Был бриз для всех клиентов (iOS, Android и Web). Конечные точки API-шлюза были связаны с функциями Lambda, которые могли взаимодействовать с DynamoDB, S3 и другими веб-службами от имени пользователя, вызывающего конечную точку. Лямбда-функции знали, кто был вызывающим пользователем, потому что пользовательский авторизатор вернул адрес электронной почты в JWT.
Вот довольно простой пользовательский авторизатор Firebase, который возвращает пользовательский адрес электронной почты в JWT как mainId:
'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: '*'
}
]
}
};
}
Затем вы можете использовать $context.authorizer.principalId
в шаблоне сопоставления шлюза API, чтобы получить электронное письмо и передать его лямбда X.
Ответ 3
Документация Aws довольно запутана. Система обратных вызовов для разных этапов аутентификации лучше документирована в Firebase. Результатом является более чистый код и лучший контроль потока аутентификации. Кроме того, пользовательский интерфейс Firebase более удобен для пользователя. Если вы планируете использовать контент-провайдеры и адаптеры синхронизации, я бы предложил использовать Firebase, потому что у вас будут простые методы синхронизации данных между локальной и удаленной (Firebase) db
Ответ 4
aws cognito предоставляет больше возможностей для аутентификации пользователей, чем firebase. Особенно, если вы строите игру, она дает возможность входа в игровые центры google и ios. Он обеспечивает синхронизацию лидеров и достижения игрового центра. Функция автоматической синхронизации состояния доступна в Cognito. Но определенно, это очень запутанно. Для реализации требуется слишком много времени. С другой стороны, проверка подлинности с помощью firebase довольно быстро реализуется.
Ответ 5
На всякий случай, если вы используете Unity, в настоящее время Unity SDK не поддерживает Cognito User Pool. (То есть, список пользователей, размещенных в AWS). В настоящее время я не согласен с этим. См. Мой пост здесь, что они подтвердили, что это правда, в настоящее время (26/06/2017) функция по-прежнему недоступна, что может показать отсутствие внимание пользователей Unity от них.
Однако, если я использую Firebase для входа в систему, мне понадобится дополнительная интеграция для этих учетных данных для использования служб AWS. (Я хотел бы использовать S3 и DynamoDB, но только пользователь в системе может использовать его.) Это также заставило меня понять, что я должен переместить все в Firebase, чтобы как можно скорее сохранить время и разочарования. (БД реального времени более дорогая, чем S3/DynamoDB, но Unity имеет собственную замену AWS MobileAnalytics)
Недавно AWS S3 получил более удобный интерфейс, который, как мне кажется, близок к уровню Google. Но кроме этого я думаю, что Firebase UI гораздо радостнее использовать.
Кроме того, аутентификация Firebase бесплатна, а Cognito бесплатна до 50 000 активных пользователей в месяц. (Следующие 50k будут стоить 0,0055, что означает, что если у вас есть 100k MAU, это будет 50000 * 0.0055 = 275 USD https://aws.amazon.com/cognito/pricing/)
Еще одна вещь, Документация AWS.NET - это кошмар для чтения/поиска по моему мнению.