discourse/lib/auth/open_id_authenticator.rb
Sam Saffron 30990006a9 DEV: enable frozen string literal on all files
This reduces chances of errors where consumers of strings mutate inputs
and reduces memory usage of the app.

Test suite passes now, but there may be some stuff left, so we will run
a few sites on a branch prior to merging
2019-05-13 09:31:32 +08:00

110 lines
3.2 KiB
Ruby

# frozen_string_literal: true
class Auth::OpenIdAuthenticator < Auth::Authenticator
attr_reader :name, :identifier
def initialize(name, identifier, enabled_site_setting, opts = {})
@name = name
@identifier = identifier
@enabled_site_setting = enabled_site_setting
@opts = opts
end
def enabled?
SiteSetting.get(@enabled_site_setting)
end
def description_for_user(user)
info = UserOpenId.where("url LIKE ?", "#{@identifier}%").find_by(user_id: user.id)
info&.email || ""
end
def can_revoke?
true
end
def revoke(user, skip_remote: false)
info = UserOpenId.where("url LIKE ?", "#{@identifier}%").find_by(user_id: user.id)
raise Discourse::NotFound if info.nil?
info.destroy!
true
end
def can_connect_existing_user?
true
end
def after_authenticate(auth_token, existing_account: nil)
Discourse.deprecate("OpenID Authentication has been deprecated, please migrate to OAuth2 or OpenID Connect", since: "2.3.0beta4", drop_from: "2.4")
result = Auth::Result.new
data = auth_token[:info]
identity_url = auth_token[:extra][:response].identity_url
result.email = email = data[:email]
raise Discourse::InvalidParameters.new(:email) if email.blank?
# If the auth supplies a name / username, use those. Otherwise start with email.
result.name = data[:name] || data[:email]
result.username = data[:nickname] || data[:email]
user_open_id = UserOpenId.find_by_url(identity_url)
if existing_account && (user_open_id.nil? || existing_account.id != user_open_id.user_id)
user_open_id.destroy! if user_open_id
user_open_id = UserOpenId.create!(url: identity_url , user_id: existing_account.id, email: email, active: true)
end
if !user_open_id && @opts[:trusted] && user = User.find_by_email(email)
user_open_id = UserOpenId.create(url: identity_url , user_id: user.id, email: email, active: true)
end
result.user = user_open_id.try(:user)
result.extra_data = {
openid_url: identity_url,
# note email may change by the time after_create_account runs
email: email
}
result.email_valid = @opts[:trusted]
result
end
def after_create_account(user, auth)
data = auth[:extra_data]
UserOpenId.create(
user_id: user.id,
url: data[:openid_url],
email: data[:email],
active: true
)
end
def register_middleware(omniauth)
omniauth.provider :open_id,
setup: lambda { |env|
strategy = env["omniauth.strategy"]
strategy.options[:store] = OpenID::Store::Redis.new($redis)
# Add CSRF protection in addition to OpenID Specification
def strategy.query_string
session["omniauth.state"] = state = SecureRandom.hex(24)
"?state=#{state}"
end
def strategy.callback_phase
stored_state = session.delete("omniauth.state")
provided_state = request.params["state"]
return fail!(:invalid_credentials) unless provided_state == stored_state
super
end
},
name: name,
identifier: identifier,
require: "omniauth-openid"
end
end