JohnSmith1976
JohnSmith1976

Reputation: 666

How to dynamically set the OmniAuth scope on runtime?

I have previously been pointed to OnmiAuth Dynamic Providers in order to switch provider on runtime, based on the visited domain. My solution is based on omniauth-shopify-oauth2 and this great answer:

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :shopify,
  scope: 'read_orders,read_products',
  setup: lambda { |env|
    request         = ActionDispatch::Request.new(env)
    subdomain       = "#{request.subdomain}" != "" ? "#{request.subdomain}." : ""
    domain          = "#{request.domain}"
    full_domain     = subdomain+domain
    shopify_client  = Rails.cache.fetch("#{full_domain}_shopify_client")

    env['omniauth.strategy'].options.merge!(
      {
        client_id:       shopify_client[:client_id],
        client_secret:   shopify_client[:client_secret]
      }
    )
    env['omniauth.strategy'].options[:client_options][:site] = "https://#{request.GET['shop']}"
  }
end

But now I also need to be able to set the scope dynamically. So "#{full_domain}_shopify_client" from the cache will contain an additional client_permissions key containing e.g. 'read_orders,read_products' or 'read_products'.

How do I refactor my code to be able to do this?

Upvotes: 1

Views: 1956

Answers (1)

cesartalves
cesartalves

Reputation: 1585

Here's a link which might help: https://github.com/Shopify/omniauth-shopify-oauth2/issues/60

I re-wrote your script in a way which seems to implement what you want. Add the 'scope' dynamically from the :client_permissions key

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :shopify,
  setup: lambda { |env|
    request         = ActionDispatch::Request.new(env)
    subdomain       = request.subdomain
    domain          = request.domain
    full_domain     = subdomain+domain
    shopify_client  = Rails.cache.fetch("#{full_domain}_shopify_client")

    env['omniauth.strategy'].options.merge!(
      {
        client_id:       shopify_client[:client_id],
        client_secret:   shopify_client[:client_secret],
        scope:           shopify_client[:client_permissions]
        client_options: {
          site: "https://#{request.GET['shop']}"
        },

      }
    )

end

If there's an Scope does not match, it may have been tampered with. error, you might have to setup the Rails.cache.fetch("#{full_domain}_shopify_client")[:client_permissions] in the session as well (session['shopify.oauth.scope']).

strategy = env['omniauth.strategy']
session = strategy.session.with_indifferent_access
env['omniauth.strategy'].options[:scope] = session['shopify.oauth.scope']

Inside your setup lambda.

Then, before redirecting to the oauth callback (from a controller, for example)

subdomain       = request.subdomain
domain          = request.domain
full_domain     = subdomain+domain
shopify_client  = Rails.cache.fetch("#{full_domain}_shopify_client")

session['shopify.oauth.scope'] = shopify_client[:client_permissions]

Upvotes: 3

Related Questions