discourse/lib/auth/discord_authenticator.rb

74 lines
2.0 KiB
Ruby

# frozen_string_literal: true
class Auth::DiscordAuthenticator < Auth::ManagedAuthenticator
class DiscordStrategy < OmniAuth::Strategies::OAuth2
option :name, 'discord'
option :scope, 'identify email guilds'
option :client_options,
site: 'https://discordapp.com/api',
authorize_url: 'oauth2/authorize',
token_url: 'oauth2/token'
option :authorize_options, %i[scope permissions]
uid { raw_info['id'] }
info do
{
name: raw_info['username'],
email: raw_info['verified'] ? raw_info['email'] : nil,
image: "https://cdn.discordapp.com/avatars/#{raw_info['id']}/#{raw_info['avatar']}"
}
end
extra do
{
'raw_info' => raw_info
}
end
def raw_info
@raw_info ||= access_token.get('users/@me').parsed.
merge(guilds: access_token.get('users/@me/guilds').parsed)
end
def callback_url
full_host + script_name + callback_path
end
end
def name
'discord'
end
def enabled?
SiteSetting.enable_discord_logins?
end
def register_middleware(omniauth)
omniauth.provider DiscordStrategy,
setup: lambda { |env|
strategy = env["omniauth.strategy"]
strategy.options[:client_id] = SiteSetting.discord_client_id
strategy.options[:client_secret] = SiteSetting.discord_secret
}
end
def after_authenticate(auth_token, existing_account: nil)
allowed_guild_ids = SiteSetting.discord_trusted_guilds.split("|")
if allowed_guild_ids.length > 0
user_guild_ids = auth_token.extra[:raw_info][:guilds].map { |g| g['id'] }
if (user_guild_ids & allowed_guild_ids).empty? # User is not in any allowed guilds
return Auth::Result.new.tap do |auth_result|
auth_result.failed = true
auth_result.failed_reason = I18n.t("discord.not_in_allowed_guild")
end
end
end
super
end
end