Commit 1084e355 authored by Sebastián Arcila Valenzuela's avatar Sebastián Arcila Valenzuela Committed by Bob Van Landuyt

Fix smartcard login in 'unpersisted' users after

This is caused by allowing to link existing accounts with new
smartcards with ldap certificates
parent 5cd237e8
...@@ -21,7 +21,7 @@ class SmartcardController < ApplicationController ...@@ -21,7 +21,7 @@ class SmartcardController < ApplicationController
def sign_in_with(certificate) def sign_in_with(certificate)
user = certificate.find_or_create_user user = certificate.find_or_create_user
unless user unless user&.persisted?
flash[:alert] = _('Failed to signing using smartcard authentication') flash[:alert] = _('Failed to signing using smartcard authentication')
redirect_to new_user_session_path(port: Gitlab.config.gitlab.port) redirect_to new_user_session_path(port: Gitlab.config.gitlab.port)
......
---
title: Link user accounts to new Smartcards certificate ldap identities on login
merge_request: 20470
author:
type: fixed
...@@ -22,7 +22,12 @@ module Gitlab ...@@ -22,7 +22,12 @@ module Gitlab
end end
def create_identity_for_existing_user def create_identity_for_existing_user
# TODO: create new identity for existing users as part of https://gitlab.com/gitlab-org/gitlab/issues/36808 user = User.find_by_email(ldap_user.email.first)
return if user.nil? || user.ldap_user?
create_ldap_certificate_identity_for(user)
user
end end
def create_user def create_user
...@@ -41,6 +46,10 @@ module Gitlab ...@@ -41,6 +46,10 @@ module Gitlab
Users::CreateService.new(nil, user_params).execute(skip_authorization: true) Users::CreateService.new(nil, user_params).execute(skip_authorization: true)
end end
def create_ldap_certificate_identity_for(user)
user.identities.create(provider: @provider, extern_uid: ldap_user.dn)
end
def adapter def adapter
@adapter ||= Gitlab::Auth::LDAP::Adapter.new(@provider) @adapter ||= Gitlab::Auth::LDAP::Adapter.new(@provider)
end end
......
...@@ -25,7 +25,6 @@ describe Gitlab::Auth::Smartcard::LDAPCertificate do ...@@ -25,7 +25,6 @@ describe Gitlab::Auth::Smartcard::LDAPCertificate do
entry['mail'] = ldap_person_email entry['mail'] = ldap_person_email
end end
end end
let(:ldap_person) { ::Gitlab::Auth::LDAP::Person.new(ldap_entry, ldap_provider) }
before do before do
allow(described_class).to( allow(described_class).to(
...@@ -41,7 +40,7 @@ describe Gitlab::Auth::Smartcard::LDAPCertificate do ...@@ -41,7 +40,7 @@ describe Gitlab::Auth::Smartcard::LDAPCertificate do
describe '#find_or_create_user' do describe '#find_or_create_user' do
subject { described_class.new(ldap_provider, certificate_header).find_or_create_user } subject { described_class.new(ldap_provider, certificate_header).find_or_create_user }
context 'user already exists' do context 'user and smartcard ldap certificate already exists' do
let(:user) { create(:user) } let(:user) { create(:user) }
before do before do
...@@ -59,6 +58,35 @@ describe Gitlab::Auth::Smartcard::LDAPCertificate do ...@@ -59,6 +58,35 @@ describe Gitlab::Auth::Smartcard::LDAPCertificate do
end end
end end
context 'user exists but it is using a new ldap certificate' do
let(:ldap_person_email) { user.email }
let_it_be(:user) { create(:user) }
it 'finds existing user' do
expect(subject).to eql(user)
end
it 'does create new user identity' do
expect { subject }.to change { user.identities.count }.by(1)
end
context 'user already has a different ldap certificate identity' do
before do
create(:identity, { provider: 'ldapmain',
extern_uid: 'old_subject_ldap_dn',
user: user })
end
it "doesn't create a new identity" do
expect { subject }.not_to change { Identity.count }
end
it "doesn't create a new user" do
expect { subject }.not_to change { User.count }
end
end
end
context 'user does not exist' do context 'user does not exist' do
let(:user) { create(:user) } let(:user) { create(:user) }
......
...@@ -157,12 +157,13 @@ describe SmartcardController, type: :request do ...@@ -157,12 +157,13 @@ describe SmartcardController, type: :request do
end end
let(:ldap_connection) { instance_double(::Net::LDAP) } let(:ldap_connection) { instance_double(::Net::LDAP) }
let(:ldap_email) { 'john.doe@example.com' }
let(:ldap_entry) do let(:ldap_entry) do
Net::LDAP::Entry.new.tap do |entry| Net::LDAP::Entry.new.tap do |entry|
entry['dn'] = subject_ldap_dn entry['dn'] = subject_ldap_dn
entry['uid'] = 'john doe' entry['uid'] = 'john doe'
entry['cn'] = 'John Doe' entry['cn'] = 'John Doe'
entry['mail'] = 'john.doe@example.com' entry['mail'] = ldap_email
end end
end end
let(:ldap_user_search_scope) { 'dc=example,dc=com' } let(:ldap_user_search_scope) { 'dc=example,dc=com' }
...@@ -205,17 +206,37 @@ describe SmartcardController, type: :request do ...@@ -205,17 +206,37 @@ describe SmartcardController, type: :request do
end end
context 'user already exists' do context 'user already exists' do
before do let_it_be(:user) { create(:user) }
user = create(:user)
it 'finds existing user' do
create(:identity, { provider: 'ldapmain', create(:identity, { provider: 'ldapmain',
extern_uid: subject_ldap_dn, extern_uid: subject_ldap_dn,
user: user }) user: user })
end
it 'finds existing user' do
expect { subject }.not_to change { User.count } expect { subject }.not_to change { User.count }
expect(request.env['warden']).to be_authenticated expect(request.env['warden']).to be_authenticated
end end
context "user has a different identity" do
let(:ldap_email) { user.email }
before do
create(:identity, { provider: 'ldapmain',
extern_uid: 'different_identity_dn',
user: user })
end
it "doesn't login a user" do
subject
expect(request.env['warden']).not_to be_authenticated
end
it "doesn't create a new user entry either" do
expect { subject }.not_to change { User.count }
end
end
end end
end end
end end
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