authenticates.rb 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. # Copyright (C) 2012-2023 Zammad Foundation, https://zammad-foundation.org/
  2. module ApplicationController::Authenticates
  3. extend ActiveSupport::Concern
  4. private
  5. def permission_check(key)
  6. ActiveSupport::Deprecation.warn("Method 'permission_check' is deprecated. Use Pundit policy and `authorize!` instead.")
  7. if @_token_auth
  8. user = Token.check(
  9. action: 'api',
  10. name: @_token_auth,
  11. permission: key,
  12. )
  13. return false if user
  14. raise Exceptions::Forbidden, __('Not authorized (token)!')
  15. end
  16. return false if current_user&.permissions?(key)
  17. raise Exceptions::Forbidden, __('Not authorized (user)!')
  18. end
  19. def authentication_check(auth_param = {})
  20. user = authentication_check_only(auth_param)
  21. # check if basic_auth fallback is possible
  22. if auth_param[:basic_auth_promt] && !user
  23. request_http_basic_authentication
  24. return false
  25. end
  26. # return auth not ok
  27. if !user
  28. raise Exceptions::Forbidden, __('Authentication required')
  29. end
  30. # return auth ok
  31. true
  32. end
  33. def authentication_check_only(auth_param = {})
  34. if %w[test development].include?(Rails.env) && ENV['FAKE_SELENIUM_LOGIN_USER_ID'].present? && session[:user_id].blank?
  35. session[:user_id] = ENV['FAKE_SELENIUM_LOGIN_USER_ID'].to_i
  36. session[:user_device_updated_at] = Time.zone.now
  37. end
  38. # logger.debug 'authentication_check'
  39. # logger.debug params.inspect
  40. # logger.debug session.inspect
  41. # logger.debug cookies.inspect
  42. authentication_errors = []
  43. # already logged in, early exit
  44. if session.id && session[:user_id]
  45. logger.debug { 'session based auth check' }
  46. user = User.lookup(id: session[:user_id])
  47. return authentication_check_prerequesits(user, 'session', auth_param) if user
  48. authentication_errors.push("Can't find User with ID #{session[:user_id]} from Session")
  49. end
  50. # check http basic based authentication
  51. authenticate_with_http_basic do |username, password|
  52. request.session_options[:skip] = true # do not send a session cookie
  53. logger.debug { "http basic auth check '#{username}'" }
  54. if Setting.get('api_password_access') == false
  55. raise Exceptions::Forbidden, 'API password access disabled!'
  56. end
  57. auth = Auth.new(username, password)
  58. return authentication_check_prerequesits(auth.user, 'basic_auth', auth_param) if auth.valid?
  59. authentication_errors.push(__('Invalid BasicAuth credentials'))
  60. end
  61. # check http token based authentication
  62. authenticate_with_http_token do |token_string, _options|
  63. logger.debug { "http token auth check '#{token_string}'" }
  64. request.session_options[:skip] = true # do not send a session cookie
  65. if Setting.get('api_token_access') == false
  66. raise Exceptions::Forbidden, 'API token access disabled!'
  67. end
  68. user = Token.check(
  69. action: 'api',
  70. name: token_string,
  71. inactive_user: true,
  72. )
  73. if user && auth_param[:permission]
  74. ActiveSupport::Deprecation.warn("Paramter ':permission' is deprecated. Use Pundit policy and `authorize!` instead.")
  75. user = Token.check(
  76. action: 'api',
  77. name: token_string,
  78. permission: auth_param[:permission],
  79. inactive_user: true,
  80. )
  81. raise Exceptions::NotAuthorized, __('Not authorized (token)!') if !user
  82. end
  83. if user
  84. token = Token.find_by(name: token_string)
  85. token.last_used_at = Time.zone.now
  86. token.save!
  87. if token.expires_at &&
  88. Time.zone.today >= token.expires_at
  89. raise Exceptions::NotAuthorized, __('Not authorized (token expired)!')
  90. end
  91. @_token = token # remember for Pundit authorization / permit!
  92. end
  93. @_token_auth = token_string # remember for permission_check
  94. return authentication_check_prerequesits(user, 'token_auth', auth_param) if user
  95. authentication_errors.push(__("Can't find User for Token"))
  96. end
  97. # check oauth2 token based authentication
  98. token = Doorkeeper::OAuth::Token.from_bearer_authorization(request)
  99. if token
  100. request.session_options[:skip] = true # do not send a session cookie
  101. logger.debug { "OAuth2 token auth check '#{token}'" }
  102. access_token = Doorkeeper::AccessToken.by_token(token)
  103. raise Exceptions::NotAuthorized, __('The provided token is invalid.') if !access_token
  104. # check expire
  105. if access_token.expires_in && (access_token.created_at + access_token.expires_in) < Time.zone.now
  106. raise Exceptions::NotAuthorized, __('OAuth2 token is expired!')
  107. end
  108. # if access_token.scopes.empty?
  109. # raise Exceptions::NotAuthorized, 'OAuth2 scope missing for token!'
  110. # end
  111. user = User.find(access_token.resource_owner_id)
  112. return authentication_check_prerequesits(user, 'token_auth', auth_param) if user
  113. authentication_errors.push("Can't find User with ID #{access_token.resource_owner_id} for OAuth2 token")
  114. end
  115. return false if authentication_errors.blank?
  116. raise Exceptions::NotAuthorized, authentication_errors.join(', ')
  117. end
  118. def authentication_check_prerequesits(user, auth_type, auth_param)
  119. raise Exceptions::Forbidden, __('Maintenance mode enabled!') if in_maintenance_mode?(user)
  120. raise_unified_login_error if !user.active
  121. if auth_param[:permission]
  122. ActiveSupport::Deprecation.warn("Parameter ':permission' is deprecated. Use Pundit policy and `authorize!` instead.")
  123. if !user.permissions?(auth_param[:permission])
  124. raise Exceptions::Forbidden, __('Not authorized (user)!')
  125. end
  126. end
  127. current_user_set(user, auth_type)
  128. user_device_log(user, auth_type)
  129. logger.debug { "#{auth_type} for '#{user.login}'" }
  130. user
  131. end
  132. def raise_unified_login_error
  133. raise Exceptions::NotAuthorized, __('Login failed. Have you double-checked your credentials and completed the email verification step?')
  134. end
  135. end