Android Google登录报错BAD_AUTHENTICATION及无凭证问题求助
解决Google登录CredentialManager抛出"No credentials available"及BAD_AUTHENTICATION错误
问题现象
点击Google登录按钮时,Logcat输出:
[RequestTokenManager] getToken() -> BAD_AUTHENTICATION。应用:com.example.packagename,服务:oauth2:openidamnk: Long live credential not available。
同时捕获到No credentials available异常,现有3年以上的解决方案均无效,相关代码如下:
fun sighInWithGoogle( context: Context, auth: FirebaseAuth ) { val rawNonce = UUID.randomUUID().toString() val bytes = rawNonce.toByteArray() val md = MessageDigest.getInstance("SHA-256") val digest = md.digest(bytes) val hashedNonce = digest.fold("") { str, it -> str + "%02x".format(it) } val googleIdOption: GetGoogleIdOption = GetGoogleIdOption.Builder() .setFilterByAuthorizedAccounts(true) .setServerClientId(context.getString(R.string.web_client_id)) .setAutoSelectEnabled(true) .setNonce(hashedNonce) .build() val googleSignRequest: GetCredentialRequest = GetCredentialRequest.Builder() .addCredentialOption(googleIdOption) .build() val credentialManager = CredentialManager.create(context) CoroutineScope(Dispatchers.IO).launch { try { val result = credentialManager.getCredential( request = googleSignRequest, context = context, ) handleGoogleSignIn(context, auth, result) } catch (e: GetCredentialException) { handleGoogleSignInFailure(context, e) } } } private fun handleGoogleSignInFailure(context: Context, e: Exception) { Log.e("TAG", "Unexpected error: ${e.message.toString()}") postToastMessage("Google Login Failed: ${e.message.toString()}") }
针对性解决方案
1. 调整授权账户过滤规则
代码中setFilterByAuthorizedAccounts(true)会仅筛选已授权过当前应用的Google账户,如果用户是首次登录或清除过授权,就会找不到可用凭证。
- 将其改为
setFilterByAuthorizedAccounts(false),允许展示所有已登录的Google账户供选择; - 或者保留
true,但在捕获NoCredentialException时启动账户选择流程(见下文异常处理优化)。
2. 优化异常处理逻辑
当前仅笼统捕获GetCredentialException,无法区分具体场景并处理。修改捕获逻辑:
CoroutineScope(Dispatchers.IO).launch { try { val result = credentialManager.getCredential( request = googleSignRequest, context = context, ) handleGoogleSignIn(context, auth, result) } catch (e: NoCredentialException) { // 无可用凭证,启动账户选择界面 withContext(Dispatchers.Main) { val intent = credentialManager.createGetCredentialIntent(googleSignRequest) (context as Activity).startActivityForResult(intent, REQUEST_CODE_GOOGLE_SIGN_IN) } } catch (e: GetCredentialException) { handleGoogleSignInFailure(context, e) } }
随后在Activity的onActivityResult或registerForActivityResult中处理返回的凭证。
3. 验证Web Client ID配置
- 确认
strings.xml中的web_client_id与Google Cloud Console中创建的OAuth 2.0 Web应用客户端ID完全一致; - 检查该客户端ID已正确关联应用的SHA-1指纹(包括debug和release版本)。
4. 确保Google Play服务版本
CredentialManager依赖最新版Google Play服务,要求设备上的Play服务版本不低于20.0.0,可提示用户更新Play服务,或在build.gradle中指定依赖版本:
implementation "com.google.android.libraries.identity.googleid:googleid:1.1.0" implementation "androidx.credentials:credentials:1.2.0" implementation "androidx.credentials:credentials-play-services-auth:1.2.0"
5. 关闭AutoSelect(可选)
setAutoSelectEnabled(true)会尝试自动选择已保存的凭证,如果没有则直接抛出异常,可暂时关闭该选项,强制用户手动选择账户,排查是否为自动选择逻辑导致的问题。
内容的提问来源于stack exchange,提问作者Axes Grinds
相关产品推荐
相关产品推荐

