X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/29afa4d9270a8ca0ea7d9756589170b718135465..d11eb815d1722e50cf5308dc6e9d99e93d3228b7:/services/api/app/controllers/user_sessions_controller.rb diff --git a/services/api/app/controllers/user_sessions_controller.rb b/services/api/app/controllers/user_sessions_controller.rb index ef0f886866..85f32772b1 100644 --- a/services/api/app/controllers/user_sessions_controller.rb +++ b/services/api/app/controllers/user_sessions_controller.rb @@ -13,68 +13,29 @@ class UserSessionsController < ApplicationController # omniauth callback method def create - omniauth = request.env['omniauth.auth'] - - identity_url_ok = (omniauth['info']['identity_url'].length > 0) rescue false - unless identity_url_ok - # Whoa. This should never happen. - logger.error "UserSessionsController.create: omniauth object missing/invalid" - logger.error "omniauth: "+omniauth.pretty_inspect - - return redirect_to login_failure_url + if !Rails.configuration.Login.LoginCluster.empty? and Rails.configuration.Login.LoginCluster != Rails.configuration.ClusterID + raise "Local login disabled when LoginCluster is set" end - # Only local users can create sessions, hence uuid_like_pattern - # here. - user = User.unscoped.where('identity_url = ? and uuid like ?', - omniauth['info']['identity_url'], - User.uuid_like_pattern).first - if not user - # Check for permission to log in to an existing User record with - # a different identity_url - Link.where("link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?", - 'permission', - 'can_login', - omniauth['info']['email'], - User.uuid_like_pattern).each do |link| - if prefix = link.properties['identity_url_prefix'] - if prefix == omniauth['info']['identity_url'][0..prefix.size-1] - user = User.find_by_uuid(link.head_uuid) - break if user - end - end - end - end - - if not user - # New user registration - user = User.new(:email => omniauth['info']['email'], - :first_name => omniauth['info']['first_name'], - :last_name => omniauth['info']['last_name'], - :identity_url => omniauth['info']['identity_url'], - :is_active => Rails.configuration.Users.NewUsersAreActive, - :owner_uuid => system_user_uuid) - if omniauth['info']['username'] - user.set_initial_username(requested: omniauth['info']['username']) - end - act_as_system_user do - user.save or raise Exception.new(user.errors.messages) + if params[:provider] == 'controller' + if request.headers['Authorization'] != 'Bearer ' + Rails.configuration.SystemRootToken + return send_error('Invalid authorization header', status: 401) end + # arvados-controller verified the user and is passing auth_info + # in request params. + authinfo = SafeJSON.load(params[:auth_info]) else - user.email = omniauth['info']['email'] - user.first_name = omniauth['info']['first_name'] - user.last_name = omniauth['info']['last_name'] - if user.identity_url.nil? - # First login to a pre-activated account - user.identity_url = omniauth['info']['identity_url'] - end + # omniauth middleware verified the user and is passing auth_info + # in request.env. + authinfo = request.env['omniauth.auth']['info'].with_indifferent_access + end - while (uuid = user.redirect_to_user_uuid) - user = User.unscoped.where(uuid: uuid).first - if !user - raise Exception.new("identity_url #{omniauth['info']['identity_url']} redirects to nonexistent uuid #{uuid}") - end - end + begin + user = User.register(authinfo) + rescue => e + Rails.logger.warn "User.register error #{e}" + Rails.logger.warn "authinfo was #{authinfo.inspect}" + return redirect_to login_failure_url end # For the benefit of functional and integration tests: @@ -96,8 +57,6 @@ class UserSessionsController < ApplicationController user.save or raise Exception.new(user.errors.messages) - omniauth.delete('extra') - # Give the authenticated user a cookie for direct API access session[:user_id] = user.id session[:api_client_uuid] = nil @@ -151,13 +110,30 @@ class UserSessionsController < ApplicationController end p = [] p << "auth_provider=#{CGI.escape(params[:auth_provider])}" if params[:auth_provider] - if params[:return_to] - # Encode remote param inside callback's return_to, so that we'll get it on - # create() after login. - remote_param = params[:remote].nil? ? '' : params[:remote] - p << "return_to=#{CGI.escape(remote_param + ',' + params[:return_to])}" + + if !Rails.configuration.Login.LoginCluster.empty? and Rails.configuration.Login.LoginCluster != Rails.configuration.ClusterID + host = ApiClientAuthorization.remote_host(uuid_prefix: Rails.configuration.Login.LoginCluster) + if not host + raise "LoginCluster #{Rails.configuration.Login.LoginCluster} missing from RemoteClusters" + end + scheme = "https" + cluster = Rails.configuration.RemoteClusters[Rails.configuration.Login.LoginCluster] + if cluster and cluster['Scheme'] and !cluster['Scheme'].empty? + scheme = cluster['Scheme'] + end + login_cluster = "#{scheme}://#{host}" + p << "remote=#{CGI.escape(params[:remote])}" if params[:remote] + p << "return_to=#{CGI.escape(params[:return_to])}" if params[:return_to] + redirect_to "#{login_cluster}/login?#{p.join('&')}" + else + if params[:return_to] + # Encode remote param inside callback's return_to, so that we'll get it on + # create() after login. + remote_param = params[:remote].nil? ? '' : params[:remote] + p << "return_to=#{CGI.escape(remote_param + ',' + params[:return_to])}" + end + redirect_to "/auth/joshid?#{p.join('&')}" end - redirect_to "/auth/joshid?#{p.join('&')}" end def send_api_token_to(callback_url, user, remote=nil)