Skip to content

Commit

Permalink
feat: add OAuth2 providers (#260)
Browse files Browse the repository at this point in the history
  • Loading branch information
mashirozx committed Oct 8, 2022
1 parent 1e7f1a8 commit 6b6f820
Show file tree
Hide file tree
Showing 11 changed files with 125 additions and 7 deletions.
2 changes: 2 additions & 0 deletions Gemfile
Expand Up @@ -39,6 +39,8 @@ end

gem 'net-ldap', '~> 0.17'
gem 'omniauth-cas', '~> 2.0'
gem 'omniauth-github', '~> 1.4'
gem 'omniauth-gitlab', '~> 1.0.2'
gem 'omniauth-saml', '~> 1.10'
gem 'gitlab-omniauth-openid-connect', '~>0.10.0', require: 'omniauth_openid_connect'
gem 'omniauth', '~> 1.9'
Expand Down
18 changes: 18 additions & 0 deletions Gemfile.lock
Expand Up @@ -418,6 +418,7 @@ GEM
minitest (5.16.3)
msgpack (1.5.4)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1)
net-ldap (0.17.1)
net-scp (4.0.0.rc1)
Expand All @@ -432,6 +433,12 @@ GEM
concurrent-ruby (~> 1.0, >= 1.0.2)
sidekiq (>= 3.5)
statsd-ruby (~> 1.4, >= 1.4.0)
oauth2 (1.4.7)
faraday (>= 0.8, < 2.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
oj (3.13.21)
omniauth (1.9.2)
hashie (>= 3.4.6)
Expand All @@ -440,6 +447,15 @@ GEM
addressable (~> 2.3)
nokogiri (~> 1.5)
omniauth (~> 1.2)
omniauth-github (1.4.0)
omniauth (~> 1.5)
omniauth-oauth2 (>= 1.4.0, < 2.0)
omniauth-gitlab (1.0.4)
omniauth (~> 1.0)
omniauth-oauth2 (~> 1.0)
omniauth-oauth2 (1.7.2)
oauth2 (~> 1.4)
omniauth (>= 1.9, < 3)
omniauth-rails_csrf_protection (0.1.2)
actionpack (>= 4.2)
omniauth (>= 1.3.1)
Expand Down Expand Up @@ -819,6 +835,8 @@ DEPENDENCIES
oj (~> 3.13)
omniauth (~> 1.9)
omniauth-cas (~> 2.0)
omniauth-github (~> 1.4)
omniauth-gitlab (~> 1.0.2)
omniauth-rails_csrf_protection (~> 0.1)
omniauth-saml (~> 1.10)
ox (~> 2.14)
Expand Down
6 changes: 6 additions & 0 deletions app/controllers/auth/omniauth_callbacks_controller.rb
Expand Up @@ -7,6 +7,12 @@ def self.provides_callback_for(provider)
define_method provider do
@user = User.find_for_oauth(request.env['omniauth.auth'], current_user)

if @user.nil?
redirect_to new_user_registration_url
set_flash_message(:alert, 'should_register_before_auth_login', scope: 'devise.failure')
return
end

if @user.persisted?
LoginActivity.create(
user: @user,
Expand Down
35 changes: 35 additions & 0 deletions app/javascript/styles/mastodon/components.scss
Expand Up @@ -94,6 +94,19 @@
outline: 0 !important;
}

&.button-primary,
&.button-alternative,
&.button-secondary,
&.button-alternative-2,
&.button-github,
&.button-gitlab {
font-size: 16px;
line-height: 36px;
height: auto;
text-transform: none;
padding: 4px 16px;
}

&.button-alternative {
color: $inverted-text-color;
background: $ui-primary-color;
Expand Down Expand Up @@ -154,6 +167,28 @@
}
}

