使用 Firebase 进行 Shopify 身份验证?
Shopify Authentication Validation with Firebase?
我一直在关注 this 关于如何使用 Node、Nextjs 和 React 构建 public Shopify 应用程序的教程。
一切顺利,但我现在需要将一些应用程序数据存储在数据库中。为此,我选择了 Firestore。
我正在做的是当用户通过他们的商店验证应用程序时,我使用我的 Next JS 服务器中的 Admin-SDK 将他们的商店和 accessToken 写入文档:
Note: I'm using the accessMode "offline" as I need a permanent access token so that my app can make Shopify API requests in the background. I also know that I should really encrypt the accessToken before storing it, however just trying to get the logic working first
server.use(
createShopifyAuth({
apiKey: SHOPIFY_API_KEY,
secret: SHOPIFY_API_SECRET_KEY,
scopes: ['read_products', 'write_products'],
accessMode: "offline",
async afterAuth(ctx) {
const {shop, accessToken} = ctx.session;
ctx.cookies.set('shopOrigin', shop, {
httpOnly: false,
secure: true,
sameSite: 'none'
});
await getSubscriptionUrl(ctx, accessToken, shop);
await db.collection('shops').doc(shop).set({
name: shop,
accessToken
}, {merge: true});
},
}),
);
我还在使用 Koa 中间件来验证对我的应用程序的任何请求,以确保它们来自 Shopify 应用程序
server.use(verifyRequest());
我现在想做的是为我的应用程序添加一种从 Firebase 提取数据的方法。我在 /pages/api/firebase.js
中创建了一个 api 端点,它使用 shopOrigin
cookie 获取商店名称,然后提取该商店的数据。
export default async(req, res) => {
const shop = req.cookies.shopOrigin;
const doc = await db.collection('shops').doc(shop).get()
res.status(200).json({success: true, data: doc.data()});
}
我面临的问题是,用户可以简单地更改该 cookie 值并为另一家商店提取数据。 verifyRequest
函数似乎不检查调用它的 shopOrigin 名称是否来自调用它的商店。
有谁知道我如何验证这些请求,以便调用我的 API 的商店只能访问存储数据(通过下一个服务器上的 admin-sdk)?
考虑到这一点,我可以使用自定义身份验证方法。
在下一个 server.js 文件中,下面使用商店名称创建自定义令牌,然后将该令牌设置在 cookie 中。例如,它然后在 shops 集合中创建一个文档,文档 ID 作为商店名称。
async afterAuth(ctx) {
const {shop, accessToken} = ctx.session;
await getSubscriptionUrl(ctx, accessToken, shop);
const customToken = await admin.auth().createCustomToken(shop)
ctx.cookies.set('shopOrigin', shop, {
httpOnly: false,
secure: true,
sameSite: 'none'
});
ctx.cookies.set('token', customToken, {
httpOnly: false,
secure: true,
sameSite: 'none'
});
await db.collection('shops').doc(shop).set({
domain: shop,
token: cryptr.encrypt(accessToken),
}, {merge: true});
},
在 React 应用程序中,初始化您的 Firebase 应用程序实例,然后在 index.js 中侦听以查看 authState 是否更改或让用户使用令牌登录。
useEffect(() => {
firebase.auth().onAuthStateChanged(user => {
if(user) {
setSignedIn(true)
} else {
firebase.auth().signInWithCustomToken(Cookies.get('token'));
}
})
},[])
然后在 Firebase 规则中,根据需要设置您的权限
match /shops/{shop}/{documents=**} {
allow read, write: if request.auth != null && request.auth.uid == shop
}
我一直在关注 this 关于如何使用 Node、Nextjs 和 React 构建 public Shopify 应用程序的教程。
一切顺利,但我现在需要将一些应用程序数据存储在数据库中。为此,我选择了 Firestore。
我正在做的是当用户通过他们的商店验证应用程序时,我使用我的 Next JS 服务器中的 Admin-SDK 将他们的商店和 accessToken 写入文档:
Note: I'm using the accessMode "offline" as I need a permanent access token so that my app can make Shopify API requests in the background. I also know that I should really encrypt the accessToken before storing it, however just trying to get the logic working first
server.use(
createShopifyAuth({
apiKey: SHOPIFY_API_KEY,
secret: SHOPIFY_API_SECRET_KEY,
scopes: ['read_products', 'write_products'],
accessMode: "offline",
async afterAuth(ctx) {
const {shop, accessToken} = ctx.session;
ctx.cookies.set('shopOrigin', shop, {
httpOnly: false,
secure: true,
sameSite: 'none'
});
await getSubscriptionUrl(ctx, accessToken, shop);
await db.collection('shops').doc(shop).set({
name: shop,
accessToken
}, {merge: true});
},
}),
);
我还在使用 Koa 中间件来验证对我的应用程序的任何请求,以确保它们来自 Shopify 应用程序
server.use(verifyRequest());
我现在想做的是为我的应用程序添加一种从 Firebase 提取数据的方法。我在 /pages/api/firebase.js
中创建了一个 api 端点,它使用 shopOrigin
cookie 获取商店名称,然后提取该商店的数据。
export default async(req, res) => {
const shop = req.cookies.shopOrigin;
const doc = await db.collection('shops').doc(shop).get()
res.status(200).json({success: true, data: doc.data()});
}
我面临的问题是,用户可以简单地更改该 cookie 值并为另一家商店提取数据。 verifyRequest
函数似乎不检查调用它的 shopOrigin 名称是否来自调用它的商店。
有谁知道我如何验证这些请求,以便调用我的 API 的商店只能访问存储数据(通过下一个服务器上的 admin-sdk)?
考虑到这一点,我可以使用自定义身份验证方法。
在下一个 server.js 文件中,下面使用商店名称创建自定义令牌,然后将该令牌设置在 cookie 中。例如,它然后在 shops 集合中创建一个文档,文档 ID 作为商店名称。
async afterAuth(ctx) {
const {shop, accessToken} = ctx.session;
await getSubscriptionUrl(ctx, accessToken, shop);
const customToken = await admin.auth().createCustomToken(shop)
ctx.cookies.set('shopOrigin', shop, {
httpOnly: false,
secure: true,
sameSite: 'none'
});
ctx.cookies.set('token', customToken, {
httpOnly: false,
secure: true,
sameSite: 'none'
});
await db.collection('shops').doc(shop).set({
domain: shop,
token: cryptr.encrypt(accessToken),
}, {merge: true});
},
在 React 应用程序中,初始化您的 Firebase 应用程序实例,然后在 index.js 中侦听以查看 authState 是否更改或让用户使用令牌登录。
useEffect(() => {
firebase.auth().onAuthStateChanged(user => {
if(user) {
setSignedIn(true)
} else {
firebase.auth().signInWithCustomToken(Cookies.get('token'));
}
})
},[])
然后在 Firebase 规则中,根据需要设置您的权限
match /shops/{shop}/{documents=**} {
allow read, write: if request.auth != null && request.auth.uid == shop
}