OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openproject/lib/open_project/authentication/strategies/warden/global_basic_auth.rb

88 lines
2.9 KiB

require 'warden/basic_auth'
module OpenProject
module Authentication
module Strategies
module Warden
##
# Allows authentication via a singular set of basic auth credentials for admin access.
#
# The credentials must be configured in `config/configuration.yml` like this:
#
# production:
# authentication:
# global_basic_auth:
# user: admin
# password: 123456
#
# The strategy will only be triggered when the configured user name is sent.
# Meaning that this strategy is skipped if a basic auth attempt involving any
# other user name is made.
class GlobalBasicAuth < ::Warden::Strategies::BasicAuth
def self.configuration
@configuration ||= configure!
end
##
# Updates the configuration for this strategy. It's usually called only once, at startup.
#
# @param [Hash] config The configuration to be used. Must contain :user and :password.
# @raise [ArgumentError] Raises an error if the configured user name collides with the
10 years ago
# user name used for UserBasicAuth (apikey) or if the
# provided password is empty.
# @return [Hash] The new hash set for the configuration or an empty hash if
# no configuration was provided.
def self.configure!(config = openproject_config)
return {} if config.empty?
if config[:user] == UserBasicAuth.user
raise ArgumentError, "global user must not be '#{UserBasicAuth.user}'"
end
if config[:password].blank?
raise ArgumentError, 'password must not be empty'
end
@configuration = config
end
##
# Reads the configuration for this strategy from OpenProject's `configuration.yml`.
def self.openproject_config
config = OpenProject::Configuration
%w(authentication global_basic_auth).inject(config) do |acc, key|
HashWithIndifferentAccess.new acc[key]
end
end
def self.configuration?
user && password
end
def self.user
configuration[:user]
end
def self.password
configuration[:password].to_s
end
##
# Only valid if global basic auth is configured and tried.
def valid?
self.class.configuration? && super && username == self.class.user
end
def authenticate_user(username, password)
if username == self.class.user && password == self.class.password
User.system.tap do |user|
user.admin = true
end
end
end
end
end
end
end
end