&.button-github {
color: $white;
background: #24292f;

&:active,
&:focus,
&:hover {
background-color: lighten(#24292f, 4%);
}
}

&.button-gitlab {
color: $white;
background: #fc6d27;

&:active,
&:focus,
&:hover {
background-color: darken(#fc6d27, 4%);
}
}

&.button--block {
display: block;
width: 100%;
Expand Down
55 changes: 48 additions & 7 deletions app/models/concerns/omniauthable.rb
Expand Up @@ -31,6 +31,8 @@ def find_for_oauth(auth, signed_in_resource = nil)
user = signed_in_resource || identity.user
user ||= create_for_oauth(auth)

return nil if user.nil?

if identity.user.nil?
identity.user = user
identity.save!
Expand All @@ -48,15 +50,18 @@ def create_for_oauth(auth)
assume_verified = strategy&.security&.assume_email_is_verified
email_is_verified = auth.info.verified || auth.info.verified_email || auth.info.email_verified || assume_verified
email = auth.info.verified_email || auth.info.email
# email = nil unless email_is_verified or trusted_auth_provider(auth)

user = User.find_by(email: email) if email_is_verified
user = User.find_by(email: email) if email_is_verified or trusted_auth_provider(auth)

return user unless user.nil?

return nil if is_registration_limited

user = User.new(user_params_from_auth(email, auth))

user.account.avatar_remote_url = auth.info.image if /\A#{URI::DEFAULT_PARSER.make_regexp(%w(http https))}\z/.match?(auth.info.image)
user.skip_confirmation! if email_is_verified
user.skip_confirmation! if email_is_verified or trusted_auth_provider(auth)
user.save!
user
end
Expand All @@ -69,19 +74,31 @@ def user_params_from_auth(email, auth)
agreement: true,
external: true,
account_attributes: {
username: ensure_unique_username(ensure_valid_username(auth.uid)),
display_name: auth.info.full_name || auth.info.name || [auth.info.first_name, auth.info.last_name].join(' '),
username: ensure_unique_username(auth),
display_name: trusted_auth_provider_display_name(auth) ||
auth.info.full_name || auth.info.name || [auth.info.first_name, auth.info.last_name].join(' '),
},
}
end

def ensure_unique_username(starting_username)
username = starting_username
def ensure_unique_username(auth)
username = auth.uid
auth_provideded_username = nil
i = 0

if auth.provider == 'github'
auth_provideded_username = auth.info.nickname
elsif auth.provider == 'gitlab'
auth_provideded_username = auth.info.username
end

username = auth_provideded_username unless auth_provideded_username.empty?

username = ensure_valid_username(username)

while Account.exists?(username: username, domain: nil)
i += 1
username = "#{starting_username}_#{i}"
username = "#{auth_provideded_username || auth.uid}_#{i}"
end

username
Expand All @@ -93,5 +110,29 @@ def ensure_valid_username(starting_username)
validated_username = temp_username.truncate(30, omission: '')
validated_username
end

def trusted_auth_provider(auth)
auth.provider == 'github' || auth.provider == 'gitlab'
end

def trusted_auth_provider_display_name(auth)
if auth.provider == 'github'
return auth.info.name
elsif auth.provider == 'gitlab'
return auth.info.name
end

return nil
end

def is_registration_limited()
if ENV['AUTO_REGISTRATION_WITH_AUTH_PROVIDERS'] == 'true'
return false
elsif Setting.registrations_mode != 'open'
return true
else
return false
end
end
end
end
10 changes: 10 additions & 0 deletions config/initializers/omniauth.rb
Expand Up @@ -101,4 +101,14 @@
oidc_options[:security][:assume_email_is_verified] = ENV['OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED'] == 'true' #OPTIONAL
config.omniauth :openid_connect, oidc_options
end

# Github strategy
if ENV['GITHUB_OAUTH2_ENABLED'] == 'true'
config.omniauth :github, ENV['GITHUB_OAUTH2_KEY'], ENV['GITHUB_OAUTH2_SECRET'], scope: 'user.info'
end

# Gitlab strategy
if ENV['GITLAB_OAUTH2_ENABLED'] == 'true'
config.omniauth :gitlab, ENV['GITLAB_OAUTH2_KEY'], ENV['GITLAB_OAUTH2_SECRET'], scope: 'read_user'
end
end
1 change: 1 addition & 0 deletions config/locales/devise.en.yml
Expand Up @@ -16,6 +16,7 @@ en:
timeout: Your session expired. Please sign in again to continue.
unauthenticated: You need to sign in or sign up before continuing.
unconfirmed: You have to confirm your email address before continuing.
should_register_before_auth_login: You need to sign up before continuing.
mailer:
confirmation_instructions:
action: Verify email address
Expand Down
1 change: 1 addition & 0 deletions config/locales/devise.zh-CN.yml
Expand Up @@ -16,6 +16,7 @@ zh-CN:
timeout: 你的会话已过期。请重新登录再继续操作。
unauthenticated: 继续操作前请注册或者登录。
unconfirmed: 你必须先确认你的电子邮件地址才能继续。
should_register_before_auth_login: 请先注册。
mailer:
confirmation_instructions:
action: 验证电子邮件地址
Expand Down
1 change: 1 addition & 0 deletions config/locales/devise.zh-HK.yml
Expand Up @@ -16,6 +16,7 @@ zh-HK:
timeout: 你的登入階段已經過期,請重新登入以繼續使用。
unauthenticated: 你必須先登入或登記,以繼續使用。
unconfirmed: 你必須先確認電郵地址,繼續使用。
should_register_before_auth_login: 你必須先登記,以繼續使用。
mailer:
confirmation_instructions:
action: 驗證電子郵件地址
Expand Down
1 change: 1 addition & 0 deletions config/locales/devise.zh-TW.yml
Expand Up @@ -16,6 +16,7 @@ zh-TW:
timeout: 登入階段逾時。請重新登入以繼續。
unauthenticated: 您必須先登入或註冊才能繼續使用。
unconfirmed: 您必須先確認電子信箱才能繼續使用。
should_register_before_auth_login: 您必須先註冊才能繼續使用。
mailer:
confirmation_instructions:
action: 驗證電子信箱地址
Expand Down
2 changes: 2 additions & 0 deletions config/locales/en.yml
Expand Up @@ -1020,6 +1020,8 @@ en:
providers:
cas: CAS
saml: SAML
github: GitHub
gitlab: GitLab
register: Sign up
registration_closed: "%{instance} is not accepting new members"
resend_confirmation: Resend confirmation instructions
Expand Down

0 comments on commit 6b6f820

Please sign in to comment.