У меня есть приложение Amplify, использующее Cognito для аутентификации пула пользователей. После того как пользователь зарегистрировался и использовал код, отправленный по электронной почте (все функции Cognito), он передается в специальную форму, в которой фиксируется дополнительная информация. При отправке выполняется лямбда-функция, которая должна:
Лямбда-функция прекрасно развертывается как часть моей песочницы, и для allow.resource(createAccount).to(["manageGroups", "addUserToGroup", "manageGroupMembership"])}
были предоставлены разрешения, а также для изменения данных DynamoDB. Однако как только CognitoIdentityProviderClient
или await client.models.User.create(user)
нажимаются изнутри лямбда-функции, я получаю следующую ошибку от Graphql API No federated jwt
. Пример используемого кода:
const user = {
userId: userId,
...
};
const { data, errors} = await client.models.User.create(user); <-- `No federated jwt` error thrown here
Или
const cognitoClient = new CognitoIdentityProviderClient();
const userGroup = {
GroupName: `GroupName`,
Precedence: 1,
Description: `Description`,
UserPoolId: userPoolId,
};
const createCommand = new CreateGroupCommand(userGroup);
const response = await cognitoClient.send(createCommand ); <-- `No federated jwt` error thrown here
Примеры в документации Amplify Gen 2 не охватывают этот сценарий. Что мне не хватает?
Ошибка возникает в лямбде. Возможно, мне следует использовать другой подход для взаимодействия с Cognito и DynamoDB из лямбда-функции?
Я решил проблему с Cognito, используя следующий клиент: let cognito = new AWS.CognitoIdentityServiceProvider(); ...тогда ждите cognito.createGroup(readGroup, function(err, data) {..... Мне просто нужно решить, как получить доступ к DynamoDB с учетными данными IAM через эту сгенерированную функцию Amplify, и я дам ответ на этот вопрос проясняю неправильный подход, который я изначально использовал
Если модель данных пользователя настроена так, чтобы разрешать создание только владельцу или аутентифицированным пользователям, вам необходимо установить для параметра authMode для команды client.models.user.create значениеidentPool и передать пользовательский jwtToken. Токен можно получить из заголовка, если вы используете APIGateway для вызова лямбды. Если вы не используете шлюз API, вам придется передать его самостоятельно.
Вот пример данных
const schema = a.schema({
User: a
.model({
name: a.string(),
group: a.string(),
})
.identifier(["User"]),
})
.authorization((allow) => [allow.owner()]);
export type Schema = ClientSchema<typeof schema>;
export const data = defineData({
schema,
authorizationModes: {
defaultAuthorizationMode: "identityPool",
},
});
А вот пример лямбды, вызываемой с использованием APIGateway
export const handler: APIGatewayProxyHandler = async (event) => {
let jwtToken: string | undefined;
// Method 1: From JWT authorizer claims
jwtToken = event.requestContext.authorizer?.jwt?.claims?.['id_token'] as string;
// Method 2: From Authorization header (if token is passed in header)
if (!jwtToken) {
const authHeader = event.headers['Authorization'];
jwtToken = authHeader;
}
if (jwtToken) {
console.info('jwtToken found:', jwtToken);
// Use the jwtToken as needed
} else {
console.info('jwtToken not found in the request');
}
const client = generateClient<Schema>({
authMode: "identityPool",
authToken: jwtToken,
});
const createStoryResult = await client.models.User.create({
name: "foo",
group: "Bar",
},
{
authMode: "identityPool",
authToken: jwtToken,
});
Спасибо, Эндрю, добавление токена JWT помогло. У меня он находился в немного другом месте, в event.request.headers['authorization']
Где возникает ошибка? внутри Lambda или при вызове Lambda из внешнего интерфейса?