2019-05-03 06:17:27 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2013-08-23 14:20:43 +08:00
|
|
|
class Auth::OpenIdAuthenticator < Auth::Authenticator
|
|
|
|
|
2013-08-26 09:04:16 +08:00
|
|
|
attr_reader :name, :identifier
|
|
|
|
|
2018-07-23 23:51:57 +08:00
|
|
|
def initialize(name, identifier, enabled_site_setting, opts = {})
|
2013-08-23 14:20:43 +08:00
|
|
|
@name = name
|
2013-08-26 09:04:16 +08:00
|
|
|
@identifier = identifier
|
2018-07-23 23:51:57 +08:00
|
|
|
@enabled_site_setting = enabled_site_setting
|
2013-08-23 14:20:43 +08:00
|
|
|
@opts = opts
|
|
|
|
end
|
|
|
|
|
2018-07-23 23:51:57 +08:00
|
|
|
def enabled?
|
2019-05-07 09:00:09 +08:00
|
|
|
SiteSetting.get(@enabled_site_setting)
|
2018-07-23 23:51:57 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def description_for_user(user)
|
2018-07-25 18:47:09 +08:00
|
|
|
info = UserOpenId.where("url LIKE ?", "#{@identifier}%").find_by(user_id: user.id)
|
2018-07-23 23:51:57 +08:00
|
|
|
info&.email || ""
|
|
|
|
end
|
|
|
|
|
2018-07-27 23:20:47 +08:00
|
|
|
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)
|
2019-04-08 17:38:25 +08:00
|
|
|
Discourse.deprecate("OpenID Authentication has been deprecated, please migrate to OAuth2 or OpenID Connect", since: "2.3.0beta4", drop_from: "2.4")
|
2013-08-23 14:20:43 +08:00
|
|
|
result = Auth::Result.new
|
|
|
|
|
|
|
|
data = auth_token[:info]
|
2014-03-26 11:52:50 +08:00
|
|
|
identity_url = auth_token[:extra][:response].identity_url
|
2013-08-23 14:20:43 +08:00
|
|
|
result.email = email = data[:email]
|
|
|
|
|
2014-08-08 01:28:50 +08:00
|
|
|
raise Discourse::InvalidParameters.new(:email) if email.blank?
|
|
|
|
|
2013-08-23 14:20:43 +08:00
|
|
|
# If the auth supplies a name / username, use those. Otherwise start with email.
|
2014-03-26 11:52:50 +08:00
|
|
|
result.name = data[:name] || data[:email]
|
|
|
|
result.username = data[:nickname] || data[:email]
|
2013-08-23 14:20:43 +08:00
|
|
|
|
|
|
|
user_open_id = UserOpenId.find_by_url(identity_url)
|
|
|
|
|
2018-07-27 23:20:47 +08:00
|
|
|
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
|
|
|
|
|
2013-08-23 14:20:43 +08:00
|
|
|
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 = {
|
2013-08-23 15:00:01 +08:00
|
|
|
openid_url: identity_url,
|
|
|
|
# note email may change by the time after_create_account runs
|
|
|
|
email: email
|
2013-08-23 14:20:43 +08:00
|
|
|
}
|
2014-03-26 11:52:50 +08:00
|
|
|
|
2013-08-23 14:20:43 +08:00
|
|
|
result.email_valid = @opts[:trusted]
|
|
|
|
|
|
|
|
result
|
|
|
|
end
|
2013-08-23 15:00:01 +08:00
|
|
|
|
|
|
|
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
|
2013-08-26 09:04:16 +08:00
|
|
|
|
|
|
|
def register_middleware(omniauth)
|
|
|
|
omniauth.provider :open_id,
|
2018-11-03 07:49:00 +08:00
|
|
|
setup: lambda { |env|
|
|
|
|
strategy = env["omniauth.strategy"]
|
2019-12-03 17:05:53 +08:00
|
|
|
strategy.options[:store] = OpenID::Store::Redis.new(Discourse.redis)
|
2018-11-03 07:49:00 +08:00
|
|
|
|
|
|
|
# Add CSRF protection in addition to OpenID Specification
|
|
|
|
def strategy.query_string
|
2018-11-05 20:16:03 +08:00
|
|
|
session["omniauth.state"] = state = SecureRandom.hex(24)
|
2018-11-03 07:49:00 +08:00
|
|
|
"?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"
|
2013-08-26 09:04:16 +08:00
|
|
|
end
|
2013-08-23 14:20:43 +08:00
|
|
|
end
|