我有一个 AWS AppSync 架构,其默认授权模式设置为 Amazon Cognito 用户池。我使用 AWS Amplify GraphQL Client 从 Web 应用程序调用此 AppSync 端点,而且它的配置也将 Cognito 用户池作为身份验证类型:
aws_appsync_authenticationType: 'AMAZON_COGNITO_USER_POOLS'
当用户经过身份验证时,它会按预期工作;然而(尽管涉及的 Cognito 身份池已经设置了正确的 Auth 和 Unath 角色),当网站运行一些 Amplify fetch 命令时,例如针对未经身份验证的(来宾)用户:
const item = await API.graphql(graphqlOperation(getItem, { id: 'my-id' }))
最终抛出错误:
"No current user"
好吧,如果我允许未经身份验证的用户,我预计它会执行,但它只是失败了。为了寻找出路,我发现了一些讨论,例如:
而且,上述所有内容都建议重新访问 Amplify 配置,以便 AppSync 身份验证类型从
AMAZON_COGNITO_USER_POOLS
转换为 AWS_IAM
或 API_KEY
。但是,由于某些详细原因1:
AMAZON_COGNITO_USER_POOLS
身份验证类型,@aws_auth
装饰器之类的。有什么可能吗?
1 根据用户组(管理员、普通用户等),我可以通过 AppSync 架构上的
@aws_auth(cognito_groups: ["default-user-group"])
等装饰器进行更精细的控制。因此,我需要 Cognito 用户池来实现该用途。
所以,我刚刚经历了类似的问题并设法解决了它。我希望这可以帮助你解决这个问题。您在问题中提到的SO问题几乎是正确的方法。然而,有一个“小”小细节没有记录下来,我花了一段时间才找到。
除了必须通过运行
amplify update auth
(您可以在上面链接的SO中看到如何)启用经过身份验证和未经身份验证的访问之外,您还需要进行其他调整。
首先,在您的模型中,您需要将规则调整为:
@auth(
rules: [
# allow owners ability to update and delete their these messages (user pools)
{ allow: owner },
# allow all authenticated users to access this data
{ allow: private, provider: userPools },
# allow all guest users (not authenticated) to access this data
{ allow: public, provider: iam }
]
)
一旦您设置此模型以允许用户池访问他们“拥有”的所有数据,您还可以让任何“来宾”用户也访问数据。
在前端,让我们以您的代码为例,您需要使用一些不同的方法:
而不是
const item = await API.graphql(graphqlOperation(getItem, { id: 'my-id' }))
尝试类似的事情
// Check if the user is logged in or not
let isLoggedIn = await isLoggedIn();
const item = (await API.graphql({
query: getItem,
variables: { id: 'my-id' },
authMode: isLoggedIn ? GRAPHQL_AUTH_MODE.AMAZON_COGNITO_USER_POOLS : GRAPHQL_AUTH_MODE.AWS_IAM,
}));
顺便说一句,“isLoggedIn”函数看起来像这样
async function isLoggedIn() {
// Another way to get if its a guest or not
//return await Auth.Credentials.getCredSource() === "guest"
try {
await Auth.currentAuthenticatedUser();
return true;
} catch {
return false;
}
}
所以...这行代码就是它的作用,但并没有很好的记录。
authMode: isLoggedIn ? GRAPHQL_AUTH_MODE.AMAZON_COGNITO_USER_POOLS : GRAPHQL_AUTH_MODE.AWS_IAM
您需要根据用户的状态(登录或访客)来确定不同方法的路径,而不仅仅是 AWS_IAM。
这只会让您读取数据,以确保客人可以创建/更新/删除,并将数据所有权与彼此和登录用户分开,这是一个完全不同的故事,您需要开始挖掘解析器以对其进行排序。但好消息是,有办法:)
非常感谢!我只需要做一些更改即可使用 Amplify v6。
我还不知道这是否是完成这个常见用例的最佳方式。
import { generateClient } from "aws-amplify/api";
import { listProducts } from "../graphql/queries";
import { useEffect, useState } from "react";
import { Product } from "../API";
const client = generateClient();
import { getCurrentUser } from "aws-amplify/auth";
async function checkForUser() {
try {
const { username, userId, signInDetails } = await getCurrentUser();
console.log(`The username: ${username}`);
console.log(`The userId: ${userId}`);
console.log(`The signInDetails: ${signInDetails}`);
return true;
} catch (err) {
console.log(err);
return false;
}
}
const ListProducts = () => {
const [products, setProducts] = useState<Product[]>([]);
useEffect(() => {
fetchProducts();
}, []);
const fetchProducts = async () => {
const isLoggedIn = await checkForUser();
try {
const productsData = await client.graphql({
query: listProducts,
authMode: isLoggedIn ? "userPool" : "iam",
});
setProducts(productsData.data.listProducts.items);
} catch (error) {
console.error("error fetching products", error);
}
};