97 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
			
		
		
	
	
			97 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Ruby
		
	
	
	
| # frozen_string_literal: true
 | |
| 
 | |
| class Oauth::AuthorizationsController < Doorkeeper::AuthorizationsController
 | |
|   include Gitlab::Experimentation::ControllerConcern
 | |
|   include InitializesCurrentUserMode
 | |
|   include Gitlab::Utils::StrongMemoize
 | |
| 
 | |
|   before_action :verify_confirmed_email!, :verify_confidential_application!
 | |
| 
 | |
|   layout 'profile'
 | |
| 
 | |
|   # Overridden from Doorkeeper::AuthorizationsController to
 | |
|   # include the call to session.delete
 | |
|   def new
 | |
|     if pre_auth.authorizable?
 | |
|       if skip_authorization? || matching_token?
 | |
|         auth = authorization.authorize
 | |
|         parsed_redirect_uri = URI.parse(auth.redirect_uri)
 | |
|         session.delete(:user_return_to)
 | |
|         render "doorkeeper/authorizations/redirect", locals: { redirect_uri: parsed_redirect_uri }, layout: false
 | |
|       else
 | |
|         render "doorkeeper/authorizations/new"
 | |
|       end
 | |
|     else
 | |
|       render "doorkeeper/authorizations/error"
 | |
|     end
 | |
|   end
 | |
| 
 | |
|   private
 | |
| 
 | |
|   def pre_auth_params
 | |
|     # Cannot be achieved with a before_action hook, due to the execution order.
 | |
|     downgrade_scopes! if action_name == 'new'
 | |
| 
 | |
|     super
 | |
|   end
 | |
| 
 | |
|   # limit scopes when signing in with GitLab
 | |
|   def downgrade_scopes!
 | |
|     auth_type = params.delete('gl_auth_type')
 | |
|     return unless auth_type == 'login'
 | |
| 
 | |
|     ensure_read_user_scope!
 | |
| 
 | |
|     params['scope'] = Gitlab::Auth::READ_USER_SCOPE.to_s if application_has_read_user_scope?
 | |
|   end
 | |
| 
 | |
|   # Configure the application to support read_user scope, if it already
 | |
|   # supports scopes with greater levels of privileges.
 | |
|   def ensure_read_user_scope!
 | |
|     return if application_has_read_user_scope?
 | |
|     return unless application_has_api_scope?
 | |
| 
 | |
|     add_read_user_scope!
 | |
|   end
 | |
| 
 | |
|   def add_read_user_scope!
 | |
|     return unless doorkeeper_application
 | |
| 
 | |
|     scopes = doorkeeper_application.scopes
 | |
|     scopes.add(Gitlab::Auth::READ_USER_SCOPE)
 | |
|     doorkeeper_application.scopes = scopes
 | |
|     doorkeeper_application.save!
 | |
|   end
 | |
| 
 | |
|   def doorkeeper_application
 | |
|     strong_memoize(:doorkeeper_application) { ::Doorkeeper::OAuth::Client.find(params['client_id'])&.application }
 | |
|   end
 | |
| 
 | |
|   def application_has_read_user_scope?
 | |
|     doorkeeper_application&.includes_scope?(Gitlab::Auth::READ_USER_SCOPE)
 | |
|   end
 | |
| 
 | |
|   def application_has_api_scope?
 | |
|     doorkeeper_application&.includes_scope?(*::Gitlab::Auth::API_SCOPES)
 | |
|   end
 | |
| 
 | |
|   # Confidential apps require the client_secret to be sent with the request.
 | |
|   # Doorkeeper allows implicit grant flow requests (response_type=token) to
 | |
|   # work without client_secret regardless of the confidential setting.
 | |
|   # This leads to security vulnerabilities and we want to block it.
 | |
|   def verify_confidential_application!
 | |
|     render 'doorkeeper/authorizations/error' if authorizable_confidential?
 | |
|   end
 | |
| 
 | |
|   def authorizable_confidential?
 | |
|     pre_auth.authorizable? && pre_auth.response_type == 'token' && pre_auth.client.application.confidential
 | |
|   end
 | |
| 
 | |
|   def verify_confirmed_email!
 | |
|     return if current_user&.confirmed?
 | |
| 
 | |
|     pre_auth.error = :unconfirmed_email
 | |
|     render "doorkeeper/authorizations/error"
 | |
|   end
 | |
| end
 |