Issue: user changed google account and can't connect thru his profile


(Mykhailo Poliarush) #1

I have one very active user on my discourse. Everything was fine until a moment when user changed surname and changed his email account. He logged on to discourse thu google authorisation. He changed his email in profile however linked google profile is pointing to an old google account and therefore he got 500 error as in profile email is new but linked google profile is pointing to an old email .

How to overcome this issue?


Change associated Google ID?
Unlink Google authentication
(Jeff Atwood) #2

This is not specific to us – it’s a basic problem of changing an email address on any website.

You cannot log in with credentials unless they point to the same email address, the email address in your Discourse account.


(Mykhailo Poliarush) #3

Previously, i just leaved this and described to user that it can’t be done. User changed email on github, logged in thru github and somehow it was connect to original account. However users still asking how to overcome this as they don’t like to lose profiles with history, bookmarks, badges, etc.

Another case, user was using discourse from work and he was logging in thru company google email for a couple of years. Now he quit, don’t have access to company email and he would like to use his personal google account for this profile with previous history, bookmarks, etc.

Maybe there is a case to make some fix directly in db? Any ideas?


(Sam Saffron) #4

as an admin you can change the email from the user pref page


(Mykhailo Poliarush) #5

The problem is that emails are not matched in email user field and in connected google account therefore user got 500 error during google authorization. Need to change “connected google account” somehow or clean “connected google account” so user can connect right google account. In UI i don’t see such option. I hope you understand what i meant :slight_smile:


(Sam Saffron) #6

What is the error look at logs. Did yo fix the email on the profile?


(Mykhailo Poliarush) #7

what we did

  1. i as admin, changed email on profile
  2. user confirmed new email by link in received email
  3. user do have access to site thru link
  4. but he tries to log in thru google authorization, user got 500 error

I asked user to give me error details however i see error message in logs (fyi, cleaned values)

PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_google_user_infos_on_user_id"
DETAIL:  Key (user_id)=(2512) already exists.
: INSERT INTO "google_user_infos" ("user_id", "google_user_id", "email", "first_name", "last_name", "gender", "name", "profile_link", "picture", "created_at", "updated_at") VALUES (2512, 'xxxxxxxxxxxxxxxxx', 'lxxxxxxx@gmail.com', 'xxxxx', 'xxxxxx', 'male', 'xxxxx xxxxxx', 'https://plus.google.com/xxxxxxxxxxxxxxxxxxxxx', 'https://lh3.googleusercontent.com/-xxxxxxxxxxxxxxxxx/photo.jpg?sz=50', '2016-01-12 08:17:40.260340', '2016-01-12 08:17:40.260340') RETURNING "id"

Any ideas what to do next?


(Sam Saffron) #8

The workaround is simple, but I do want to sort out the root cause

./launcher enter app
rails c
GoogleUserInfo.where(user_id: 2512).destroy_all

(Mykhailo Poliarush) #9

user error looks like this


(Catherine Zavala) #10

Hi, I have a related issue where we need to change the email for a user account in Discourse. I understand I can do this as Admin. This generates a confirmation email to the old email address. The problem is the old email address is no longer a valid address so we are getting Delivery Failure notices.

I saw this post by Kane York- part time developer on Jan '15
"I think you can change it at the external site, then have them log out/log in again? I think that will resync the email address"

Does this mean if I have the user on hand to log in as soon as I reset their password, we can bypass the email confirmation issue?


(Kane York) #11

That was in reference to native SSO, not OAuth logins. It sounds like there’s something different between the Github and Google authenticators causing this issue.


(Michael Brown) #12

We just had this happen again and I think I have a pretty good idea of how it happens:

  • user has email: user@gmail.com, google login: user@gmail.com
  • user changes email to user@discourse.org
  • user logs in with google account user@discourse.org
  • Discourse sees existing account with email user@discourse.org, tries to associate the login with existing (correct) user
  • fails as user already has google account user@gmail.com associated with the Discourse account

(Michael Brown) #14

For future reference, if a user runs into this problem when logging in on an iPad, they get a purely white screen with no error message or any sort of indication of a problem.


(Michael - DiscourseHosting.com) #15

We had a customer running into this as well.

  • User got deactivated in Discourse
  • User got deactivated in Google Apps
  • After some time the User got re-activated in Google Apps (different email address)
  • We reactivated the account on Discourse as well
  • User attempts to log in with Google SSO
  • The process fail with 500 Error

Seems to me that this is caused by blindly trying to create a new record, instead of updating an existing one if that is there (or maybe blindly deleting/creating will work as well)

Lines 24 and 33:


(Jeff Atwood) #16

How do you figure, if records are keyed on email? If the email changed…


(Michael - DiscourseHosting.com) #17

Not entirely sure how that part works, but the main issue is that a GoogleUserInfo record is created for a certain user id, while such a record already exists, causing a unique key violation on user_id.

So instead of

::GoogleUserInfo.create({ user_id: result.user.id }.merge(google_hash))

this should be something like (update scenario)

user_info = ::GoogleUserInfo.find_by(user_id: result.user.id)
if user_info 
  # update the record, dunno how that would look like
else
  ::GoogleUserInfo.create({ user_id: result.user.id }.merge(google_hash))
end

or alternatively something like (blindly delete scenario)

user_info = ::GoogleUserInfo.find_by(user_id: result.user.id)
::GoogleUserInfo.delete({ user_id: result.user.id }) if user_info
::GoogleUserInfo.create({ user_id: result.user.id }.merge(google_hash))

I’m not very fluent with ActiveRecord, maybe there is a better way. But you get the idea :slight_smile:


(Michael Brown) #18

I think we should do two things here:

  • when the user changes their email, scrub their GoogleUserInfo record if it exists. This avoids the common scenario of “I changed my email and now I can’t login via Google”
  • when there is a conflict, report a proper error with a useful way forward

EDIT: after further consideration, if the user can login to the Google account then they have access to the account’s email and could perform a local password reset to gain access (if enabled). So I don’t think we’re introducing any problems by scrubbing any existing GoogleUserInfo record if BOTH the google_user_id and email address are different.


(Michael Brown) #19

Implemented as described - if the google account ID AND email changes, it’ll be replaced, but if only the account ID changes the user will get an error:


User has changed their Google account and cannot login
(Kane York) #20

You should probably create a canonical set of directions for how to resolve the error if you’re going to be pointing people to this topic in the error message.


(Michael Brown) #21

Absolutely… I thought of this as well but hadn’t yet actually done it…

Maybe a support:faq section.

EDIT: It’s a bit of a shift from our current direction, this notion of having an external “online help page” for this kind of situation.

It also doesn’t sit well for translating. But I don’t feel great about having reams of text in the error message itself.

Maybe we just Do It for now and worry about it when it never becomes a problem since it’s so infrequent (we’ve had one report?)

Added: https://meta.discourse.org/t/76575