FROM CACHE - en_header

verifyRequest() on post routes

Solved
GMKnight
Shopify Partner
72 7 31

Hi folks,

 

Examples using koa router show using verifyRequest() with get routes (get '*' catch all).

 

I've never seen examples of this being done on post / put / delete.

 

Should we not verifyRequest() on everything coming into the server?

The alternative app.use(verifyRequest()) indicates this to be the case?

 

GMKnight.

Store owner and app developer. Canada.
Accepted Solutions (2)

Accepted Solutions
tolgapaksoy
Shopify Partner
93 7 55

This is an accepted solution.

You most certainly should verify POST request.

 

This is how my server.js looks:

 

  router.get("*", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
    ctx.res.statusCode = 200;
  });
  router.post("*", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
  });
  router.patch("*", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
  });

View solution in original post

tolgapaksoy
Shopify Partner
93 7 55

This is an accepted solution.

Might as well dump my entire server.js here:

 

  router.get("/subscription/basic", verifyRequest(), async ctx => {
    const shopId = ctx.cookies.get("shopId");
    const subscriptionUrl = await getBasicUrl(ctx, shopId);

    ctx.redirect(subscriptionUrl);
  });
  router.get("/subscription/pro", verifyRequest(), async ctx => {
    const shopId = ctx.cookies.get("shopId");
    const subscriptionUrl = await getProUrl(ctx, shopId);

    ctx.redirect(subscriptionUrl);
  });

  const webhook = receiveWebhook({ secret: SHOPIFY_API_SECRET });
  router.post("/webhooks/app_subscriptions/update", webhook, async ctx => {
    const {
      payload: { app_subscription }
    } = ctx.state.webhook;
    await handleAppSubscriptionUpdate(app_subscription);

    ctx.respond = false;
    ctx.res.statusCode = 200;
  });

  router.get("*", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
    ctx.res.statusCode = 200;
  });
  router.post("*", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
  });
  router.patch("*", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
  });
  server.use(router.allowedMethods());
  server.use(router.routes());
  server.listen(port, () => {
    console.log(`> Ready on http://localhost:${port}`);
  });

So you can see that I have routes that precede the catchall routes.

View solution in original post

Replies 8 (8)
tolgapaksoy
Shopify Partner
93 7 55

This is an accepted solution.

You most certainly should verify POST request.

 

This is how my server.js looks:

 

  router.get("*", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
    ctx.res.statusCode = 200;
  });
  router.post("*", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
  });
  router.patch("*", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
  });
GMKnight
Shopify Partner
72 7 31

Hi @tolgapaksoy ,

 

This is what I have - it seemed implied in docs rather than implicitly specified.

 

Many thanks for the verification.

 

GMKnight.

Store owner and app developer. Canada.
GMKnight
Shopify Partner
72 7 31

Hi @tolgapaksoy ,

 

Although I want to look through the koa router source code later, just for my edification you might know:

 

We can do:

 

router.post( '/myroute', verifyRequest(), async ctx => { ... });

 

We can also do:

 

router.post('*', verifyRequest(), async ctx => { .. });

 

The former would precede the latter. We we saying that the verifyRequest() in the former post is redundant here? 

I am not clear about execution order I guess.

 

Many thanks for your knowledge prior to source code reading.

 

GMKnight.

Store owner and app developer. Canada.
GMKnight
Shopify Partner
72 7 31

Hi @tolgapaksoy ,

 

Very interesting - I have a very trivial setup with the '*' catchall for posts at the end of the code - and it doesn't get fired.

 

The get for '*' gets fired every time, the post never. 

 

I think I must be misunderstanding something but I'll debug later when I have a chance.

 

GMKnight.

Store owner and app developer. Canada.
tolgapaksoy
Shopify Partner
93 7 55

This is an accepted solution.

Might as well dump my entire server.js here:

 

  router.get("/subscription/basic", verifyRequest(), async ctx => {
    const shopId = ctx.cookies.get("shopId");
    const subscriptionUrl = await getBasicUrl(ctx, shopId);

    ctx.redirect(subscriptionUrl);
  });
  router.get("/subscription/pro", verifyRequest(), async ctx => {
    const shopId = ctx.cookies.get("shopId");
    const subscriptionUrl = await getProUrl(ctx, shopId);

    ctx.redirect(subscriptionUrl);
  });

  const webhook = receiveWebhook({ secret: SHOPIFY_API_SECRET });
  router.post("/webhooks/app_subscriptions/update", webhook, async ctx => {
    const {
      payload: { app_subscription }
    } = ctx.state.webhook;
    await handleAppSubscriptionUpdate(app_subscription);

    ctx.respond = false;
    ctx.res.statusCode = 200;
  });

  router.get("*", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
    ctx.res.statusCode = 200;
  });
  router.post("*", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
  });
  router.patch("*", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
  });
  server.use(router.allowedMethods());
  server.use(router.routes());
  server.listen(port, () => {
    console.log(`> Ready on http://localhost:${port}`);
  });

So you can see that I have routes that precede the catchall routes.

GMKnight
Shopify Partner
72 7 31

@tolgapaksoy ,

 

I really appreciate you posting. In fact this is what I did end up doing myself.... 

 

Many thanks, GMKnight!

Store owner and app developer. Canada.
rmking
New Member
2 0 2

You might need to update the path syntax slightly on newer versions

(.*) instead of just *

 

  router.post("(.*)", verifyRequest(), async ctx => {
    await handle(ctx.req, ctx.res);
    ctx.respond = false;
  });

 

If you get errors like 

UnhandledPromiseRejectionWarning: TypeError: Unexpected MODIFIER at 0, expected END

Fabrice3
Tourist
5 0 2

Hi there,

Please assist here, been stuck for a while...

 router.get("/recharge", verifyRequest(), async ctx => {
    
  ...
  ctx.redirect(rechargeUrl);
});

ctx.redirect does not work because of X-FRAME-OPTIONS.

Is there a hack to redirect at top level? In JS, it is simply window.top.location.href

 

Thanks in advance.