0

I'm trying to get the user account information from google like birthdate , gender and other user data but i get this exception while using people API

W/System.err: com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
  "code" : 403,
  "errors" : [ {
    "domain" : "global",
    "message" : "The request is missing a valid API key.",
    "reason" : "forbidden"
  } ],
  "message" : "The request is missing a valid API key.",
  "status" : "PERMISSION_DENIED"
}

i didn't know where to add my api key to solve my exception here is my code

package com.example.MyApp.ui.activities;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;

import com.example.myApp.R;
import com.example.myApp.utils.PreferenceController;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
import com.google.android.gms.common.SignInButton;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.tasks.Task;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest;
import com.google.api.client.googleapis.auth.oauth2.GoogleBrowserClientRequestUrl;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.people.v1.PeopleService;
import com.google.api.services.people.v1.model.Person;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

public class LoginActivity extends AppCompatActivity {
    private final String TAG = "LoginActivity";
    private SignInButton loginWithGoogleAccountBtn;
    private static final int RC_SIGN_IN = 1;
    AccountManager accountManager;
    GoogleSignInClient mGoogleSignInClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                .requestEmail()
                .build();
// Build a GoogleSignInClient with the options specified by gso.
        mGoogleSignInClient = GoogleSignIn.getClient(this, gso);

        loginWithGoogleAccountBtn = findViewById(R.id.loginWithGoogleAccountBtn);
        loginWithGoogleAccountBtn.setSize(SignInButton.SIZE_STANDARD);
        loginWithGoogleAccountBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                signIn();


            }

        });
    }

    private void signIn() {
        Intent signInIntent = mGoogleSignInClient.getSignInIntent();
        startActivityForResult(signInIntent, RC_SIGN_IN);
    }

    @Override
    protected void onStart() {
        super.onStart();
        GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
        if (account != null) {
            Toast.makeText(this, "account : " + account.getDisplayName() + " : email " + account.getEmail() + "account id " + account.getId(), Toast.LENGTH_SHORT).show();
            try {
                getAccountData(account);
            } catch (IOException e) {
                e.printStackTrace();
            }
            redirectToMain();
        }
    }

    public void getAccountData(final GoogleSignInAccount account) throws IOException {
        Thread myThread = new Thread() {
            @Override
            public void run() {
                HttpTransport httpTransport = new NetHttpTransport();
                JacksonFactory jsonFactory = new JacksonFactory();
                String clientId = Constant.CLIENT_ID;
                String clientSecret = Constant.CLIENT_SECRET;
                GoogleCredential credential = new GoogleCredential.Builder()
                        .setTransport(httpTransport)
                        .setJsonFactory(jsonFactory)

                        .setClientSecrets(clientId, clientSecret)
                        .build();

                PeopleService peopleService =
                        new PeopleService.Builder(httpTransport, jsonFactory, credential).setApplicationName("MyApp").
                                build();
                try {

                    Person profile = peopleService.people().get("people/" + account.getId())
                            .setPersonFields("names,genders")
                            .setAccessToken(account.getIdToken())
                            .execute();

                    Log.i(TAG, profile.getGenders().get(0).getValue());
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };
        myThread.start();


    }


    private void redirectToMain() {

        Intent intent = new Intent(LoginActivity.this, MainActivity.class);
        startActivity(intent);
    }

    private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
        try {
            GoogleSignInAccount account = completedTask.getResult(ApiException.class);

        } catch (ApiException e) {
            // The ApiException status code indicates the detailed failure reason.
            // Please refer to the GoogleSignInStatusCodes class reference for more information.
            e.printStackTrace();
            Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());

        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data
        if (requestCode == RC_SIGN_IN) {
            Log.i(TAG, "onActivityResult: ");
            Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
            handleSignInResult(task);
        }

    }
}

the exception with my person object after getting google account from the intent the exception is appeared here

Person profile = peopleService.people().get("people/" + account.getId())
                        .setPersonFields("names,genders")
                        .setAccessToken(account.getIdToken())
                        .execute();
Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
BlackAndWhite
  • 55
  • 2
  • 9
  • Hello, based on the error message that you are getting I believe the issue may be on the credentials you obtain from your account using `account.getIdToken()`. Could you try logging them right before the call, using something such as `Log.i(TAG, account.getIdToken())`? What do you obtain from that? Cheers – carlesgg97 Dec 03 '19 at 11:37
  • it returns null but when i remove setAccessToken from Person object. i have the same exception – BlackAndWhite Dec 03 '19 at 12:04
  • Hey @BlackAndWhite, I provided an answer that should fix your issue. Kindly let me know whether that works for you. Cheers! – carlesgg97 Dec 03 '19 at 12:26

1 Answers1

1

When calling account.getIdToken(), the value returned by it is null.

That is because when creating your GoogleSignIn you are not requesting an Id Token.

The Id Token has to be explicitly requested for, which you can do as follows:

  • Replace the following code:
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                                                     .requestEmail()
                                                     .build();
    
    For the following:
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                                                     .requestIdToken("YOUR_OAUTH_CLIENT_ID")
                                                     .requestEmail()
                                                     .build();
    
    Where the YOUR_OAUTH_CLIENT_ID string should be replaced for your actual OAuth Client Id.
carlesgg97
  • 4,184
  • 1
  • 8
  • 24
  • I tried your solution but i'm still have the same exception and account.getIdtoken returns null. if there is another solution let me know. Thanks – BlackAndWhite Dec 03 '19 at 12:31
  • @BlackAndWhite Thanks for your answer. Could you check in the Google Developers Console the credentials you created? Kindly make sure that the application type of your credentials is `Web application` (And not Android or Other). In case it is not, please create new credentials with it, and replace them in your project. – carlesgg97 Dec 03 '19 at 12:36
  • i create new credintial for OAuth client id with web application as you said and change the requestIdToken with the new id but i still have the same error with the null idToken – BlackAndWhite Dec 03 '19 at 15:09
  • @BlackAndWhite Did you also change the `clientId` and `clientSecret` variables in your code? (`run()` function). Also, if you are using any credentials caching, please make sure to remove them (find a "tokens" folder in your project, and in case it exists, delete the "StoredCredential" file). Make sure that the OAuth authentication flow is properly running - it asks you to manually log in and accept the scopes the application is using – carlesgg97 Dec 03 '19 at 15:25
  • @BlackAndWhite Perhaps this other issue can help you: https://stackoverflow.com/questions/34111978/why-is-requestidtoken-returning-null – carlesgg97 Dec 03 '19 at 15:27