Focuses on API authentication, access scopes, and permission management.
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) => { e.preventDefault(); const loginUrl = new URL(`${process.env.NEXT_PUBLIC_SHOPIFY_ACCOUNT_API_URL}/auth/oauth/authorize`); loginUrl.searchParams.append("scope", "openid email https://api.customers.com/auth/customer.graphql"); 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", `https://f501-90-166-179-8.ngrok-free.app/authorize`); // 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;
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); crypto.getRandomValues(array); 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); }
Could anyone point me in the right direction?
Thanks a lot!
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. https://shopify.dev/docs/custom-storefronts/building-with-the-customer-account-api/hydrogen
I am now getting it work properly as the docs describe - https://shopify.dev/docs/custom-storefronts/building-with-the-customer-account-api/hydrogen
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:
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.
@marnau We're you able to resolve this or find a work around. I'm running into similar issues.
Yes, I did manage to get it to work. I couldn't have done it without this wonderful repository as a reference: https://github.com/osseonews/commerce/tree/customer
At the end of the readme you'll see where he implements all the customer account functionality : )
Finally a break in the case! Thank you so much.