Как сохранить идентичность Cognito на страницах в браузере
Я аутентифицируюсь через Cognito в браузере на стороне клиента, используя идентификацию, аутентифицированную разработчиком. Когда моя страница загружается (или обновляется), я бы хотел, чтобы мое приложение запоминало Идентичность до тех пор, пока срок действия объекта не истек (думаю, он длится около часа). Однако я не знаю, как получить удостоверение из Cognito без необходимости повторной проверки подлинности разработчика.
Вот что делает код при загрузке страницы:
var cognitoCredentials
$(document).ready(function() {
"use strict";
cognitoParams = {
IdentityPoolId: 'us-east-1:xxxxxxx'
};
cognitoCredentials = new AWS.CognitoIdentityCredentials(cognitoParams);
AWS.config.credentials = cognitoCredentials;
});
И после входа в систему через аутентификацию разработчика:
cognitoCredentials.params.IdentityId = output.identityId;
cognitoCredentials.params.Logins = {
'cognito-identity.amazonaws.com': output.token
};
cognitoCredentials.expired = true;
Если я уже вошел в систему, а затем обновил страницу и попытался снова войти в систему, я получаю сообщение об ошибке, что я пытаюсь получить удостоверение личности, когда у меня уже есть
Error: Missing credentials in config(…) NotAuthorizedException: Missing credentials in config
"Access to Identity 'us-east-1:xxxxxxx' is forbidden."
Тем не менее, я не знаю, как получить к нему доступ. Как получить учетные данные, чтобы при обновлении страницы я мог обнаружить предыдущую идентификационную информацию, заданную Cognito?
Ответы
Ответ 1
Единственный способ вернуться к одному и тому же идентификатору при обновлении страницы - использовать тот же токен, который используется для инициализации этого идентификатора. Вы можете обратиться к этому вопросу, поскольку проблемы схожи (замена токена Facebook токеном OpenId Connect из потока аутентифицированных идентификаторов разработчика).
Чтобы повторить, что говорит этот вопрос: учетные данные в SDK не будут сохраняться на разных страницах, поэтому вы должны кэшировать токен, который будет повторно использоваться.
Ответ 2
Сохраните не менее accessKeyId, secretAccessKey, sessionToken
в sessionStorage
между страницами. Вы можете загрузить их в AWS.config.credentials(после загрузки AWS SDK, конечно). Это намного быстрее, чем ждать, когда Когнито ответит. Имейте в виду, вам придется вручную обновить их с помощью токена от одного из поставщиков, и это только хорошо, пока временный токен не истечет (~ 1 час).
var credKeys = [
'accessKeyId',
'secretAccessKey',
'sessionToken'
];
// After Cognito login
credKeys.forEach(function(key) {
sessionStorage.setItem(key, AWS.config.credentials[key]);
});
// After AWS SDK load
AWS.config.region = 'us-east-1'; // pick your region
credKeys.forEach(function(key) {
AWS.config.credentials[key] = sessionStorage.getItem(key);
});
// Now make your AWS calls to S3, DynamoDB, etc
Ответ 3
Я использую немного другой подход, который позволяет SDK обновлять учетные данные.
Короче говоря, я сериализую объект JSON AssumeRoleWithWebIdentityRequest
в хранилище сеансов.
Вот пример использования Angular, но концепция применима в любом приложении JS:
const AWS = require('aws-sdk/global');
import { STS } from 'aws-sdk';
import { environment } from '../../environments/environment';
const WEB_IDENT_CREDS_SS_KEY = 'ic.tmpAwsCreds';
// Handle tmp aws creds across page refreshes
const tmpCreds = sessionStorage.getItem(WEB_IDENT_CREDS_SS_KEY);
if (!!tmpCreds) {
AWS.config.credentials = new AWS.WebIdentityCredentials(JSON.parse(tmpCreds));
}
@Injectable({
providedIn: 'root'
})
export class AuthService {
...
async assumeAwsRoleFromWebIdent(fbUser: firebase.User) {
const token = await fbUser.getIdToken(false);
let p: STS.Types.AssumeRoleWithWebIdentityRequest = {
...environment.stsAssumeWebIdentConfig,
//environment.stsAssumeWebIdentConfig contains:
//DurationSeconds: 3600,
//RoleArn: 'arn:aws:iam::xxx:role/investmentclub-fbase-trust',
RoleSessionName: fbUser.uid + '@' + (+new Date()),
WebIdentityToken: token
};
// Store creds across page refresh, duno WTF 'new AWS.WebIdentityCredentials(p)' don't have an option for this
AWS.config.credentials = new AWS.WebIdentityCredentials(p);
sessionStorage.setItem(WEB_IDENT_CREDS_SS_KEY, JSON.stringify(p));
}
removeAwsTempCreds() {
AWS.config.credentials = {};
sessionStorage.removeItem(WEB_IDENT_CREDS_SS_KEY);
}
...
Несколько замечаний:
- После входа в систему я сохраняю параметры
WebIdentityCredentials
в виде строки JSON в кэше сеанса.
- Вы заметите, что я проверяю кэш сеанса браузера в глобальной области видимости, чтобы
обрабатывать обновления страниц (устанавливает кредиты, прежде чем их можно будет использовать).
Учебное пособие с полным примером можно найти в моем блоге.