103 lines
3.0 KiB
Ruby
103 lines
3.0 KiB
Ruby
# name: discourse-openid-connect
|
|
# about: Add support for openid-connect as a login provider
|
|
# version: 1.0
|
|
# authors: David Taylor
|
|
# url: https://github.com/discourse/discourse-openid-connect
|
|
|
|
require_relative "lib/omniauth_open_id_connect"
|
|
require_relative 'app/models/user_associated_account'
|
|
|
|
class Auth::ManagedAuthenticator < Auth::Authenticator
|
|
def match_by_email
|
|
true
|
|
end
|
|
|
|
def after_authenticate(auth_token)
|
|
# puts "after authenticate ", auth_token.to_json
|
|
|
|
result = Auth::Result.new
|
|
|
|
result.authenticator_name = "OpenID Connect"
|
|
|
|
result.extra_data = {
|
|
provider: auth_token[:provider],
|
|
uid: auth_token[:uid],
|
|
info: auth_token[:info],
|
|
extra: auth_token[:extra],
|
|
credentials: auth_token[:credentials]
|
|
}
|
|
|
|
data = auth_token[:info]
|
|
result.email = email = data[:email]
|
|
result.name = name = "#{data[:first_name]} #{data[:last_name]}"
|
|
result.username = data[:nickname]
|
|
|
|
association = UserAssociatedAccount.find_by(provider_name: auth_token[:provider], provider_uid: auth_token[:uid])
|
|
|
|
if match_by_email && association.nil? && (user = User.find_by_email(email)) && !UserAssociatedAccount.exists?(user: user, provider_name: auth_token[:provider])
|
|
association = UserAssociatedAccount.create!(user: user, provider_name: auth_token[:provider], provider_uid: auth_token[:uid], info: auth_token[:info], credentials: auth_token[:credentials], extra: auth_token[:extra])
|
|
end
|
|
|
|
result.user = association&.user
|
|
result.email_valid = true
|
|
|
|
result
|
|
end
|
|
|
|
def after_create_account(user, auth)
|
|
data = auth[:extra_data]
|
|
association = UserAssociatedAccount.create!(
|
|
user: user,
|
|
provider_name: data[:provider],
|
|
provider_uid: data[:uid],
|
|
info: data[:info],
|
|
credentials: data[:credentials],
|
|
extra: data[:extra]
|
|
)
|
|
end
|
|
end
|
|
|
|
class OpenIDConnectAuthenticator < Auth::ManagedAuthenticator
|
|
|
|
def name
|
|
'oidc'
|
|
end
|
|
|
|
def enabled?
|
|
true
|
|
end
|
|
|
|
def register_middleware(omniauth)
|
|
|
|
omniauth.provider :openid_connect,
|
|
name: :oidc,
|
|
cache: lambda { |key, &blk| Rails.cache.fetch(key, expires_in: 10.minutes, &blk) },
|
|
error_handler: lambda { |error, message|
|
|
handlers = SiteSetting.openid_connect_error_redirects.split("\n")
|
|
handlers.each do |row|
|
|
parts = row.split("|")
|
|
return parts[1] if message.include? parts[0]
|
|
end
|
|
nil
|
|
},
|
|
setup: lambda { |env|
|
|
opts = env['omniauth.strategy'].options
|
|
opts.deep_merge!(
|
|
client_id: SiteSetting.openid_connect_client_id,
|
|
client_secret: SiteSetting.openid_connect_client_secret,
|
|
client_options: {
|
|
discovery_document: SiteSetting.openid_connect_discovery_document,
|
|
},
|
|
scope: SiteSetting.openid_connect_authorize_scope,
|
|
token_params: {
|
|
scope: SiteSetting.openid_connect_token_scope,
|
|
}
|
|
)
|
|
}
|
|
end
|
|
end
|
|
|
|
auth_provider title: 'with OpenID Connect',
|
|
authenticator: OpenIDConnectAuthenticator.new(),
|
|
full_screen_login: true
|