App Installation Flow with Unlisted Public App

Solved
Highlighted
Tourist
14 0 2

Hi All.

I'm submitting an unlisted application.

The installation flow is as follows:

1. The user asks for the application at a third party website.

2. The user receives an e-mail with the installation link

3. User clicks the link, and inserts the shop domain name, and click on "install now"

4. Redirect to Shopify to confirm the app installation and proceed with the OAuth flow.

 

The OAuth flow itself works correctly, but I've been rejected, saying that I couldn't ask for a user's shop domain.

Being an unlisted app, I'm unsure on how to proceed, since I most definitely need a user's shop domain, I need my own "add app" button, since I have some custom information on my URL during the installation flow. 

0 Likes
Highlighted
Trailblazer
134 12 22

I think to get through the approval process you will need to make sure your app installs correctly as if a merchant were clicking Add App from the app store (I doubt there's any way around this given that this process is automated on Shopify's end).

So what that means is, let's say your app is hosted at myapp.herokuapp.com. When someone clicks on the install link, Shopify will automatically append hmac, timestamp and shopOrigin parameters - this is one way you can get the shop domain. So now their url becomes myapp.comherokuapp.com?hmac={hmac}&timestamp={timestamp}&shopOrigin={shopOrigin}. The way you can make sure this is working properly is when you use the "test on development store" link and install it on your development store, it will successfully go through OAuth. 

