Shopify / shopify-app-js

MIT License
299 stars 120 forks source link

Shopify-app-remix doesn't handle authentication in custom callback (redirect-uri) #1554

Open gabriel-rye opened 2 months ago

gabriel-rye commented 2 months ago

Issue summary

Before opening this issue, I have:

Expected behavior

Im trying to complete the callback process on a custom auth callback. Using a custom installation link like

https://rye-gabriel-test.myshopify.com/admin/oauth/authorize?client_id=X&scope=unauthenticated_read_product_listings&redirect_uri=https://princeton-engineers-scenic-arrow.trycloudflare.com/api/auth/callback&state=123

Shopify will call /api/auth/callback but when calling const { session, admin, redirect } = await authenticate.admin(request); in this route breaks the auth process.

It looks like the auth process can't handle custom callback uri since it always /auth/callback, causing it to fail since

isAuthCallbackRequest: false
isAuthRequest: false

in respondToOAuthRequests for AuthCode Strategy can't handle custom callback uri. and in deriveConfig you override auth config.

My use is: I want to use the state parameter to do a custom logic during installation and I can only access it using custom redirect_uri and also need the session.

If I could have

const callbackResponse = await shopify.auth.callback({
        rawRequest: req,
        rawResponse: res,
      });

This available in remix would make life easier.

Actual behavior

What actually happens?

Steps to reproduce the problem

  1. trying to install a app using custom redirect_uri white listed in app
  2. on this custom route, call authenticate.admin.
  3. it will throw an odd error: [shopify-app/DEBUG] Authenticate returned a response with a 302

Debug logs

[shopify-app/DEBUG] Ensuring app is installed on shop | {shop: rye-gabriel-test.myshopify.com}
console.js:38
[Auth Callback logger] 20:33:08.901 INFO  Auth Params here:http://princeton-engineers-scenic-arrow.trycloudflare.com/api/auth/callback?code=d5e353bf0f7d9b744ce5d6c3326d01cd&hmac=5825f0408b88fcab87b4b7512ef42d103a571c1476a25cf88df7b9dceb82bcf2&host=YWRtaW4uc2hvcGlmeS5jb20vc3RvcmUvcnllLWdhYnJpZWwtdGVzdA&shop=rye-gabriel-test.myshopify.com&state=aqui&timestamp=1727134362aqui
console.js:38
[Auth Callback logger] 20:33:09.292 INFO  trying to authenticate admin
console.js:38
[shopify-app/INFO] Shop hasn't installed app yet, redirecting to OAuth | {shop: rye-gabriel-test.myshopify.com}
console.js:38
[shopify-api/INFO] Beginning OAuth | {shop: rye-gabriel-test.myshopify.com, isOnline: false, callbackPath: /auth/callback}
console.js:38
[shopify-api/DEBUG] OAuth started, redirecting to https://rye-gabriel-test.myshopify.com/admin/oauth/authorize?client_id=a07ff292325328eb3fe250b03659ddf1&scope=read_fulfillments%2Cread_inventory%2Cread_product_listings%2Cread_products%2Cread_shipping%2Cread_shopify_payments_accounts%2Cunauthenticated_read_product_listings%2Cwrite_checkouts%2Cwrite_discounts%2Cwrite_draft_orders%2Cwrite_orders%2Cwrite_resource_feedbacks%2Cwrite_returns&redirect_uri=https%3A%2F%2Fprinceton-engineers-scenic-arrow.trycloudflare.com%2Fauth%2Fcallback&state=923785303522789&grant_options%5B%5D= | {shop: rye-gabriel-test.myshopify.com, isOnline: false}
console.js:38
[shopify-app/DEBUG] Authenticate returned a response

it throws a 302 response error because it tries to ensureAppIsInstalled but it already is my guess.

gabriel-rye commented 2 months ago

Currently, my working around to make this work in remix is to instantiate another shopify-api client and use the methods.

matteodepalo commented 2 months ago

Hi @gabriel-rye, thank you for opening this issue, we'll take a look.

gabriel-rye commented 2 months ago

@matteodepalo, thanks! In general, we're looking for a way to get data when our users follow the installation link during the installation process. We currently use the installation link's state param and custom callback. But if somehow remix-shopify-app provides this param in the afterAuth or new hooks like: handleStateParamFromAuth or something would work.

tiagodreis commented 1 month ago

I'm having the exact same requirement / issue as @gabriel-rye . Any updates on this? having access to the param on afterAuth (or new hook as suggested) would be ideal. @gabriel-rye, can you expand on your workaround please? I'm currently having to call an API from MyApp, and pass the store host + accessToken - but I would also need to pass this state parameter coming from the custom installation URL

tiagodreis commented 1 month ago

OK - my approach was to save the custom parameter on a Prisma model and access it on afterAuth.

gabriel-rye commented 1 month ago

Hey folks! Yeah my approach was to save the state param since the normal flow would be to exist the iframe and get back with cookie set making the auth flow complete. In the afterAuth you check if there is a state attached in db to the shop if so, do the custom setup logic.

On Mon, 14 Oct 2024 at 10:12 Tiago Reis @.***> wrote:

OK - my approach was to save the custom parameter on a Prisma model and access it on afterAuth.

— Reply to this email directly, view it on GitHub https://github.com/Shopify/shopify-app-js/issues/1554#issuecomment-2411232219, or unsubscribe https://github.com/notifications/unsubscribe-auth/BJ5W4NTWYBYMBAFWZRDJIPDZ3O7NHAVCNFSM6AAAAABOXDOMV2VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMJRGIZTEMRRHE . You are receiving this because you were mentioned.Message ID: @.***>