module MnoEnterprise::Concerns::Controllers::Auth::OmniauthCallbacksController
This controller is used to handle the authentication (+creation) of external users via OpenID (e.g: QuickBooks OpenID)
When users click on the “sign in with <provider>” button, they get redirected to the authorize endpoint (/users/auth/:provider - e.g: /users/auth/intuit). The action (handled by parent controller OmniauthCallbacksController
) prepares the callback url then redirects the user to the OpenID provider (E.g: Intuit) for authentication.
Once authentication has been performed at the OpenID provider level (e.g: Intuit) the user gets redirected to the callback endpoint (/users/auth/:provider/callback) The provider parameter in the url (E.g: intuit) gets automatically redirected to a controller action with the same name (handled by parent controller OmniauthCallbacksController
) as you can see below with intuit.
Then provider specific action then handles the (creation +) authentication of the user. Also, it automatically adds the right applications to the user dashboard (e.g: QuickBooks for Intuit)
Intuit:
For intuit, the authorize endpoint is be bypassed when the user clicks “try Maestrano” from the Intuit marketplace. The user automatically lands on the callback endpoints with a parameter in the url called 'qb_initiated'. This parameter is used to automatically trigger the retrieval of the oauth token in the background via javascript (by storing the temporary grant url in session)
On Intuit, it is also possible to directly choose one of the apps proposed by Maestrano (E.g: 'SugarCRM by Maestrano'). In this case, an 'app' attribute containing the app nid (named id - e.g: 'sugarcrm') is added to the url parameters. The action then setup the app automatically (along with QuickBooks).
Public Instance Methods
¶ ↑
Instance methods
¶ ↑
GET|POST /users/auth/:action/callback
# File lib/mno_enterprise/concerns/controllers/auth/omniauth_callbacks_controller.rb, line 76 def intuit auth = request.env['omniauth.auth'] opts = { orga_on_create: create_orga_on_user_creation(auth.info.email), authorized_link_to_email: session['omniauth.intuit.authorized_link_to_email'] } # Try to find via intuit begin @user = MnoEnterprise::User.find_for_oauth(auth, opts, current_user) rescue SecurityError # Intuit email is NOT a confirmed email. Therefore we need to ask the user to # login the old fashion to make sure it is the right user! session["omniauth.intuit.request_account_link"] = true redirect_to new_user_session_path, notice: "Please sign in using your regular Maestrano account to confirm that you want to link it to your Intuit account" return end # Cleanup any temporary omniauth.intuit session cleanup_intuit_session if @user && @user.persisted? # Automatically adds a QuickBooks app (and any other app passed via :app param) # to the user orga # Only for new users for which an orga was created (not an invited user # typically) app_instances = setup_apps(@user,['quickbooks',params[:app]], oauth_keyset: params[:app]) qb_instance = app_instances.first # On Intuit, Mno is configured to add qb_initiated=true if the user # comes directly from apps.com (This is a different workflow from using # the QuickBooks connect button because we're supposed to trigger the # oauth workflow directly via javascript using directConnectToIntuit) # Here we store in session the fact that we need to trigger an oauth # workflow via directConnectToIntuit # ---- # See layouts/partners/intuit for more info. The session param set # below get reset in the view. # if params[:qb_initiated] && qb_instance && !qb_instance.oauth_keys_valid? session[:qb_direct_connect_grant_url] = authorize_webhook_oauth_url(qb_instance.uid) end # The above methods trigger many different hooks which # may impact the user (typically user workspace). It is safer # to reload the user before continuing so that the picture # is up to date @user.reload # Check whether we should redirect the user to a specific # url redirect_url = session.delete(:openid_previous_url) || MnoEnterprise.router.dashboard_path || main_app.root_path sign_in @user redirect_to redirect_url, event: :authentication set_flash_message(:notice, :success, kind: "Intuit") if is_navigational_format? else session["devise.intuit_data"] = request.env["omniauth.auth"] redirect_to home_url, "ng-controller" => "MnoSignupProcessCtrl", "ng-click" => "startProcess()" end end
Private Instance Methods
Whether to create an orga on user creation
# File lib/mno_enterprise/concerns/controllers/auth/omniauth_callbacks_controller.rb, line 150 def create_orga_on_user_creation(user_email = nil) return false if user_email.blank? return false if MnoEnterprise::User.exists?(email: user_email) # First check previous url to see if the user # was trying to accept an orga if !session[:previous_url].blank? && (r = session[:previous_url].match(/\/orga_invites\/(\d+)\?token=(\w+)/)) invite_params = { id: r.captures[0].to_i, token: r.captures[1] } return false if OrgInvite.where(invite_params).any? end # Get remaining invites via email address return MnoEnterprise::OrgInvite.where(user_email: user_email).empty? end
Create or find the apps provided in argument Accept an array of app nid (named id - e.g: 'quickbooks') opts:
oauth_keyset: If a oauth_keyset is provided then it will be added to the
oauth_keys of any app that is oauth ready (QuickBooks for example)
Return an array of app instances (found or created)
# File lib/mno_enterprise/concerns/controllers/auth/omniauth_callbacks_controller.rb, line 172 def setup_apps(user = nil, app_nids = [], opts = {}) return [] unless user return [] unless (user.organizations.reload.count == 1) return [] unless (org = user.organizations.first) return [] unless MnoEnterprise::Ability.new(user).can?(:edit,org) results = [] apps = MnoEnterprise::App.where('nid.in' => app_nids.compact) existing = org.app_instances.active.index_by(&:app_id) # For each app nid (which is not nil), try to find an existing instance or create one apps.each do |app| if (app_instance = existing[app.id]) results << app_instance else # Provision instance and add to results app_instance = org.app_instances.create(product: app.nid) results << app_instance MnoEnterprise::EventLogger.info('app_add', user.id, 'App added', app_instance) end # Add oauth keyset if defined and app_instance is # oauth ready and does not have a valid set of oauth keys if app_instance && opts[:oauth_keyset].present? && !app_instance.oauth_keys_valid? app_instance.oauth_keys = { keyset: opts[:oauth_keyset] } app_instance.save end end return results end