class SalesforceFlo::Authentication::OauthWrapper

Constants

DEFAULT_AUTH_HOST
DEFAULT_CLIENT_ID
DEFAULT_LISTEN_PORT
DEFAULT_REDIRECT_HOSTNAME
OAUTH_ENDPOINT

Public Class Methods

new(opts={}) click to toggle source

Creates a new OauthWrapper instance

@param [Hash] opts The options needed to create the provider @option opts [String] :client_id The client id of the connected app for Oauth authorization @option opts [String] :redirect_hostname (localhost:3835) The hostname portion of the uri that the user will be redirected to at the end of the Oauth authorization flow. This MUST match the redirect URL specified in the connected app settings. @option opts [String] :port (3835) The port that the user will be redirected to at the end of the Oauth @option opts [String] :auth_host (login.salesforce.com) The hostname where the user will be directed for

authentication.  This is useful if your org utilizes a custom domain.

flow. This will be appended to the redirect_hostname @option opts [#call] :client An object that produces a client when called with initialization options @raise [ArgumentError] If client object does not respond_to?(:call)

# File lib/salesforce_flo/authentication/oauth_wrapper.rb, line 35
def initialize(opts={})
  @client_id = opts.fetch(:client_id, DEFAULT_CLIENT_ID)
  @redirect_hostname = opts.fetch(:redirect_hostname, DEFAULT_REDIRECT_HOSTNAME)
  @port = opts.fetch(:port, DEFAULT_LISTEN_PORT)
  @auth_host = opts.fetch(:auth_host, DEFAULT_AUTH_HOST)
  @client = opts.fetch(:client, -> (options) { Restforce.new(options) })

  raise ArgumentError.new(':client must respond to #call, try a lambda') unless @client.respond_to?(:call)
end

Public Instance Methods

call(opts={}) click to toggle source

Starts a temporary webserver on the specified port, and initiates an Oauth authorization flow, which will redirect the user back to localhost on the specified port.

@param [Hash] opts Options that will be passed to the client when called, which will be merged with the response from the salesforce that includes the access token @return The result of invoking call on the client object

# File lib/salesforce_flo/authentication/oauth_wrapper.rb, line 51
def call(opts={})
  server = WEBrick::HTTPServer.new(Port: @port)
  auth_details = {}

  server.mount_proc('/') do |req, res|
    res.body = js_template
  end

  server.mount_proc('/send_token') do |req, res|
    auth_details = JSON.parse(req.body)
    res.body = 'token sent'

    server.shutdown # server will shutdown after completing the request
  end

  trap "INT" do server.shutdown end

  Launchy.open("#{@auth_host}#{OAUTH_ENDPOINT}?#{oauth_query_string}")
  server.start

  merged_options = opts.merge(auth_details).merge(client_id: @client_id, api_version: '39.0').inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
  merged_options[:oauth_token] = merged_options[:access_token] if merged_options[:access_token]
  @client.call(merged_options)
end

Private Instance Methods

js_template() click to toggle source
# File lib/salesforce_flo/authentication/oauth_wrapper.rb, line 86
      def js_template
        <<-TEMPLATE
          <html>
          <head></head>
          <body onload="sendHashParams()">
            OAuth authentication completed successfully.  This window will close shortly.
            <script>
              function getHashParams() {

                  var hashParams = {};
                  var e,
                      a = /\\+/g,  // Regex for replacing addition symbol with a space
                      r = /([^&;=]+)=?([^&;]*)/g,
                      d = function (s) { return decodeURIComponent(s.replace(a, " ")); },
                      q = window.location.hash.substring(1);

                  while (e = r.exec(q))
                     hashParams[d(e[1])] = d(e[2]);

                  return hashParams;
              }

              function sendHashParams() {
                xhr = new XMLHttpRequest();
                var url = "http://localhost:#{@port}/send_token";
                xhr.open("POST", url, true);
                xhr.setRequestHeader("Content-type", "application/json");
                var data = JSON.stringify(getHashParams());
                xhr.send(data);

                setTimeout(function() {
                  window.close;
                }, (10 * 1000))
              }
            </script>
          </body>
        </html>
        TEMPLATE
      end
oauth_query_string() click to toggle source
# File lib/salesforce_flo/authentication/oauth_wrapper.rb, line 78
def oauth_query_string
  query_string = URI.encode_www_form([['client_id', @client_id], ['response_type', 'token'], ['redirect_uri', redirect_uri]])
end
redirect_uri() click to toggle source
# File lib/salesforce_flo/authentication/oauth_wrapper.rb, line 82
def redirect_uri
  "http://#{@redirect_hostname}:#{@port}"
end