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
# (default: 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
# 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.
......
......@@ -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['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_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_attributes'] = ['email'] if Settings.omniauth['sync_profile_attributes'].nil?
......
......@@ -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.
## 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
> Introduced in GitLab 8.7.
......
......@@ -62,6 +62,7 @@ module Gitlab
def find_user
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 ||= build_new_user if signup_enabled?
......@@ -269,6 +270,10 @@ module Gitlab
.disabled_oauth_sign_in_sources
.include?(auth_hash.provider)
end
def auto_link_user?
Gitlab.config.omniauth.auto_link_user
end
end
end
end
......
......@@ -194,6 +194,43 @@ RSpec.describe Gitlab::Auth::OAuth::User do
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
before do
stub_omniauth_config(auto_link_ldap_user: false)
......@@ -364,6 +401,90 @@ RSpec.describe Gitlab::Auth::OAuth::User do
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
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