X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/4c7323ea090e7570f962d821fa24c3ab20308e1e..4b4bb33aca0e12ae06bce395f02031890d6ef8bc:/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 a7391bd732..87967a40a5 100644 --- a/services/api/app/controllers/user_sessions_controller.rb +++ b/services/api/app/controllers/user_sessions_controller.rb @@ -1,6 +1,11 @@ +# Copyright (C) The Arvados Authors. All rights reserved. +# +# SPDX-License-Identifier: AGPL-3.0 + class UserSessionsController < ApplicationController - before_filter :require_auth_scope_all, :only => [ :destroy ] + before_filter :require_auth_scope, :only => [ :destroy ] + skip_before_filter :set_cors_headers skip_before_filter :find_object_by_uuid skip_before_filter :render_404_if_no_object @@ -9,18 +14,21 @@ class UserSessionsController < ApplicationController # omniauth callback method def create omniauth = env['omniauth.auth'] - #logger.debug "+++ #{omniauth}" 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.pretty_inspect():\n\n#{omniauth.pretty_inspect()}" + logger.error "omniauth: "+omniauth.pretty_inspect return redirect_to login_failure_url end - user = User.find_by_identity_url(omniauth['info']['identity_url']) + # 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 @@ -37,13 +45,28 @@ class UserSessionsController < ApplicationController end end end + + while (uuid = user.andand.redirect_to_user_uuid) + user = User.where(uuid: uuid).first + if !user + raise Exception.new("identity_url #{omniauth['info']['identity_url']} redirects to nonexistent uuid #{uuid}") + 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.new_users_are_active) + :is_active => Rails.configuration.new_users_are_active, + :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) + end else user.email = omniauth['info']['email'] user.first_name = omniauth['info']['first_name'] @@ -54,11 +77,14 @@ class UserSessionsController < ApplicationController end end + # For the benefit of functional and integration tests: + @user = user + # prevent ArvadosModel#before_create and _update from throwing # "unauthorized": Thread.current[:user] = user - user.save! + user.save or raise Exception.new(user.errors.messages) omniauth.delete('extra') @@ -86,13 +112,15 @@ class UserSessionsController < ApplicationController flash[:notice] = 'You have logged off' return_to = params[:return_to] || root_url - redirect_to "#{CUSTOM_PROVIDER_URL}/users/sign_out?redirect_uri=#{CGI.escape return_to}" + redirect_to "#{Rails.configuration.sso_provider_url}/users/sign_out?redirect_uri=#{CGI.escape return_to}" end # login - Just bounce to /auth/joshid. The only purpose of this function is # to save the return_to parameter (if it exists; see the application # controller). /auth/joshid bypasses the application controller. def login + auth_provider = if params[:auth_provider] then "auth_provider=#{CGI.escape(params[:auth_provider])}" else "" end + if current_user and params[:return_to] # Already logged in; just need to send a token to the requesting # API client. @@ -102,9 +130,9 @@ class UserSessionsController < ApplicationController send_api_token_to(params[:return_to], current_user) elsif params[:return_to] - redirect_to "/auth/joshid?return_to=#{CGI.escape(params[:return_to])}" + redirect_to "/auth/joshid?return_to=#{CGI.escape(params[:return_to])}&#{auth_provider}" else - redirect_to "/auth/joshid" + redirect_to "/auth/joshid?#{auth_provider}" end end @@ -115,7 +143,8 @@ class UserSessionsController < ApplicationController # Stub: automatically register all new API clients api_client_url_prefix = callback_url.match(%r{^.*?://[^/]+})[0] + '/' act_as_system_user do - @api_client = ApiClient.find_or_create_by_url_prefix api_client_url_prefix + @api_client = ApiClient. + find_or_create_by(url_prefix: api_client_url_prefix) end api_client_auth = ApiClientAuthorization. @@ -133,4 +162,8 @@ class UserSessionsController < ApplicationController callback_url += 'api_token=' + api_client_auth.api_token redirect_to callback_url end + + def cross_origin_forbidden + send_error 'Forbidden', status: 403 + end end