Where the error appears tells you which side failed.

  • At the provider. Google, Microsoft or Facebook shows an error and the member never comes back: the redirect URI is not registered for the hostname they are on. Register https://<hostname>/oauth/callback/<provider> for every hostname members can sign in from, including aliases, staging and development. The admin's OAuth App Setup tab lists them.
  • A server error as soon as the button is pressed. The provider was switched on before its client ID and secret were filled in.
  • A 404 on the button. The provider is switched off and the button is hardcoded. Build the buttons from enabledOAuthAuthenticators instead.
  • Your site's errors/oauth.html, with HTTP 400. The handshake failed on the way back, and $code says how:
    • invalid_state: the session was lost between leaving and returning. Usually the callback's hostname differs from the one the member started on, so the browser did not send the session cookie. Or they took too long, or finished in another browser.
    • access_denied: they pressed Cancel at the provider.
    • authorization_failed_or_incomplete: the code exchange failed. A wrong or expired client secret, or for Microsoft the wrong tenant.
    • user_authenticator_already_exists_for_user: an account with that email already has another way in. They sign in that way, then connect the provider on the linked-accounts screen.
  • Facebook only: a Facebook account with no email address cannot sign in.

A sign-in that succeeds but creates a second account is a matching problem. An incoming sign-in is matched by email address against usernames, so a member whose username is not their email address gets a new user (which providers are safe to enable).