Repository: Shopify/shopify_app

Issue #618: [Docs request] Add concurrent access mode examples (offline & online auth)
Created: 2018-08-15T19:58:18Z
Overview
Shopify's OAuth API and Omniauth gem supports both offline and online access modes. We should provide a clear example of how to use them both, concurrently, in our apps. More specifically, how to setup online access for only the ShopifyApp::AuthenticatedController while still maintaining offline access for ShopifyApp::AppProxyVerification and ShopifyApp::WebhookVerification.
Previous discussions
This has been discussed before, see #580, but there has not been a clear solution moving forward. As of today, there aren't any public repos in Github implementing this either. From what I understood, you can build two Shopify tokens, one for offline and one for online, but I'm not sure how to scope them properly.
Examples
Here's an example of what I'm talking about:
Offline setup (default) <-- This works
AuthenticatedControllers, proxy app, and webhooks work properly, but you can't access individual user info on AuthenticatedControllers.
# config/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  # Offline access
  provider :shopify,
  ShopifyApp.configuration.api_key,
  ShopifyApp.configuration.secret,
  scope: ShopifyApp.configuration.scope,
  setup: lambda { |env|
    strategy = env['omniauth.strategy']

    shopify_auth_params = strategy.session['shopify.omniauth_params']&.with_indifferent_access
    shop = if shopify_auth_params.present?
      "https://#{shopify_auth_params[:shop]}"
    else
      ''
    end

    strategy.options[:client_options][:site] = shop
  }
end
Online setup <-- This works
AuthenticatedControllers work properly, but proxy app and webhooks are Unauthorized.
# config/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  # Online access
  provider :shopify,
  ShopifyApp.configuration.api_key,
  ShopifyApp.configuration.secret,
  scope: ShopifyApp.configuration.scope,
  per_user_permissions: true, # <-- this changed
  setup: lambda { |env|
    strategy = env['omniauth.strategy']

    shopify_auth_params = strategy.session['shopify.omniauth_params']&.with_indifferent_access
    shop = if shopify_auth_params.present?
      "https://#{shopify_auth_params[:shop]}"
    else
      ''
    end

    strategy.options[:client_options][:site] = shop
  }
end
Concurrent setup (offline & online) <-- How does this work?
Expected: AuthenticatedControllers, proxy app, and webhooks work properly, and you can access the Shopify user info on AuthenticatedControllers.
# config/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  # Offline access
  provider :shopify,
  ShopifyApp.configuration.api_key,
  ShopifyApp.configuration.secret,
  scope: ShopifyApp.configuration.scope,
  setup: lambda { |env|
    strategy = env['omniauth.strategy']

    shopify_auth_params = strategy.session['shopify.omniauth_params']&.with_indifferent_access
    shop = if shopify_auth_params.present?
      "https://#{shopify_auth_params[:shop]}"
    else
      ''
    end

    strategy.options[:client_options][:site] = shop
  }

  # Online access
  provider :shopify,
  ShopifyApp.configuration.api_key,
  ShopifyApp.configuration.secret,
  scope: ShopifyApp.configuration.scope,
  per_user_permissions: true,
  setup: lambda { |env|
    # ??? <-- Would this be different than the one above?
  }
end
Does this make sense? Or am I missing something obvious?
If someone has solved this in a way that is compatible with this gem, could you share it here? I'm willing to write the proper documentation once we've figured this out.
Things I've learned so far

You can generate a new session using the Shopify API directly. Could adding an around_action to the AuthenticatedController that finds or creates a new online access session work? Instead of using the Omniauth::Builder?
We need to toggle between the offline and online token headers depending on what kind of access a certain action requires. As seen on Shopify's OAuth instructions I believe we would have to set the proper token on each request.

Related Notes
IMO concurrent access should be the default behavior for this gem. It's one less configuration step, shouldn't break current implementations, is more secure for embedded apps, and would allow use of proxy apps, webhooks, and embedded apps with users (together) right from the get-go, which I feel is a common, and amazing, combination for apps.
Next steps
I'm opening this issue to see if I'm missing something before working on a potential solution. And if the feedback is positive, to see if anyone would like to help.
Thank you ❤️

Duplicate issue #872: Dual support for Shop-based and User-based authentication
Created: 2020-01-23T22:16:49Z
I'm really excited about the new support for User-based authentication in addition to Shop-based auth. However, after reading the docs with the new 11.5.1 release, it seems to me that it's an either/or situation, not both. It's important for most apps to create tokens that are permanent for background tasks, and know who's logged in. This is certainly possible since the API docs say so.
Are there any plans to add this or are there ways to implement this?

Closing comment (2020-01-23T22:20:35Z): Realizing this is a duplicate of #618