简体   繁体   中英

Recent changes with Firebase Authentication via. Google Sign-In?

I've a question to people who use Firebase Google Sign-In authentication:

My app, which has already been working for a couple of months, is using both Google Sign-In and e-mail/password options for Firebase Authentication. However about a week ago I've noticed that the Google Sign-In stopped working. No code was changed, also the e-mail/password option works just as usual.

I've checked the documentation ( https://firebase.google.com/docs/auth/android/google-signin ), it's still the same (My app copies the authentication method from the documentation).

Did you face a similar problem too? If yes, please tell me how can I solve it.

Here is my code related to Google Sign-in inside my LoginActivity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    ...   
    //--------Google Sign In
    GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
            .requestIdToken(getString(R.string.default_web_client_id))
            .requestEmail()
            .build();

    mGoogleApiClient = new GoogleApiClient.Builder(this)
            .enableAutoManage(this, new GoogleApiClient.OnConnectionFailedListener() {
                @Override
                public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
                    Toast.makeText(LoginActivity.this, "Connection failed!", Toast.LENGTH_SHORT).show();
                }
            })
            .addApi(Auth.GOOGLE_SIGN_IN_API, gso)
            .build();

    mGoogleBttn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            SignIn();
        }
    });

}

private void SignIn() {
    Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
    startActivityForResult(signInIntent, RC_SIGN_IN);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    mProgress.setMessage("Signing in with Google Account...");
    mProgress.show();
    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
    if (requestCode == RC_SIGN_IN) {
        GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);

        if (result.isSuccess()) {
            // Google Sign In was successful, authenticate with Firebase
            GoogleSignInAccount account = result.getSignInAccount();
            firebaseAuthWithGoogle(account);
        } else {
            // Google Sign In failed, update UI appropriately
            // ...
            mProgress.dismiss();
            Toast.makeText(LoginActivity.this, "Google sign in failed!", Toast.LENGTH_SHORT).show();
        }
    }
}

private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
    Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId());

    AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
    mAuth.signInWithCredential(credential)
            .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
                @Override
                public void onComplete(@NonNull Task<AuthResult> task) {
                    Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());

                    mProgress.dismiss();
                    checkUserExist();

                    // If sign in fails, display a message to the user. If sign in succeeds
                    // the auth state listener will be notified and logic to handle the
                    // signed in user can be handled in the listener.
                    if (!task.isSuccessful()) {
                        Log.w(TAG, "signInWithCredential", task.getException());
                        Toast.makeText(LoginActivity.this, "Authentication failed.",
                                Toast.LENGTH_SHORT).show();
                    }
                }
            });
}

private void checkUserExist() {
    final String user_id = mAuth.getCurrentUser().getUid();
    mDatabaseUsers.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot.hasChild(user_id)) {
                Intent mainIntent = new Intent(LoginActivity.this, MainActivity.class);
                mainIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(mainIntent);
            } else {
                Intent setupIntent = new Intent(LoginActivity.this, SetupActivity.class);
                setupIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(setupIntent);
            }
        }
        @Override
        public void onCancelled(DatabaseError databaseError) {
        }
    });
}

Here are my app and project level build.gradle files: https://gist.github.com/anonymous/2c9737e898ca2568129af63e61a30f16

As OP has found the solution to the problem and answered it already. I'll be trying to explain the cases, as requested by OP, that might be the real causes behind the problem. Before that lets know something about keystores and certificates .

The documentation says:

Android requires that all APKs be digitally signed with a public-key certificate before they can be installed. Even that application you build and run during the development period must be signed with a certificate. If you don't do it manually Android Studio automatically signs your APK with a debug certificate generated by the Android SDK tools. The first time you run or debug your project in Android Studio, the IDE automatically creates the debug keystore and certificate in $HOME/.android/debug.keystore , and sets the keystore and key passwords. A public-key certificate, also known as a digital certificate or an identity certificate, contains the public key of a public/private key pair, as well as some other metadata identifying the owner of the key (for example, name and location). The owner of the certificate holds the corresponding private key.

When you sign an APK, the signing tool attaches the public-key certificate to the APK. The public-key certificate serves as as a "fingerprint" that uniquely associates the APK to you and your corresponding private key. This helps Android ensure that any future updates to your APK are authentic and come from the original author.

A keystore is a binary file that contains one or more private keys.

Every app must use the same certificate throughout its lifespan in order for users to be able to install new versions as updates to the app.

Back to the question; after studying the OP's problem and with a short conversation with him I came up with following deduction:

  • He must be using one keystore/certificate for development and different certificate for Project Setting(firebase console).
  • Since, Google Sign-In was working fine for a couple of months but stopped lately, he must have changed the keystore lately.
  • Found that he has just migrated to new development device and hence the app he build now might have a new debug keystore file and new certificate which shall be, in fact, different from that in Project Setting.

The case is still a mystery, I later knew that the OP never built or ran his app from the new device.

PS Android Studio automatically creates the debug keystore and certificate in $HOME/.android/debug.keystore, and sets the keystore and key passwords the first time you run or debug your project. This mean that every computer you work on will generate a new SHA-1 unless you have a copy of a previous keystore file and you use it.

Okay, I'll admit one thing - it had nothing to do with the code... I managed to fix the issue, and I'll explain how.

I debugged the app with the debugger as I was recommended by good people inside the comments and it turned out that inside the onActivityResult() method the Auth.GoogleSignInApi.getSignInResultFromIntent(data) was returning this error result code:

Status{statusCode=DEVELOPER_ERROR, resolution=null}

This was more than enough to understand where to dig. I looked up into my Firebase console -> Project -> Project settings -> SHA-1 fingerprints.

What is interesting - there was a fingerprint there, the one I've put before. Anyways, I decided to check if it's the same with the one I get from Android Studio -> Gradle Projects -> inside the project/app/tasks/android/ folder there is a signingReport which contains SHA-1. To my surprise, the SHA-1 fingerprints did not match. Anyways, I copied it from the AS and added 2nd line inside Firebase Console. Guess what? It works now...

I still have a lot of questions about why this could happened, since it did happen all of a sudden as I explained previously in my question.

I hope this info will help others who had a similar issue. Nevertheless, question solved, but since there is a bounty set I'll award it to the person, who'll explain me this magic...

This might be the case -

  • In your device, you have added just one email account which is not authorized in your app. Other than this, there is no other account added in your device.
  • So when you click on your 'Sign in with Google' button, it automatically takes that email account. But it is not authorized so it fails.

Solution - Add your authorized account in your device. Now when you click on 'Sign in with Gooogle', it will show a pop up and ask you which account you want to choose. Select the correct one and you must be able to login. Hope that helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM