From 2938daeee9484131ec7fd096051612d124359379 Mon Sep 17 00:00:00 2001 From: PavloNetrebchuk Date: Tue, 21 Jul 2026 13:21:53 +0300 Subject: [PATCH] fix: handle unregistered account on Google/social sign-in The mobile access-token exchange endpoint (AUTH_ENTRY_LOGIN_API) only signs in an already existing/linked account; a first-time or unlinked social identity returns invalid_grant. The Sign In screen previously surfaced this as a generic "Something went wrong". It now shows a specific "This account is not linked with any account. Please register." message (matching iOS), guiding new users to the Register -> Continue with Google flow that creates and links the account. Also fix the Google OAuth scope requested in GoogleAuthHelper: it was a malformed, email-only string ("oauth2: .../userinfo.email") and is now "oauth2:openid .../userinfo.email .../userinfo.profile", matching the iOS/web clients and the server-side google-oauth2 DEFAULT_SCOPE. --- .../presentation/signin/SignInViewModel.kt | 19 ++++++++++++++++++- .../auth/presentation/sso/GoogleAuthHelper.kt | 16 +++++++++++++++- auth/src/main/res/values/strings.xml | 1 + 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/auth/src/main/java/org/openedx/auth/presentation/signin/SignInViewModel.kt b/auth/src/main/java/org/openedx/auth/presentation/signin/SignInViewModel.kt index 395cf7ec5..e7053f2c6 100644 --- a/auth/src/main/java/org/openedx/auth/presentation/signin/SignInViewModel.kt +++ b/auth/src/main/java/org/openedx/auth/presentation/signin/SignInViewModel.kt @@ -34,6 +34,7 @@ import org.openedx.core.system.notifier.app.AppUpgradeEvent import org.openedx.core.system.notifier.app.SignInEvent import org.openedx.core.utils.Logger import org.openedx.foundation.presentation.BaseViewModel +import org.openedx.foundation.presentation.UIMessage import org.openedx.foundation.system.ResourceManager import org.openedx.core.R as CoreRes @@ -217,7 +218,23 @@ class SignInViewModel( interactor.loginSocial(token, authType) }.onFailure { error -> logger.e { "Social login error: $error" } - onUnknownError() + if (error is EdxError.InvalidGrantException) { + // The social identity resolved on Google's side but is not linked to any + // account on this platform. The mobile token-exchange endpoint only signs in + // existing/linked users, so guide the user to register (mirrors iOS/web). + sendMessage( + UIMessage.SnackBarMessage( + resourceManager.getString( + R.string.auth_social_account_not_registered, + authType.methodName, + configuration.getPlatformName(), + ) + ) + ) + _uiState.update { it.copy(showProgress = false) } + } else { + onUnknownError() + } }.onSuccess { logger.d { "Social login (${authType.methodName}) success" } _uiState.update { it.copy(loginSuccess = true) } diff --git a/auth/src/main/java/org/openedx/auth/presentation/sso/GoogleAuthHelper.kt b/auth/src/main/java/org/openedx/auth/presentation/sso/GoogleAuthHelper.kt index 99985b882..c5e2ced6e 100644 --- a/auth/src/main/java/org/openedx/auth/presentation/sso/GoogleAuthHelper.kt +++ b/auth/src/main/java/org/openedx/auth/presentation/sso/GoogleAuthHelper.kt @@ -105,6 +105,20 @@ class GoogleAuthHelper(private val config: Config) { private companion object { const val TAG = "GoogleAuthHelper" - const val SCOPE = "oauth2: https://www.googleapis.com/auth/userinfo.email" + + /** + * Scopes requested for the Google access token that is exchanged on the backend via + * `/oauth2/exchange_access_token/google-oauth2/`. + * + * Must match the scopes expected by the server-side social-auth `google-oauth2` backend + * (`DEFAULT_SCOPE = ["openid", "email", "profile"]`) and the iOS/web clients. Requesting + * only `userinfo.email` yields a token whose `userinfo` response lacks the profile/name + * claims, so first-time SSO account creation fails and the exchange returns + * `invalid_grant` ("access_token is not valid"). The `oauth2:` prefix is immediately + * followed by a space-separated scope list (no leading space). + */ + const val SCOPE = "oauth2:openid " + + "https://www.googleapis.com/auth/userinfo.email " + + "https://www.googleapis.com/auth/userinfo.profile" } } diff --git a/auth/src/main/res/values/strings.xml b/auth/src/main/res/values/strings.xml index 77401c27f..9838dab6b 100644 --- a/auth/src/main/res/values/strings.xml +++ b/auth/src/main/res/values/strings.xml @@ -10,6 +10,7 @@ Email or Username Invalid email or username Password is too short + This %1$s account is not linked with any %2$s account. Please register. Welcome back! Sign in to access your courses. Show optional fields Hide optional fields