1 class UserSessionsController < ApplicationController
2 before_filter :require_auth_scope, :only => [ :destroy ]
4 skip_before_filter :find_object_by_uuid
5 skip_before_filter :render_404_if_no_object
9 # omniauth callback method
11 omniauth = env['omniauth.auth']
13 identity_url_ok = (omniauth['info']['identity_url'].length > 0) rescue false
14 unless identity_url_ok
15 # Whoa. This should never happen.
16 logger.error "UserSessionsController.create: omniauth object missing/invalid"
17 logger.error "omniauth.pretty_inspect():\n\n#{omniauth.pretty_inspect()}"
19 return redirect_to login_failure_url
22 user = User.find_by_identity_url(omniauth['info']['identity_url'])
24 # Check for permission to log in to an existing User record with
25 # a different identity_url
26 Link.where("link_class = ? and name = ? and tail_uuid = ? and head_uuid like ?",
29 omniauth['info']['email'],
30 User.uuid_like_pattern).each do |link|
31 if prefix = link.properties['identity_url_prefix']
32 if prefix == omniauth['info']['identity_url'][0..prefix.size-1]
33 user = User.find_by_uuid(link.head_uuid)
40 # New user registration
41 user = User.new(:email => omniauth['info']['email'],
42 :first_name => omniauth['info']['first_name'],
43 :last_name => omniauth['info']['last_name'],
44 :identity_url => omniauth['info']['identity_url'],
45 :is_active => Rails.configuration.new_users_are_active,
46 :owner_uuid => system_user_uuid)
48 user.save or raise Exception.new(user.errors.messages)
51 user.email = omniauth['info']['email']
52 user.first_name = omniauth['info']['first_name']
53 user.last_name = omniauth['info']['last_name']
54 if user.identity_url.nil?
55 # First login to a pre-activated account
56 user.identity_url = omniauth['info']['identity_url']
60 # For the benefit of functional and integration tests:
63 # prevent ArvadosModel#before_create and _update from throwing
65 Thread.current[:user] = user
67 user.save or raise Exception.new(user.errors.messages)
69 omniauth.delete('extra')
71 # Give the authenticated user a cookie for direct API access
72 session[:user_id] = user.id
73 session[:api_client_uuid] = nil
74 session[:api_client_trusted] = true # full permission to see user's secrets
76 @redirect_to = root_path
77 if params.has_key?(:return_to)
78 return send_api_token_to(params[:return_to], user)
80 redirect_to @redirect_to
83 # Omniauth failure callback
85 flash[:notice] = params[:message]
88 # logout - Clear our rack session BUT essentially redirect to the provider
89 # to clean up the Devise session from there too !
91 session[:user_id] = nil
93 flash[:notice] = 'You have logged off'
94 return_to = params[:return_to] || root_url
95 redirect_to "#{CUSTOM_PROVIDER_URL}/users/sign_out?redirect_uri=#{CGI.escape return_to}"
98 # login - Just bounce to /auth/joshid. The only purpose of this function is
99 # to save the return_to parameter (if it exists; see the application
100 # controller). /auth/joshid bypasses the application controller.
102 auth_provider = if params[:auth_provider] then "auth_provider=#{CGI.escape(params[:auth_provider])}" else "" end
104 if current_user and params[:return_to]
105 # Already logged in; just need to send a token to the requesting
108 # FIXME: if current_user has never authorized this app before,
109 # ask for confirmation here!
111 send_api_token_to(params[:return_to], current_user)
112 elsif params[:return_to]
113 redirect_to "/auth/joshid?return_to=#{CGI.escape(params[:return_to])}&#{auth_provider}"
115 redirect_to "/auth/joshid?#{auth_provider}"
119 def send_api_token_to(callback_url, user)
120 # Give the API client a token for making API calls on behalf of
121 # the authenticated user
123 # Stub: automatically register all new API clients
124 api_client_url_prefix = callback_url.match(%r{^.*?://[^/]+})[0] + '/'
125 act_as_system_user do
126 @api_client = ApiClient.find_or_create_by_url_prefix api_client_url_prefix
129 api_client_auth = ApiClientAuthorization.
131 api_client: @api_client,
132 created_by_ip_address: remote_ip,
134 api_client_auth.save!
136 if callback_url.index('?')
141 callback_url += 'api_token=' + api_client_auth.api_token
142 redirect_to callback_url