Shopify Проверка подлинности с помощью Firebase? - PullRequest
2 голосов
/ 19 июня 2020

Я следил за этим руководством по созданию приложения publi c Shopify с использованием Node, Next js и React.

Все идет хорошо, но я сейчас я нахожусь в точке, где мне нужно сохранить некоторые данные моего приложения в базе данных. Для этого я выбрал Firestore.

То, что я делаю, это когда пользователь аутентифицирует приложение в своем магазине, я использую Admin-SDK на моем сервере Next JS для записи своего магазина и accessToken в документ:

Примечание. Я использую режим доступа "offline", поскольку мне нужен постоянный токен доступа, чтобы мое приложение могло выполнять запросы Shopify API в фоновом режиме. Я также знаю, что мне действительно нужно зашифровать accessToken перед его сохранением, но я просто пытаюсь заставить logi c работать первым

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. Я создал конечную точку api в /pages/api/firebase.js, которая использует shopOrigin cook ie для получения имени магазина, а затем извлекает данные для этого магазина.

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 на сервере Next)?

1 Ответ

2 голосов
/ 20 июня 2020

Подумав об этом, я могу использовать собственный метод аутентификации.

На следующем сервере. js файл, приведенный ниже файл создает специальный токен, используя название магазина, а затем устанавливает этот токен в Cook ie. Например, он затем создает документ в коллекции магазинов с идентификатором документа в качестве имени магазина.

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, а затем в индексе. 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
}
...