Shopify Hydrogen App Authentication

Solved

Shopify Hydrogen App Authentication

Hayk2002
New Member
6 0 0

Hey I am creating a shopify hydrogen app and currently want ot login form my local app. Unfortunaelty it shows up the mentioned error in the image. Looks like it redirects me to my account page where the error is being trigerred by remix loaders. 

Anyone has ever experienced integrating user auth flow in hydrogen app.

This is the link that the error page loads: 
https://shopify.com/authentication/60802433076/oauth/authorize?client_id=shp_429055a5-1cf3-4e9f-ad61...

Hayk2002_0-1746113885078.png

The following is my routes structure of account files:

Hayk2002_1-1746113942523.png

 



 

Accepted Solution (1)

fielde
Tourist
7 1 0

This is an accepted solution.

 

Create an .env file if you haven’t already:

 

env
CopyEdit
PUBLIC_APP_URL=http://localhost:3000 SHOPIFY_APP_API_KEY=your_api_key_here SHOPIFY_APP_SECRET=your_secret_here

 

 

In your app code:

 

ts
CopyEdit
const REDIRECT_URI = `${process.env.PUBLIC_APP_URL}/auth/callback`;

 

 

🔹 2. Route: app/routes/auth._authorize.tsx

Use this route to initiate OAuth:

 

tsx
CopyEdit
// app/routes/auth._authorize.tsx import { LoaderFunction, redirect } from "@remix-run/node"; export const loader: LoaderFunction = async ({ request }) => { const shop = new URL(request.url).searchParams.get("shop"); if (!shop) { return new Response("Missing shop parameter", { status: 400 }); } const redirectUri = `${process.env.PUBLIC_APP_URL}/auth/callback`; const oauthUrl = `https://${shop}/admin/oauth/authorize?client_id=${process.env.SHOPIFY_APP_API_KEY}&scope=read_products,write_orders&redirect_uri=${encodeURIComponent( redirectUri )}&state=noncevalue&grant_options[]=per-user`; return redirect(oauthUrl); };

 

 

🔹 3. Route: app/routes/auth.callback.tsx

This is where Shopify redirects after OAuth — here you handle the token exchange:

 

tsx
CopyEdit
// app/routes/auth.callback.tsx import { LoaderFunction, redirect } from "@remix-run/node"; export const loader: LoaderFunction = async ({ request }) => { const url = new URL(request.url); const shop = url.searchParams.get("shop"); const code = url.searchParams.get("code"); if (!shop || !code) { return new Response("Invalid callback params", { status: 400 }); } // Exchange code for token or do what your app needs here // Redirect to account or dashboard after successful auth return redirect("/account"); };

 

 

🛡 Bonus: Protect account._index.tsx Loader

Make sure your account._index.tsx loader checks that the user is authenticated before rendering:

 

tsx
CopyEdit
// app/routes/account._index.tsx import { LoaderFunction, redirect } from "@remix-run/node"; export const loader: LoaderFunction = async ({ request }) => { // Example: Check for session/token const user = await getUserFromSession(request); if (!user) { return redirect("/auth/authorize?shop=myshop.myshopify.com"); } return { user }; };
 

View solution in original post

Replies 3 (3)

fielde
Tourist
7 1 0

This is an accepted solution.

 

Create an .env file if you haven’t already:

 

env
CopyEdit
PUBLIC_APP_URL=http://localhost:3000 SHOPIFY_APP_API_KEY=your_api_key_here SHOPIFY_APP_SECRET=your_secret_here

 

 

In your app code:

 

ts
CopyEdit
const REDIRECT_URI = `${process.env.PUBLIC_APP_URL}/auth/callback`;

 

 

🔹 2. Route: app/routes/auth._authorize.tsx

Use this route to initiate OAuth:

 

tsx
CopyEdit
// app/routes/auth._authorize.tsx import { LoaderFunction, redirect } from "@remix-run/node"; export const loader: LoaderFunction = async ({ request }) => { const shop = new URL(request.url).searchParams.get("shop"); if (!shop) { return new Response("Missing shop parameter", { status: 400 }); } const redirectUri = `${process.env.PUBLIC_APP_URL}/auth/callback`; const oauthUrl = `https://${shop}/admin/oauth/authorize?client_id=${process.env.SHOPIFY_APP_API_KEY}&scope=read_products,write_orders&redirect_uri=${encodeURIComponent( redirectUri )}&state=noncevalue&grant_options[]=per-user`; return redirect(oauthUrl); };

 

 

🔹 3. Route: app/routes/auth.callback.tsx

This is where Shopify redirects after OAuth — here you handle the token exchange:

 

tsx
CopyEdit
// app/routes/auth.callback.tsx import { LoaderFunction, redirect } from "@remix-run/node"; export const loader: LoaderFunction = async ({ request }) => { const url = new URL(request.url); const shop = url.searchParams.get("shop"); const code = url.searchParams.get("code"); if (!shop || !code) { return new Response("Invalid callback params", { status: 400 }); } // Exchange code for token or do what your app needs here // Redirect to account or dashboard after successful auth return redirect("/account"); };

 

 

🛡 Bonus: Protect account._index.tsx Loader

Make sure your account._index.tsx loader checks that the user is authenticated before rendering:

 

tsx
CopyEdit
// app/routes/account._index.tsx import { LoaderFunction, redirect } from "@remix-run/node"; export const loader: LoaderFunction = async ({ request }) => { // Example: Check for session/token const user = await getUserFromSession(request); if (!user) { return redirect("/auth/authorize?shop=myshop.myshopify.com"); } return { user }; };
 
Hayk2002
New Member
6 0 0

Where exactly I should put the following:

const REDIRECT_URI = `${process.env.PUBLIC_APP_URL}/auth/callback`;

 

Hayk2002
New Member
6 0 0

Thanks for the hint, it worked.