You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 01:53:15