Class: ShopifyAPI::Session

Inherits:
Object
  • Object
show all
Defined in:
lib/shopify_api.rb

Overview

The Shopify API authenticates each call via HTTP Authentication, using

  * the application's API key as the username, and
  * a hex digest of the application's shared secret and an 
    authentication token as the password.

Generation & acquisition of the beforementioned looks like this:

  0. Developer (that's you) registers Application (and provides a
     callback url) and receives an API key and a shared secret

  1. User visits Application and are told they need to authenticate the
     application first for read/write permission to their data (needs to
     happen only once). User is asked for their shop url.

  2. Application redirects to Shopify : GET <user's shop url>/admin/api/auth?api_key=<API key>
     (See Session#create_permission_url)

  3. User logs-in to Shopify, approves application permission request

  4. Shopify redirects to the Application's callback url (provided during
     registration), including the shop's name, and an authentication token in the parameters:
       GET client.com/customers?shop=snake-oil.myshopify.com&t=a94a110d86d2452eb3e2af4cfb8a3828

  5. Authentication password computed using the shared secret and the
     authentication token (see Session#computed_password)

  6. Profit!
     (API calls can now authenticate through HTTP using the API key, and
     computed password)

LoginController and ShopifyLoginProtection use the Session class to set Shopify::Base.site
so that all API calls are authorized transparently and end up just looking like this:

  # get 3 products
  @products = ShopifyAPI::Product.find(:all, :params => {:limit => 3})

  # get latest 3 orders
  @orders = ShopifyAPI::Order.find(:all, :params => {:limit => 3, :order => "created_at DESC" })

As an example of what your LoginController should look like, take a look
at the following:

  class LoginController < ApplicationController
    def index
      # Ask user for their #{shop}.myshopify.com address
    end

    def authenticate
      redirect_to ShopifyAPI::Session.new(params[:shop]).create_permission_url
    end

    # Shopify redirects the logged-in user back to this action along with
    # the authorization token t.
    # 
    # This token is later combined with the developer's shared secret to form
    # the password used to call API methods.
    def finalize
      shopify_session = ShopifyAPI::Session.new(params[:shop], params[:t])
      if shopify_session.valid?
        session[:shopify] = shopify_session
        flash[:notice] = "Logged in to shopify store."

        return_address = session[:return_to] || '/home'
        session[:return_to] = nil
        redirect_to return_address
      else
        flash[:error] = "Could not log in to Shopify store."
        redirect_to :action => 'index'
      end
    end

    def logout
      session[:shopify] = nil
      flash[:notice] = "Successfully logged out."

      redirect_to :action => 'index'
    end
  end

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url, token = nil, params = nil) ⇒ Session

Returns a new instance of Session.



131
132
133
134
135
136
137
138
139
140
141
# File 'lib/shopify_api.rb', line 131

def initialize(url, token = nil, params = nil)
  self.url, self.token = url, token

  if params
    unless self.class.validate_signature(params) && params[:timestamp].to_i > 24.hours.ago.utc.to_i
      raise "Invalid Signature: Possible malicious login" 
    end
  end

  self.class.prepare_url(self.url)
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



125
126
127
# File 'lib/shopify_api.rb', line 125

def name
  @name
end

#tokenObject

Returns the value of attribute token.



125
126
127
# File 'lib/shopify_api.rb', line 125

def token
  @token
end

#urlObject

Returns the value of attribute url.



125
126
127
# File 'lib/shopify_api.rb', line 125

def url
  @url
end

Class Method Details

.setup(params) ⇒ Object



127
128
129
# File 'lib/shopify_api.rb', line 127

def self.setup(params)
  params.each { |k,value| send("#{k}=", value) }
end

Instance Method Details

#create_permission_urlObject



147
148
149
150
# File 'lib/shopify_api.rb', line 147

def create_permission_url
  return nil if url.blank? || api_key.blank?
  "http://#{url}/admin/api/auth?api_key=#{api_key}"
end

#shopObject



143
144
145
# File 'lib/shopify_api.rb', line 143

def shop
  Shop.current
end

#siteObject

Used by ActiveResource::Base to make all non-authentication API calls

(ShopifyAPI::Base.site set in ShopifyLoginProtection#shopify_session)



155
156
157
# File 'lib/shopify_api.rb', line 155

def site
  "#{protocol}://#{api_key}:#{computed_password}@#{url}/admin"
end

#valid?Boolean

Returns:

  • (Boolean)


159
160
161
# File 'lib/shopify_api.rb', line 159

def valid?
  url.present? && token.present?
end