Search code examples
ruby-on-railsrubyshopifyx-frame-options

Not able to embed sites in an application in Shopify (X-Frame-Options)


I've been working on my first RoR/Shopify-application for the last couple of weeks and it is nearly finished. The only thing I'm having trouble with are the application charges. When a user sees my application in the store he clicks on "Get" and the authentication process is then initialized. The app is being installed and the user can Accept/Decline the charges. If he declines, he is redirected to my app listing in the store. Now here is my problem. If the user declines the fees my application is still installed and if he clicks on my banner a second time I need to check whether he is paying for it or not. I do it via

if (ShopifyAPI::RecurringApplicationCharge.current)
   some logic since the charge is valid
else 
   redirect_to billing_index_path(:shop_url => cur_shop_url)

My idea was to make the popup with the charging fees show up once again if the user hasn't paid yet. This doesn't work and I get an error saying that my site was not displayed because the X-Frame-Options are set to DENY. I've already tried to delete the options in my application_controller.rb and also in my application.rb using either

Response.headers.delete('X-Frame-Options') 

and

config.action_dispatch.default_headers.delete('X-Frame-Options') 

respectively. The first time the user installs the app everything seems to work, the embedding, the logic etc. but after he tries it a second time all hell breaks loose. How can I embed all the sites each time a user accesses my application? I read that Shopify's response has a DENY Header by default but I am sure that there must be a solution to this problem. I can't make a user uninstall the app every single time.

Thanks in advance


Solution

  • Shopify ignore 302's to their charge approval forms. The reason being, that your app is embedded in an iframe. The payment confirmation endpoint refuses to be embedded inside an iframe regardless of origin - they don't even whitelist their own site!!

    This means you CANNOT simply do a form post and 302 on success to the subscription confirmation url, that would be too easy.

    You MUST write some javascript that will take the confirmation url and perform window.top.location = confirm_url;.

    You MUST break out of the iframe or shopify will also deny you redirect capabilities and you'll be back where you were.

    Alternatively, you can open the link in a new window.

    I had to convert my 'quick and simple' app to make an Ajax call to submit the subscription information to my server, then do a JS redirect using the resulting confirmation url sent back.

    Have to say, Shopify's API is horrendously under-documented, and incredibly poorly implemented. At every turn their "API" puts up a roadblock.