Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get serverAuthCode using Credential Manager

We are updating our application to use the CredentialManager for logging in, but we are not finding a way to get the serverAuthCode from this new implementation. We need this information to maintain compatibility with our backend, which expects this information instead of the idToken.

Our old implementation:

val task = GoogleSignIn.getSignedInAccountFromIntent(activityResult.data)
val account = try {
    task.getResult(ApiException::class.java)
} catch (e: ApiException) {
    // Something treatment here
    null
}
val serverAuthCode = account?.serverAuthCode
// endpoint call

New implementation:

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)
        // rest of the code and endpoint call

As I mentioned above, in this new implementation, it is not possible to get the serverAuthCode, only the idToken.

How should we go about getting the serverAuthCode and maintaining compatibility with our backend?

Here’s how I’m handling the authorization:

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 // always 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)
    }
}

like image 284
Pedro Almeida Avatar asked Oct 18 '25 14:10

Pedro Almeida


1 Answers

The solution for this is to request offline access when building the authorization request:

AuthorizationRequest.builder()
    .setRequestedScopes(requestedScopes)
    .requestOfflineAccess(SERVER_CLIENT_ID) // THIS!
    .build()

See a working sample here

like image 88
Eury Pérez Beltré Avatar answered Oct 21 '25 03:10

Eury Pérez Beltré



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!