Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Migrating from Google Sign-In for Android to Firebase Authentication

Currently, we plan to use Google Sign-In for Android, as our server authentication method.

This is what we plan to do.

Client side (Google Sign-In for Android)

GoogleSignInAccount account = completedTask.getResult(ApiException.class);
// This idToken will sent to backend server.
String idToken = account.getIdToken();

Server side (Google Sign-In for Android)

// Based on received idToken from client, backend server will call https://www.googleapis.com/oauth2/v3/tokeninfo?id_token=... 
// to identify who is this user.

{
 // These six fields are included in all Google ID Tokens.
 "iss": "https://accounts.google.com",
 "sub": "110169484474386276334",
 "azp": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "aud": "1008719970978-hb24n2dstb40o45d4feuo2ukqmcc6381.apps.googleusercontent.com",
 "iat": "1433978353",
 "exp": "1433981953",

 // These seven fields are only included when the user has granted the "profile" and
 // "email" OAuth scopes to the application.
 "email": "[email protected]",
 "email_verified": "true",
 "name" : "Test User",
 "picture": "https://lh4.googleusercontent.com/-kYgzyAWpZzJ/ABCDEFGHI/AAAJKLMNOP/tIXL9Ir44LE/s99-c/photo.jpg",
 "given_name": "Test",
 "family_name": "User",
 "locale": "en"
}

In the future, we might want to migrate to provide more login option. This is my future migration plan, to migrate from Google Sign-In for Android to Firebase Authentication.

Client side (Firebase Authentication)

FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();
mUser.getIdToken(true)
    .addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
        public void onComplete(@NonNull Task<GetTokenResult> task) {
            if (task.isSuccessful()) {
                // This idToken will sent to backend server.
                String idToken = task.getResult().getToken();

            } else {
                // Handle error -> task.getException();
            }
        }
    });

Server side (Google Sign-In for Android)

# idToken comes from the client app (shown above)
decoded_token = auth.verify_id_token(idToken)
uid = decoded_token['uid']

My questions are

  1. For Google Sign-In for Android, We plan to store "sub": "110169484474386276334", as an unique identifier to represent a user. Is that a correct field to be used? Is it unique per user? My testing so far is, at client side, we might get different idToken for a same user (At different day). Different idToken from same user, will still yield same sub at server side.

  2. One day, we might migrate to Firebase Authentication to support more login methods. Is it still backward compatible with Google Sign-In for Android. Is Firebase Authentication able to return same "sub" as what is previously returned by Google Sign-In for Android? As you can see in the code example, Firebase Authentication is returning uid.

How can I compare new Firebase Authentication's uid, with previous stored Google Sign-In's sub?

like image 957
Cheok Yan Cheng Avatar asked Dec 14 '18 11:12

Cheok Yan Cheng


People also ask

How do I use Google authentication with Firebase?

In the Firebase console, open the Auth section. On the Sign in method tab, enable the Google sign-in method and click Save.

Can I use Firebase just for authentication?

You can use Firebase Authentication to allow users to sign in to your app using one or more sign-in methods, including email address and password sign-in, and federated identity providers such as Google Sign-in and Facebook Login.

How to initialize Firebase Auth in Android?

To register a user with email and password, firstly, you have to declare an instance of FirebaseAuth. Now, in the onCreate() method, initialize the FirebaseAuth instance. To signup a user with email and password, we can take the help of createUserWithEmailAndPassword() method.


1 Answers

Q1: is basically answered here:

A Google account's email address can change, so don't use it to identify a user. Instead, use the account's ID, which you can get on the client with GoogleSignInAccount.getId(), and on the backend from the sub claim of the ID token.

Q2: Google as Auth provider for Firebase still uses the same Google sign-in flow (in the beginning), while it then authenticates the user against a Firebase project, as well.

there's an example which shows it:

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

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
    if (requestCode == REQUESTCODE_SIGN_IN) {

        Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
        try {

            // Google Sign In was successful
            GoogleSignInAccount account = task.getResult(ApiException.class);
            String idToken = account.getIdToken();
            // Send token to your backend via HTTPS

            // authenticate with Firebase
            firebaseAuthWithGoogle(account);

        } catch (ApiException e) {
            Log.w(TAG, "Google sign in failed", e);
        }
    }
}

where GoogleSignInAccount account is still the same response.

edit: one can even verify the ID token from FirebaseAuth alike this:

FirebaseUser mUser = FirebaseAuth.getInstance().getCurrentUser();

mUser.getIdToken(true).addOnCompleteListener(new OnCompleteListener<GetTokenResult>() {
    public void onComplete(@NonNull Task<GetTokenResult> task) {
        if (task.isSuccessful()) {

            String idToken = task.getResult().getToken();
            // Send token to your backend via HTTPS

        } else {
            // Handle error -> task.getException();
        }
    }
});
like image 159
Martin Zeitler Avatar answered Oct 21 '22 07:10

Martin Zeitler