Customer Account API error access denied

Shopify Partner
8 0 2

I'm trying to implement a passwordless authentication with the new Customer Account API in Next.js.

I'm facing problems in the local environment because when I get redirected, I get an access denied error.


The steps I'm following are these:


1) I have ngrok installed, and I create a "tunnel domain".


2) I enable the Customer Account API in the Shopify dashboard.

a) I set the client type to Public

b) I copy my client_id

c) I add the ngrok tunned domain to application setup, callback and javascript origin.


3) I defined the function to call when I click on my account button like this:


import { generateCodeVerifier } from "./verifierAndChallenge";
import { generateCodeChallenge } from "./verifierAndChallenge";

const loginCustomer = async (e) => {

  const loginUrl = new URL(`${process.env.NEXT_PUBLIC_SHOPIFY_ACCOUNT_API_URL}/auth/oauth/authorize`);

  loginUrl.searchParams.append("scope", "openid email");
  loginUrl.searchParams.append("client_id", process.env.NEXT_PUBLIC_SHOPIFY_CUSTOMER_ACCOUNT_ACCESS_TOKEN);
  loginUrl.searchParams.append("response_type", "code");
  loginUrl.searchParams.append("redirect_uri", ``);
  // For extra security use the following (must do, but later)
  // loginUrl.searchParams.append("state", await generateState());
  // loginUrl.searchParams.append("nonce", await generateNonce(25));

  // Public client
  const verifier = await generateCodeVerifier();
  const challenge = await generateCodeChallenge(verifier);
  localStorage.setItem("code-verifier", verifier);
  loginUrl.searchParams.append("code_challenge", challenge);
  loginUrl.searchParams.append("code_challenge_method", "S256");

  window.location.href = loginUrl.toString();

export default loginCustomer;


And the preceding code uses this one: 
export async function generateCodeVerifier() {
  const rando = generateRandomCode();
  return base64UrlEncode(rando);

export async function generateCodeChallenge(codeVerifier) {
  const digestOp = await crypto.subtle.digest({ name: "SHA-256" }, new TextEncoder().encode(codeVerifier));
  const hash = convertBufferToString(digestOp);
  return base64UrlEncode(hash);

function generateRandomCode() {
  const array = new Uint8Array(32);
  return String.fromCharCode.apply(null, Array.from(array));

function base64UrlEncode(str) {
  const base64 = btoa(str);
  // This is to ensure that the encoding does not have +, /, or = characters in it.
  return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");

function convertBufferToString(hash) {
  const uintArray = new Uint8Array(hash);
  const numberArray = Array.from(uintArray);
  return String.fromCharCode(...numberArray);
But when I click on the my account button, the url show this error:
And this is what the request looks like:
Captura de Pantalla 2024-02-20 a les 11.49.18.png

Could anyone point me in the right direction?

Thanks a lot!

Replies 2 (2)

Shopify Partner
4 0 0

I ran into the same issue, they replaced those Docs about a week ago on Friday. I started with the new docs and I am still getting the same unauthorized error.

Shopify Partner
4 0 0

I am now getting it work properly as the docs describe -

The step in the above docs around "Javascript Origins". Before this week there was only Callback URIs and Logout URIs, adding the correct URLs to the new Javascript Origins input made everything start working, except for the orders page. account/orders is broken on "status". 

The fix for account/orders is removing "status" from the end of this line: 

const fulfillmentStatus = flattenConnection(order.fulfillments)[0].status;
It's line 98 in the account/orders route. 

I also a noticed another new addition to the Shopify UI this morning for "Log Drains" - I really wish Shopify wouldn't say something is ready when it clearly isn't and they are filling in the pieces of the background.