outline/outline

Handle Google login primary domain changes

markspolakovs opened this issue · 2 comments

At my org we're going through a re-brand, and as part of this we're changing our primary domain. We use Outline with Google SSO and so we switched it for testing, but since the switch any logins fail with a authentication-required notice.

To Reproduce

  1. Set up an Outline instance using Google Workspace SSO (with two domains configured in Google)
  2. Sign in at least once
  3. Change the primary domain on the Workspace user
  4. Sign out and sign in again

Expected behavior
The user can sign in with the same account

Actual behaviour

The user gets a blank error page with ?notice=authentication-required in the URL. In the logs there is this error:

{
  "error": "User authentication 112884385789198496882 already exists for 6c1888fc-9666-4f34-a384-2e3326838823, tried to assign to 615e85f2-8099-4cb9-8e44-a73dd2fa51db",
  "level": "error",
  "message": "Error during authentication",
  "stack": "UnauthorizedError: User authentication 112884385789198496882 already exists for 6c1888fc-9666-4f34-a384-2e3326838823, tried to assign to 615e85f2-8099-4cb9-8e44-a73dd2fa51db\n    at AuthenticationError (/opt/outline/build/server/errors.js:41:34)\n    at accountProvisioner (/opt/outline/build/server/commands/accountProvisioner.js:121:43)\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)"
}

Screenshots
image

Outline:

  • Install: self-hosted
  • Version: docker.getoutline.com/outlinewiki/outline:0.74.0

Desktop:

  • OS: Windows
  • Browser Chrome
  • Version 124

It looks like the error comes from

// We found an authentication record that matches the user id, but it's
// associated with a different authentication provider, (eg a different
// hosted google domain). This is possible in Google Auth when moving domains.
// In the future we may auto-migrate these.
if (auth.authenticationProviderId !== authenticationProviderId) {
throw new Error(
`User authentication ${providerId} already exists for ${auth.authenticationProviderId}, tried to assign to ${authenticationProviderId}`
);
}

I'd be happy to send a PR to fix this, given some guidance on the best way of fixing it.

Unfortunately this is due to the fact that Google uses the domain name as the primary ID. An awful decision that continues to bite everyone that uses it as an auth provider forever.

If you want to easily fix your setup without code changes the easiest thing to do is to find the authentication_provider record in the db and change the providerId to your new domain name.

In a self-hosted environment if the domain matches one in allowed domains we could probably continue to allow sign-in by switching the user authentication to the other provider automatically (the "auto-migrate" mentioned in the comment above)