Search code examples
ruby-on-railsoauthoauth-2.0shopifyomniauth

Switch provider for the omniauth-shopify-oauth2 gem in runtime?


The initializer for the omniauth-shopify-oauth2 gem is supposed to look like this:

# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :shopify, ENV['SHOPIFY_API_KEY'], ENV['SHOPIFY_SHARED_SECRET']
end

However, in our Rails app resides a few different brands who offers the same functionality. Throughout the entire app, the request.domain of a request determines which brand you are exposed to (brand1.example.com, brand2.example.com, etc.).

We can easily store brand specific credentials and redirect the users to the brand specific authorization path:

https://example.myshopify.com/admin/oauth/authorize?client_id=brand1&scope=read_orders,read_products&redirect_uri=https://brand1.example.com/auth/shopify/callback

But I can't figure out how we can have different providers for the middleware, chosen based on the visited request.domain. Any idea how to set this up?


Solution

  • Omniauth provides documentation on Dynamic Providers, which will be helpful here. Something like:

    # config/initializers/omniauth.rb
    Rails.application.config.middleware.use OmniAuth::Builder do
      provider :shopify, setup: lambda do |env|
    
        # Do logic to get correct credentials for request.
        # For example, if you store the credentials on a model called Brand,
        # and have it keyed on "subdomain":
        request = ActionDispatch::Request.new(env)
        brand = Brand.find_by(subdomain: request.subdomain)
    
        env['omniauth.strategy'].options.merge!({
          client_id: brand.client_id,
          client_secret: brand.client_secret
        })
    
        # `site` needs to be set. This is part of the shopify provider setup phase, which we are overriding
        env['omniauth.strategy'].options[:client_options][:site] = "https://#{ request.GET['shop'] }"
      end
    end