For full context, I have an android application which communicates with a php server. I am able to successfully login to a google account using this function from android level (kotlin):
val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestServerAuthCode(getString(R.string.default_web_client_id))
.requestEmail()
.build()
val googleSignInClient = GoogleSignIn.getClient(requireContext(), gso)
val view = inflater.inflate(R.layout.fragment_social_login, container, false)
val googleSignUpButton = view.findViewById<ImageButton>(R.id.googleSignUpButton)
someActivityResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result: ActivityResult ->
val data: Intent? = result.data
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
try {
val account = task.getResult(ApiException::class.java)!!
validateToken(account.idToken!!)
} catch (e: ApiException) {
Log.w("SocialLoginFragment", "Google sign in failed", e)
}
}
private fun firebaseAuthWithGoogle(idToken: String) {
val credential = GoogleAuthProvider.getCredential(idToken, null)
auth.signInWithCredential(credential)
.addOnCompleteListener(requireActivity()) { task ->
if (task.isSuccessful) {
val user = auth.currentUser
Toast.makeText(requireContext(), user?.email, Toast.LENGTH_SHORT).show()
} else {
Log.w("SocialLoginFragment", "signInWithCredential:failure", task.exception)
}
}
}
the **"validateToken" **calls the GET request https://www.googleapis.com/oauth2/v3/tokeninfo?id_token= and verifies if the id_token is valid, which is the case. **"firebaseAuthWithGoogle" **just shows the user's mail in Toast. but when i pass that id token to my PHP backend server, it returns Invalid credentials, to be specific this my Hybridauth snippet
$idToken = "ID_TOKEN"; //same id token generated previously from android after login success
$clientId = "CLIENT_ID";
$secretKey = "SECRET_KEY";
$callback = "https://baseurl/index.php/sociallogin/social/callback/?hauth.done=Google";
$config = [
'callback' => $callback,
'keys' => ['id' => $clientId, 'secret' => $secretKey],
'scope' => 'https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/userinfo.profile',
'authorize_url_parameters' => [
'approval_prompt' => 'force',
'access_type' => 'offline'
]
];
try {
$hybridauth = new Hybridauth\Hybridauth($config);
$adapter = new \Hybridauth\Provider\Google($config);
$adapter->setAccessToken([
'access_token' => $idToken
]);
$profile = $adapter->getUserProfile();
} catch (\Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "\n";
}
expected output: user info
current output:
Caught exception: Signed API request to https://www.googleapis.com/oauth2/v3/userinfo has returned an error. HTTP error 401. Raw Provider API response: {
"error": "invalid_request",
"error_description": "Invalid Credentials"
}.
I could've sworn that it worked perfectly earlier this year. Any help would be appreciated.
UPDATE:
I have resolved the problem by using authorization code instead of id token to get the access token, i was confusing between id token and access token. Here is my updated code for both kotlin and php sides
Android:
someActivityResultLauncher = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) { result: ActivityResult ->
....
val authCode = account?.serverAuthCode
Log.d(TAG,"$authCode") //i have copied the console output into the php code
}}
Php:
$config = ....
$client = new Google_Client();
$client->setClientId('1000593837042-il6hm8f4b3grahtpo4c2s0esggagl2dn.apps.googleusercontent.com');
$client->setClientSecret('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');
$authCode= //here i paste my authCode from the android console
$tokenArray = $client->fetchAccessTokenWithAuthCode($authCode);
try {
$accessToken = $tokenArray['access_token'];
$hybridauth = new Hybridauth\Hybridauth($config);
$adapter = new \Hybridauth\Provider\Google($config);
$adapter->setAccessToken([
'access_token' => $accessToken
]);
$profile = $adapter->getUserProfile();
echo $profile->email //outputs the email ;
if there's anything still unclear, feel free to reach out.