Once you've gotten your app approved, the best way is to actually just link them to your Shopify app store listing since that way they don't need to enter shop origin (which isn't an approved way to install an app, anyway). 

0 Likes
Highlighted
Tourist
14 0 2

Hi, maybe I wasn't clear.

My application installs correctly, and all works well in my development environment.

I have followed every single tutorial for developers from Shopify, one of which, explicitly says that "If your install link doesn’t originate from the Shopify App Store, then you need to provide the shop parameter yourself or implement other handling to get the user’s shop." Well that's exactly my case: it does not originate from Shopify App Store, and I give all the right parameters, I make the permission URL myself (for the OAuth2 flow) and all works well. 

Your example only mentions the case where the `install app` is from the App Store (again, which is not my case). So coming from outside the AppStore, would be expected to ask the user for it's shopDomain in order to generate the proper permission URL for the OAuth flow (in fact, would be the only way).

Screen Shot 2020-08-10 at 21.00.00.pngEven worth mentioning that even Shopify SDK for Python has a specific method to "generate permission URL" (which wouldn't make sense if Shopify was the only option to generate this URL).

0 Likes
Highlighted
Trailblazer
134 12 22

To confirm, when you installed it on your development store, you used the "install" button/link from your partners admin panel? I.e., you didn't manually generate a permission URL with the shopOrigin already present in the URL? 

0 Likes
Highlighted
Tourist
14 0 2

For my development store I followed exactly the same flow I expect my customers to follow:

  1. The user asks for the application at a third party website.
  2. The user receives an e-mail with a link to my website
  3. In my website the user inserts the shop domain name, and click on "install now" (this is what I use to generate the `permission URL`, which triggers the OAuth2 flow).
  4. Redirect to Shopify to confirm the app installation and proceed with the OAuth flow.

What I mean by that is that the permission URL (the "INSTALL" button link) is generated by me, in my website, as per this link, and this link, it should be possible normally: 

Those links explicitly say: "The installation process can be initiated with any web link" and ""If your install link doesn’t originate from the Shopify App Store, then you need to provide the shop parameter yourself or implement other handling to get the user’s shop."

1 Like
Highlighted
Trailblazer
134 12 22

It is certainly possible to install an app the way you want by generating a permission URL for the user. The problem is, Shopify's automated app review process tests the installation of your app as if a user is clicking the Add App button from your app listing (with the automatic appending of shop parameter, etc.). In my experience, the only way to confirm you will pass this process is to use the install button from the partner dashboard - if that works, then it will work with their bot as well. 

0 Likes
Highlighted
Tourist
14 0 2

Hmmm, ok, I see what you are saying.

So the approval flow I must be ready for is something like:

  1. Shopify bot clicks "install app"
  2. I get a request at  https://myapp.com/?oauth_params
  3. Redirect the user to the authorisation link like: https://{shop}.myshopify.com/admin/oauth......
  4. Follow OAuth flow, validate params, exchange code for token etc.

 

What is strange is that while generating the link on my end I use state={my_generated_nonce} for some internal validation (to make sure the link was generated by me). So if the installation request comes without state (which seems to be the case for Shopify tests), this should fail my validation. It seems that Shopify tests comes without this parameter, so considering what you are saying I should adapt my flow for the approval process and then stick with my initial flow?

 

 

0 Likes
Highlighted
Trailblazer
134 12 22

That's correct. Regarding state/nonce though, you can still append that to your OAuth permission URL since that's something you construct. So if your app is hosted at https://myapp.com:

  1. Bot clicks add app which will then hit your app with the URL https://myapp.com?hmac={hmac}&timestamp={timestamp}&shop={shopOrigin}

  2. Your own app logic will then detect that this merchant hasn't installed your app and redirect to your generated permission URL which can include state/nonce: https://{shop}.myshopify.com/admin/oauth/authorize?client_id={api_key}&scope={scopes}&redirect_uri={...

If you submit your app and you see that the bot installs and uninstalls your app, and more than 10-15 minutes passes and you don't get an automated rejection notice, then you can feel confident you made it past this stage. 

1 Like
Highlighted
Shopify Staff
Shopify Staff
587 72 130

Hey @policenauts1,

Couldn't have explained it better myself  

@wiretrackio thanks for posting this, I've seen this come up before and I'm wondering if we need to clarify the messaging when an app is automatically rejected. Can you confirm which messaging you were referring to when you said:

I've been rejected, saying that I couldn't ask for a user's shop domain

For clarity it's totally fine to ask for a shop's URL (if the shop param isn't provided). However your app will be rejected if the shop param is provided, and you ask for it anyways.

JB | Developer Support @ Shopify
 - Was my reply helpful? Click Like to let me know! 
 - Was your question answered? Click Accept as Solution 

0 Likes
Highlighted
Tourist
14 0 2

Hi _JB, thanks a lot for your attention.

So, there are a couple of interesting aspects about my case that I wasn't able to find an answer for. The exact message I got was the following:

"We were redirected to the  following page [this was a link to a screenshot of my page] when trying to install your app. The OAuth grant screen must be the first step in the installation process when trying to install the app. The app must never ask a merchant for their .myshopify.com URL. Please watch this example of what the required installation flow looks like. Please see this document for additional details. "

Just so you understand, my current flow is as follows:

  1. The users starts the flow in a third party web site (it's a ERP).
  2. I generate a link (with a token that I user internally), and a send it by email to the user (at this point, I don't know his store) - this is something like https://myapp.com/config?token=MYGENERATEDTOKEN
  3. The user clicks the link which takes him to my website
  4. In  my website (inside the /config route, so it's not the main application route) the user inputs their Shopify URL (I necessarily need to know the parameter to generate the Permission URL)
  5. I redirect the user to the Shopify permission page, starting the OAuth2 flow, just as the documentation says

This all seemed ok to me: the OAuth2 flow works perfectly, I get the token, I validade the parameters HMAC, timestamp etc, just as the documentation says. So now the funny thing is, the screenshot they sent me was for my login page (https://myapp.com) - so this page is NOT the installation page/path, it should only work for people who already have installed the application. So they surely did not use the link I've provided on my "Test Instructions", but as @policenauts1 said, they automatically append the parameters to application page: which surely doesn't work, because (1) it's not on the right installation path and (2) doesn't have my internally generated token. As the listing is in a forign language (and I wrote the instructions in that particular language, it could make sense that the test instructions were not read at all).

I understand how to append the state (nonce) field, but the thing is, this application has a certain context (API KEY and SECRET of another service, since it's an integration), so it doesn't make sense to allow the installation from anyone (that's why I made it unlisted, it's not something for every single Shopify user), so I need my own internally generated token (and that specific path URL with it's query params) to allow the user to proceed the installation.

Sorry if that's was too long. Does what I'm saying makes sense?

Would you shed some light on how should I proceed? Seems like I'm stuck and I can't see why/what I might me doing that's not compliant with Shopify's policy.

Thanks a bunch,

Best regards

Does that make sense to you?

1 Like