shopify-api-js icon indicating copy to clipboard operation
shopify-api-js copied to clipboard

CustomSessionStorage failed to store a session. Error Details: Error: ReplyError: NOAUTH Authentication require

Open kiranupadhyak opened this issue 2 years ago • 3 comments

Issue summary

I'm trying to build an app by using Redis CustomSessionStorage. I have referred to the below docs and implemented the same

https://github.com/Shopify/shopify-node-api/blob/main/docs/usage/customsessions.md#example-usage

it works fine with MemorySessionStorage, when I switch to CustomSessionStorage it shows a below error after clicking the install button.

Connected to REDIS...
(node:1130018) UnhandledPromiseRejectionWarning: Error: CustomSessionStorage failed to store a session. Error Details: Error: ReplyError: NOAUTH Authentication required
    at SessionStorageError.ShopifyError [as constructor] (../shopify/newapp/node_modules/@shopify/shopify-api/dist/error.js:13:28)
    at new SessionStorageError (../shopify/newapp/node_modules/@shopify/shopify-api/dist/error.js:172:42)
    at CustomSessionStorage.<anonymous> (../shopify/newapp/node_modules/@shopify/shopify-api/dist/auth/session/storage/custom.js:28:31)
    at step (../shopify/newapp/node_modules/tslib/tslib.js:143:27)
    at Object.throw (../shopify/newapp/node_modules/tslib/tslib.js:124:57)
    at rejected (../shopify/newapp/node_modules/tslib/tslib.js:115:69)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:1130018) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:1130018) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code

This is the redis-store.js class

const redis = require("redis");

class RedisStore {
  constructor() {
    this.client = redis.createClient({
      socket: {
          host: 'HOST_NAME',
          port: 12426,
          password: 'PASSWORD'
        }
      });


    this.client.on('error', (err) => console.log('Redis Client Error', err));

    this.client.on("connect", function() {
        console.error("Connected to REDIS...");
    });

    this.client.connect();
  }

  async storeCallback(session) {
    try {
      return await this.client.set(session.id, JSON.stringify(session));
    } catch (err) {
      throw new Error(err);
    }
  }

  async loadCallback(id) {
    try {
      let reply = await this.client.get(id);
      if (reply) {
        return JSON.parse(reply);
      } else {
        return undefined;
      }
    } catch (err) {
      throw new Error(err);
    }
  }

  async deleteCallback(id) {
    try {
      return await this.client.del(id);
    } catch (err) {
      throw new Error(err);
    }
  }
}


module.exports = RedisStore

This is server.js


const express = require('express');
const dotenv = require('dotenv');
const { Shopify, ApiVersion, ShopifyOAuth } =  require('@shopify/shopify-api');

const router = express.Router();

dotenv.config();

const {SHOPIFY_API_KEY, SHOPIFY_API_SECRET, SCOPES, HOST} = process.env
const RedisStore = require('../classes/redis-store');

const shops = {}

const sessionStorage = new RedisStore();

Shopify.Context.initialize({
	API_KEY: SHOPIFY_API_KEY,
	API_SECRET_KEY: SHOPIFY_API_SECRET,
	SCOPES: SCOPES.split(","),
	HOST_NAME: HOST.replace(/https:\/\/|\/$/g, ""),
	API_VERSION: ApiVersion.October20,
	IS_EMBEDDED_APP: true,
	SESSION_STORAGE: new Shopify.Session.CustomSessionStorage(
		sessionStorage.storeCallback.bind(sessionStorage),
    	sessionStorage.loadCallback.bind(sessionStorage),
    	sessionStorage.deleteCallback.bind(sessionStorage),
	),
});

router.get('/', async(req, res) => {
	const sessionId = await Shopify.Utils.loadCurrentSession(req, res, false);
	if (typeof shops[req.query.shop] != 'undefined') {
		res.render('index.twig');
	} else {
		res.redirect(`/auth?shop=${req.query.shop}`);
	}
})

router.get('/auth', async(req, res) => {
	const authRoute = await Shopify.Auth.beginAuth(
		req,
		res,
		req.query.shop,
		'/auth/callback',
		false,
	);
	res.redirect(authRoute);
});

router.get('/auth/callback', async(req, res, next) => {
	const shopSession = await Shopify.Auth.validateAuthCallback(
		req,
		res,
		req.query,
	);
	shops[shopSession.shop] = shopSession
	res.redirect(`https://${shopSession.shop}/admin/apps/newapp-174`)
});

module.exports = router

kiranupadhyak avatar Mar 08 '22 13:03 kiranupadhyak

The linked post helped me with something similar. In redis-store.js try adding client.auth(REDIS_PASSWORD) after port & hostname client. https://stackoverflow.com/questions/52433199/how-do-i-connect-my-app-to-redis-labs-server

technologytesting avatar Mar 08 '22 15:03 technologytesting

Thank you. I have added the client.auth(REDIS_PASSWORD) after the port & hostname client and it shows the The client is closed error.

...
constructor() {
    this.client = redis.createClient({
      socket: {
          host: HOST_NAME,
          port: 12426
        }
      });
    this.client.auth(PASSWORD)


    this.client.on('error', (err) => console.log('Redis Client Error', err));

    this.client.on("connect", function() {
        console.error("Connected to REDIS...");
    });

    this.client.connect();
  }
...
Listening on port 3000
(node:1136022) UnhandledPromiseRejectionWarning: Error: The client is closed
    at Commander._RedisClient_sendCommand (../shopify/newapp/node_modules/@node-redis/client/dist/lib/client/index.js:408:31)
    at Commander.commandsExecutor (../shopify/newapp/node_modules/@node-redis/client/dist/lib/client/index.js:166:154)
    at Commander.BaseClass.<computed> [as auth] (../shopify/newapp/node_modules/@node-redis/client/dist/lib/commander.js:8:29)
    at new RedisStore (../shopify/newapp/classes/redis-store.js:11:17)
    at Object.<anonymous> (../shopify/newapp/config/routes.js:14:24)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:12)
    at Module.require (internal/modules/cjs/loader.js:974:19)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:1136022) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:1136022) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
Connected to REDIS..

kiranupadhyak avatar Mar 08 '22 17:03 kiranupadhyak

i had the same problem but instead of using Redis npm package I used ioredis and it fixes error

import session from "express-session";
import connectRedis from "connect-redis";
import Redis from "ioredis";

let RedisStore = connectRedis(session);
let RedisStore = connectRedis(session);
let redisClient = new Redis({
  host: process.env.REDIS_URL,
  port: process.env.REDIS_PORT,
});


app.use(
  session({
    store: new RedisStore({
      client: redisClient,
    }),
    secret: process.env.SESSION_SECRET,
    resave: false,
    saveUninitialized: false,
    cookie: {
      secure: false,
      resave: false,
      saveUninitialized: false,
      httpOnly: true, // javascript can't access it
      maxAge: 300000,
    },
  })
);

johnmerga avatar Jun 18 '22 18:06 johnmerga

This issue is stale because it has been open for 90 days with no activity. It will be closed if no further action occurs in 14 days.

github-actions[bot] avatar Oct 06 '22 02:10 github-actions[bot]

We are closing this issue because it has been inactive for a few months. This probably means that it is not reproducible or it has been fixed in a newer version. If it’s an enhancement and hasn’t been taken on since it was submitted, then it seems other issues have taken priority.

If you still encounter this issue with the latest stable version, please reopen using the issue template. You can also contribute directly by submitting a pull request– see the CONTRIBUTING.md file for guidelines

Thank you!

github-actions[bot] avatar Oct 20 '22 02:10 github-actions[bot]