Files
discourse/lib/auth/github_authenticator.rb
Régis Hanol 9dadc0141c FEATURE: add link to "associated accounts" providers (#33275)
This adds a link for each authentication providers that are listed in
/my/preferences/account in the "Associated Accounts" section.

This is particularly useful when Discourse is being used in the PWA or
in the DiscourseMobile app where there's no browser bar available and
the only way to visit the provider's website is to open a browser
window.

That way, they can _just_ click the provider's name.

Internal ref - t/156255

---

**BEFORE**

![Screenshot 2025-06-19 at 21 04
46](https://github.com/user-attachments/assets/3d2be5d0-d857-4b8a-b0a5-5672301c59c6)

**AFTER**

![Screenshot 2025-06-19 at 21 03
39](https://github.com/user-attachments/assets/4c8bc5e9-3c99-4924-8d33-547f567bb346)
2025-06-20 10:22:29 +02:00

75 lines
2.0 KiB
Ruby

# frozen_string_literal: true
require "has_errors"
class Auth::GithubAuthenticator < Auth::ManagedAuthenticator
def name
"github"
end
def display_name
"GitHub"
end
def provider_url
"https://github.com"
end
def enabled?
SiteSetting.enable_github_logins
end
def after_authenticate(auth_token, existing_account: nil)
result = super
return result if result.user
# If email domain restrictions are configured,
# pick a secondary email which is allowed
all_github_emails(auth_token).each do |candidate|
next if !EmailValidator.allowed?(candidate[:email])
result.email = candidate[:email]
result.email_valid = !!candidate[:verified]
break
end
result
end
def find_user_by_email(auth_token)
# Use verified secondary emails to find a match
all_github_emails(auth_token).each do |candidate|
next if !candidate[:verified]
if user = User.find_by_email(candidate[:email])
return user
end
end
nil
end
def all_github_emails(auth_token)
emails = Array.new(auth_token[:extra][:all_emails])
primary_email = emails.find { |email| email[:primary] }
if primary_email
emails.delete(primary_email)
emails.unshift(primary_email)
end
emails
end
def register_middleware(omniauth)
omniauth.provider :github,
setup:
lambda { |env|
strategy = env["omniauth.strategy"]
strategy.options[:client_id] = SiteSetting.github_client_id
strategy.options[:client_secret] = SiteSetting.github_client_secret
},
scope: "user:email"
end
# the omniauth-github gem only picks up the primary email if it's verified:
# https://github.com/omniauth/omniauth-github/blob/0ac46b59ccdabd4cbe5be4a665df269355081915/lib/omniauth/strategies/github.rb#L58-L61
def primary_email_verified?(auth_token)
true
end
end