如何通过CredentialManager获取serverAuthCode以兼容后端?
如何通过CredentialManager获取Google登录的serverAuthCode以兼容后端?
我们正在升级应用,采用CredentialManager实现登录,但新方案中无法获取serverAuthCode。由于后端仅接收该参数而非idToken,必须获取它来保持兼容性。
旧实现代码(可正常获取serverAuthCode)
val task = GoogleSignIn.getSignedInAccountFromIntent(activityResult.data) val account = try { task.getResult(ApiException::class.java) } catch (e: ApiException) { // 异常处理 null } val serverAuthCode = account?.serverAuthCode // 调用后端接口
新CredentialManager实现(仅能获取idToken)
val googleIdOption = GetSignInWithGoogleOption.Builder("our serverClientId").build() val request = GetCredentialRequest.Builder() .addCredentialOption(googleIdOption) .build() val credentialManager = CredentialManager.create(context) val response = credentialManager.getCredential(context, request) val credential = response.credential if (credential is CustomCredential && credential.type == TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) { try { val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.data) // 后续逻辑及接口调用 } catch (e: Exception) { // 异常处理 } }
如上所示,新实现仅能获取idToken,无法获取serverAuthCode。我们尝试了授权处理代码,但serverAuthCode始终为null:
val authorizationLauncher = rememberAuthorizationLauncher() val requestedScopes = listOf( Scope(Scopes.PLUS_ME), Scope(Scopes.PROFILE), Scope("https://www.googleapis.com/auth/user.birthday.read"), Scope("https://www.googleapis.com/auth/user.gender.read"), Scope("https://www.googleapis.com/auth/userinfo.email") ) val authorizationRequest = AuthorizationRequest.builder().setRequestedScopes(requestedScopes).build() Identity.getAuthorizationClient(context) .authorize(authorizationRequest) .addOnSuccessListener { authorizationResult -> if (authorizationResult.hasResolution()) { authorizationResult.pendingIntent?.intentSender?.let { intentSender -> authorizationLauncher.launch(IntentSenderRequest.Builder(intentSender).build()) } } else { authorizationResult.serverAuthCode // 始终为null } } @Composable private fun rememberAuthorizationLauncher( activity: Activity = LocalActivity.current ) = rememberLauncherForActivityResult( contract = ActivityResultContracts.StartIntentSenderForResult() ) { activityResult -> if (activityResult.resultCode == Activity.RESULT_OK) { Identity.getAuthorizationClient(activity).getAuthorizationResultFromIntent(activityResult.data) } }
解决方案
要获取有效的serverAuthCode,需要在授权请求中明确配置关键参数,并正确处理授权回调:
1. 修正AuthorizationRequest配置
必须指定后端的Web Client ID和响应类型为CODE,这是获取serverAuthCode的核心要求:
val authorizationLauncher = rememberAuthorizationLauncher() // 保留必要的权限范围,移除已废弃的权限 val requestedScopes = listOf( Scope("https://www.googleapis.com/auth/userinfo.email"), Scope("https://www.googleapis.com/auth/userinfo.profile") ) val authorizationRequest = AuthorizationRequest.builder() .setRequestedScopes(requestedScopes) // 替换为你的Google Cloud Console中Web客户端的Client ID .setServerClientId("your_web_server_client_id") // 指定响应类型为CODE,明确要求返回serverAuthCode .setResponseType(AuthorizationRequest.ResponseType.CODE) .build() Identity.getAuthorizationClient(context) .authorize(authorizationRequest) .addOnSuccessListener { authorizationResult -> if (authorizationResult.hasResolution()) { authorizationResult.pendingIntent?.intentSender?.let { intentSender -> authorizationLauncher.launch(IntentSenderRequest.Builder(intentSender).build()) } } }
2. 正确在回调中提取serverAuthCode
在授权完成后的回调中,从返回的Intent解析出结果并获取serverAuthCode:
@Composable private fun rememberAuthorizationLauncher( activity: Activity = LocalActivity.current ) = rememberLauncherForActivityResult( contract = ActivityResultContracts.StartIntentSenderForResult() ) { activityResult -> if (activityResult.resultCode == Activity.RESULT_OK) { val authorizationResult = Identity.getAuthorizationClient(activity) .getAuthorizationResultFromIntent(activityResult.data) // 这里可以获取到有效的serverAuthCode authorizationResult.serverAuthCode?.let { serverAuthCode -> // 调用后端接口,传入serverAuthCode } } }
关键注意事项
- Server Client ID必须为Web客户端ID:在Google Cloud Console中,创建一个Web类型的OAuth客户端ID,而非Android客户端ID,将其填入
setServerClientId。 - 权限范围精简:移除已废弃的
Scopes.PLUS_ME,保留必要的email和profile范围即可,多余权限可能导致授权流程异常。 - OAuth同意屏幕配置:确保Google Cloud Console中的OAuth同意屏幕已配置正确的应用信息和权限范围,测试阶段可添加测试用户。
内容的提问来源于stack exchange,提问作者Pedro Almeida
相关产品推荐
相关产品推荐

