diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb index c483d6f4b7..31f9a29ac3 100644 --- a/app/controllers/omniauth_callbacks_controller.rb +++ b/app/controllers/omniauth_callbacks_controller.rb @@ -2,8 +2,13 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController def openid_connect - OidcAccount.link(spree_current_user, request.env["omniauth.auth"]) + ActiveRecord::Base.transaction do + OidcAccount.link(spree_current_user, request.env["omniauth.auth"]) + end + redirect_to admin_oidc_settings_path + rescue ActiveRecord::RecordNotUnique + flash[:error] = t("devise.oidc.record_not_unique", uid: request.env["omniauth.auth"].uid) redirect_to admin_oidc_settings_path end diff --git a/config/locales/en.yml b/config/locales/en.yml index 946f9c24d7..6e5d5f6f3d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -321,6 +321,7 @@ en: send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes." oidc: failure: "Could not sign in: %{error}" + record_not_unique: "%{uid} is already associated with another account" home_page_alert_html: "Home page alert HTML" hub_signup_case_studies_html: "Hub signup case studies HTML" hub_signup_detail_html: "Hub signup detail HTML" diff --git a/spec/requests/omniauth_callbacks_controller_spec.rb b/spec/requests/omniauth_callbacks_controller_spec.rb index aef5ef69d6..6c02540b33 100644 --- a/spec/requests/omniauth_callbacks_controller_spec.rb +++ b/spec/requests/omniauth_callbacks_controller_spec.rb @@ -35,6 +35,20 @@ RSpec.describe '/user/spree_user/auth/openid_connect/callback', type: :request d expect(account.uid).to eq "ofn@example.com" expect(response.status).to eq(302) end + + context 'when OIDC account already linked with a different user' do + before do + create(:user, email: "ofn@elsewhere.com") + .create_oidc_account!(uid: "ofn@example.com") + end + + it 'fails with error message' do + expect { request! }.not_to change { OidcAccount.count } + + expect(response.status).to eq(302) + expect(flash[:error]).to match "ofn@example.com is already associated with another account" + end + end end context 'when the omniauth openid_connect is mocked with an error' do @@ -46,6 +60,7 @@ RSpec.describe '/user/spree_user/auth/openid_connect/callback', type: :request d expect { request! }.not_to change { OidcAccount.count } expect(response.status).to eq(302) + expect(flash[:error]).to match "Could not sign in" end end end