Commit 6918999f authored by Blair Lunceford's avatar Blair Lunceford

Add auto_link_user OmniAuth setting

This change adds the auto_link_user OmniAuth setting.
Users signing in to GitLab can be automatically linked to current user.
Users are linked based on email.

Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/24327
MR: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36664
Related Omnibus MR: https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4415
parent 29518bb0
---
title: Add auto_link_user OmniAuth setting
merge_request: 36664
author:
type: added
...@@ -888,6 +888,11 @@ production: &base ...@@ -888,6 +888,11 @@ production: &base
# (default: false) # (default: false)
auto_link_saml_user: false auto_link_saml_user: false
# Allow users with existing accounts to login and auto link their account via OmniAuth
# login, without having to do a manual login first and manually add OmniAuth. Links on email.
# (default: false)
auto_link_user: false
# Set different Omniauth providers as external so that all users creating accounts # Set different Omniauth providers as external so that all users creating accounts
# via these providers will not be able to have access to internal projects. You # via these providers will not be able to have access to internal projects. You
# will need to use the full name of the provider, like `google_oauth2` for Google. # will need to use the full name of the provider, like `google_oauth2` for Google.
......
...@@ -83,6 +83,7 @@ Settings.omniauth['external_providers'] = [] if Settings.omniauth['external_prov ...@@ -83,6 +83,7 @@ Settings.omniauth['external_providers'] = [] if Settings.omniauth['external_prov
Settings.omniauth['block_auto_created_users'] = true if Settings.omniauth['block_auto_created_users'].nil? Settings.omniauth['block_auto_created_users'] = true if Settings.omniauth['block_auto_created_users'].nil?
Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil? Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil?
Settings.omniauth['auto_link_saml_user'] = false if Settings.omniauth['auto_link_saml_user'].nil? Settings.omniauth['auto_link_saml_user'] = false if Settings.omniauth['auto_link_saml_user'].nil?
Settings.omniauth['auto_link_user'] = false if Settings.omniauth['auto_link_user'].nil?
Settings.omniauth['sync_profile_from_provider'] = false if Settings.omniauth['sync_profile_from_provider'].nil? Settings.omniauth['sync_profile_from_provider'] = false if Settings.omniauth['sync_profile_from_provider'].nil?
Settings.omniauth['sync_profile_attributes'] = ['email'] if Settings.omniauth['sync_profile_attributes'].nil? Settings.omniauth['sync_profile_attributes'] = ['email'] if Settings.omniauth['sync_profile_attributes'].nil?
......
...@@ -140,6 +140,23 @@ OmniAuth provider for an existing user. ...@@ -140,6 +140,23 @@ OmniAuth provider for an existing user.
The chosen OmniAuth provider is now active and can be used to sign in to GitLab from then on. The chosen OmniAuth provider is now active and can be used to sign in to GitLab from then on.
## Automatically Link Existing Users to OmniAuth Users
You can automatically link OmniAuth users with existing GitLab users if their email addresses match by adding the following setting:
**For Omnibus installations**
```ruby
gitlab_rails['omniauth_auto_link_user'] = true
```
**For installations from source**
```yaml
omniauth:
auto_link_user: true
```
## Configure OmniAuth Providers as External ## Configure OmniAuth Providers as External
> Introduced in GitLab 8.7. > Introduced in GitLab 8.7.
......
...@@ -62,6 +62,7 @@ module Gitlab ...@@ -62,6 +62,7 @@ module Gitlab
def find_user def find_user
user = find_by_uid_and_provider user = find_by_uid_and_provider
user ||= find_by_email if auto_link_user?
user ||= find_or_build_ldap_user if auto_link_ldap_user? user ||= find_or_build_ldap_user if auto_link_ldap_user?
user ||= build_new_user if signup_enabled? user ||= build_new_user if signup_enabled?
...@@ -269,6 +270,10 @@ module Gitlab ...@@ -269,6 +270,10 @@ module Gitlab
.disabled_oauth_sign_in_sources .disabled_oauth_sign_in_sources
.include?(auth_hash.provider) .include?(auth_hash.provider)
end end
def auto_link_user?
Gitlab.config.omniauth.auto_link_user
end
end end
end end
end end
......
...@@ -194,6 +194,43 @@ RSpec.describe Gitlab::Auth::OAuth::User do ...@@ -194,6 +194,43 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end end
end end
context "with auto_link_user disabled (default)" do
before do
stub_omniauth_config(auto_link_user: false)
end
include_examples "to verify compliance with allow_single_sign_on"
end
context "with auto_link_user enabled" do
before do
stub_omniauth_config(auto_link_user: true)
end
context "and a current GitLab user with a matching email" do
let!(:existing_user) { create(:user, email: 'john@mail.com', username: 'john') }
it "adds the OmniAuth identity to the GitLab user account" do
oauth_user.save
expect(gl_user).to be_valid
expect(gl_user.username).to eql 'john'
expect(gl_user.email).to eql 'john@mail.com'
expect(gl_user.identities.length).to be 1
identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
expect(identities_as_hash).to match_array(
[
{ provider: 'twitter', extern_uid: uid }
]
)
end
end
context "and no current GitLab user with a matching email" do
include_examples "to verify compliance with allow_single_sign_on"
end
end
context "with auto_link_ldap_user disabled (default)" do context "with auto_link_ldap_user disabled (default)" do
before do before do
stub_omniauth_config(auto_link_ldap_user: false) stub_omniauth_config(auto_link_ldap_user: false)
...@@ -364,6 +401,90 @@ RSpec.describe Gitlab::Auth::OAuth::User do ...@@ -364,6 +401,90 @@ RSpec.describe Gitlab::Auth::OAuth::User do
end end
end end
end end
context "with both auto_link_user and auto_link_ldap_user enabled" do
before do
stub_omniauth_config(auto_link_user: true, auto_link_ldap_user: true)
end
context "and at least one LDAP provider is defined" do
before do
stub_ldap_config(providers: %w(ldapmain))
end
context "and a corresponding LDAP person" do
before do
allow(ldap_user).to receive_messages(
uid: uid,
username: uid,
name: 'John Doe',
email: ['john@mail.com'],
dn: dn
)
end
context "and no account for the LDAP user" do
before do
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_uid).and_return(ldap_user)
oauth_user.save
end
it "creates a user with dual LDAP and omniauth identities" do
expect(gl_user).to be_valid
expect(gl_user.username).to eql uid
expect(gl_user.name).to eql 'John Doe'
expect(gl_user.email).to eql 'john@mail.com'
expect(gl_user.identities.length).to be 2
identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
expect(identities_as_hash).to match_array(
[
{ provider: 'ldapmain', extern_uid: dn },
{ provider: 'twitter', extern_uid: uid }
]
)
end
it "has name and email set as synced" do
expect(gl_user.user_synced_attributes_metadata.name_synced).to be_truthy
expect(gl_user.user_synced_attributes_metadata.email_synced).to be_truthy
end
it "has name and email set as read-only" do
expect(gl_user.read_only_attribute?(:name)).to be_truthy
expect(gl_user.read_only_attribute?(:email)).to be_truthy
end
it "has synced attributes provider set to ldapmain" do
expect(gl_user.user_synced_attributes_metadata.provider).to eql 'ldapmain'
end
end
context "and LDAP user has an account already" do
let!(:existing_user) { create(:omniauth_user, name: 'John Doe', email: 'john@mail.com', extern_uid: dn, provider: 'ldapmain', username: 'john') }
it "adds the omniauth identity to the LDAP account" do
allow(Gitlab::Auth::Ldap::Person).to receive(:find_by_uid).and_return(ldap_user)
oauth_user.save
expect(gl_user).to be_valid
expect(gl_user.username).to eql 'john'
expect(gl_user.name).to eql 'John Doe'
expect(gl_user.email).to eql 'john@mail.com'
expect(gl_user.identities.length).to be 2
identities_as_hash = gl_user.identities.map { |id| { provider: id.provider, extern_uid: id.extern_uid } }
expect(identities_as_hash).to match_array(
[
{ provider: 'ldapmain', extern_uid: dn },
{ provider: 'twitter', extern_uid: uid }
]
)
end
end
end
end
end
end end
describe 'blocking' do describe 'blocking' do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment