koa-shopify-auth redirect callback url

Highlighted
Tourist
7 0 2

Hey guys,

 

I am using "@shopify/koa-shopify-auth" for my application and I followed the Node/React tutorial, except I am not using next.js but separate node and react applications.

 

Locally, everything is working fine. But in production (I have each deployed to a different domain), I am getting a wrong redirect_url which has the hostname as my backend host instead of the frontend.

i.e. https://{BACKEND_HOSTNAME}/auth/callback

What might be the reason for this?

Thank you for your help.

1 Like
Highlighted

I would look into setting your env variables on the hosting platform. 

Here’s the docs for Heroku:

https://devcenter.heroku.com/articles/config-vars

0 Likes
Highlighted
Tourist
6 1 0

I have same problem. I followed the tutorial, everything works fine with localhost (use ngrok). But when I deploy the app to production and use real domain name for the app, it redirect to 

https://app-domain.com/admin/auth/authorize?state=xxx&scope=xxx&client_id=xxx&redirect_uri=https%3A%2F%2Flocalhost%3A3000%2Fauth%2Fcallback&grant_options%5B%5D=per-user

Finally end up with error: 

Expected a valid shop query parameter

 error2.pngerror1.png

Please advise. Thank you very much.

0 Likes
Highlighted
Tourist
6 1 0

Additional info: my app is hosted on a Windows server, using IIS as reverse proxy and pm2 to manage node processes.

0 Likes
Highlighted
Tourist
7 0 2

Hey kurt, 

I think your problem is different than mine. The redirect url appears as localhost in your case which I think is related to a problem in your code/setup.

And, what do you use for authentication? koa-shopify-auth?

0 Likes
Highlighted
Tourist
6 1 0

Yes, I use koa-shopify-auth.

 

0 Likes
Highlighted
Tourist
7 0 2

ok.

So for me, the issue was because koa-shopify-auth defaults the host of the redirect URL to the host of the request.

This host is changed by the reverse proxy. For me, I had to configure Nginx myself for it to work.

I also opened an issue to make this configurable.

0 Likes
Highlighted

You will probably need to change your HOST variable in your .env file at the root of your project. 

If we look inside the koa-shopify-auth package, we can see the following:

export default function createOAuthStart(
  options: OAuthStartOptions,
  callbackPath: string,
) {
  return function oAuthStart(ctx: Context) {
    const {myShopifyDomain} = options;
    const {query} = ctx;
    const {shop} = query;

    const shopRegex = new RegExp(
      `^[a-z0-9][a-z0-9\\-]*[a-z0-9]\\.${myShopifyDomain}$`,
      'i',
    );

    if (shop == null || !shopRegex.test(shop)) {
      ctx.throw(400, Error.ShopParamMissing);
      return;
    }

    ctx.cookies.set(TOP_LEVEL_OAUTH_COOKIE_NAME, '', getCookieOptions(ctx));

    const formattedQueryString = oAuthQueryString(ctx, options, callbackPath);

    ctx.redirect(
      `https://${shop}/admin/oauth/authorize?${formattedQueryString}`,
    );
  };
}

The redirect is being created in the oAuthQueryString module. If we take a look in that module, the redirect_uri is being created with your process.env.HOST variable, which is being propagated through the Koa context.

export default function oAuthQueryString(
  ctx: Context,
  options: OAuthStartOptions,
  callbackPath: string,
) {
  const {host, cookies} = ctx;
  const {scopes = [], apiKey, accessMode} = options;

  const requestNonce = createNonce();
  cookies.set('shopifyNonce', requestNonce, getCookieOptions(ctx));

  /* eslint-disable @typescript-eslint/camelcase */
  const redirectParams = {
    state: requestNonce,
    scope: scopes.join(', '),
    client_id: apiKey,
    redirect_uri: `https://${host}${callbackPath}`,
  };
  /* eslint-enable @typescript-eslint/camelcase */

  if (accessMode === 'online') {
    redirectParams['grant_options[]'] = 'per-user';
  }

  return querystring.stringify(redirectParams);
}

This is fine to have set as https://localhost:3000 when you're in dev mode, but in production, you'll need to change the environment variable in the production environment. I haven't used IIS in a long time, but I'm sure there's a way to set your HOST var to your production domain.

In Heroku, for example, you can set it within the web app for the deployment, or on the CLI.

Here's a screenshot of a production embedded app's config vars in Heroku:

Screen Shot 2020-08-24 at 11.31.27 AM.png

 

Hope that helps!

0 Likes
Highlighted
Tourist
7 0 2

hello @composed  thank you for your detailed reply.

 

Are you sure koa's host defaults to the environment variable and not the host from the request headers? Because I think that's the case.

0 Likes
Highlighted

Sure, np. You're right, the host is represented in ctx.request.header.host on requests, but for creating the callback it's pulling from process.env.HOST.

This is being set with the package dotenv and merged back into the process.env variables:

https://www.npmjs.com/package/dotenv

When you're running in production, the production host will need to configure this host by pulling from the config variables set on the hosting platform. You will want to mirror the same environment variables as in your .env file in dev, but use the production domain for the HOST.

So in the case of using the Shopify CLI, they are using ngrok to tunnel into the localhost from the outside. So the Shopify CLI will set process.env.HOST to the ngrok tunnel URL when it starts the server.

I had this problem when I deployed to Heroku, and had to change my Heroku config vars and it fixed the issue.

Also, if you are using Nextjs in the project, like what's generated in the Shopify CLI, you can access the env variables on the front end if necessary by prepending "NEXT_PUBLIC_" on the variable in the .env file.

https://nextjs.org/docs/basic-features/environment-variables

You can see the .env file set to the ngrok tunnel below:

Screen Shot 2020-08-24 at 12.00.53 PM.png

 

0 Likes