diff --git a/auth/app/build.gradle.kts b/auth/app/build.gradle.kts index 01bbd4e00..2188f391c 100644 --- a/auth/app/build.gradle.kts +++ b/auth/app/build.gradle.kts @@ -49,6 +49,11 @@ dependencies { // [START gradle_firebase_ui_auth] implementation("com.firebaseui:firebase-ui-auth:8.0.2") + // Google Identity Services SDK (only required for Auth with Google) + implementation("androidx.credentials:credentials:1.3.0") + implementation("androidx.credentials:credentials-play-services-auth:1.3.0") + implementation("com.google.android.libraries.identity.googleid:googleid:1.1.1") + // Required only if Facebook login support is required // Find the latest Facebook SDK releases here: https://goo.gl/Ce5L94 implementation("com.facebook.android:facebook-android-sdk:4.42.0") diff --git a/auth/app/src/main/java/com/google/firebase/quickstart/auth/GoogleSignInActivity.java b/auth/app/src/main/java/com/google/firebase/quickstart/auth/GoogleSignInActivity.java index a95c31f0b..e8121ec4e 100644 --- a/auth/app/src/main/java/com/google/firebase/quickstart/auth/GoogleSignInActivity.java +++ b/auth/app/src/main/java/com/google/firebase/quickstart/auth/GoogleSignInActivity.java @@ -16,57 +16,61 @@ package com.google.firebase.quickstart.auth; -import android.app.Activity; -import android.content.Intent; +import static com.google.android.libraries.identity.googleid.GoogleIdTokenCredential.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL; + import android.os.Bundle; +import android.os.CancellationSignal; import android.util.Log; import androidx.annotation.NonNull; - -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.api.ApiException; -import com.google.android.gms.tasks.OnCompleteListener; -import com.google.android.gms.tasks.Task; +import androidx.appcompat.app.AppCompatActivity; +import androidx.credentials.ClearCredentialStateRequest; +import androidx.credentials.Credential; +import androidx.credentials.CredentialManager; +import androidx.credentials.CredentialManagerCallback; +import androidx.credentials.CustomCredential; +import androidx.credentials.GetCredentialRequest; +import androidx.credentials.GetCredentialResponse; +import androidx.credentials.exceptions.ClearCredentialException; +import androidx.credentials.exceptions.GetCredentialException; +import com.google.android.libraries.identity.googleid.GetGoogleIdOption; +import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential; import com.google.firebase.auth.AuthCredential; -import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.FirebaseAuth; import com.google.firebase.auth.FirebaseUser; import com.google.firebase.auth.GoogleAuthProvider; +import java.util.concurrent.Executors; /** * Demonstrate Firebase Authentication using a Google ID Token. */ -public class GoogleSignInActivity extends Activity { +public class GoogleSignInActivity extends AppCompatActivity { private static final String TAG = "GoogleActivity"; - private static final int RC_SIGN_IN = 9001; // [START declare_auth] private FirebaseAuth mAuth; // [END declare_auth] - private GoogleSignInClient mGoogleSignInClient; + // [START declare_credential_manager] + private CredentialManager credentialManager; + // [END declare_credential_manager] @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // [START config_signin] - // Configure Google Sign In - GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) - .requestIdToken(getString(R.string.default_web_client_id)) - .requestEmail() - .build(); - - mGoogleSignInClient = GoogleSignIn.getClient(this, gso); - // [END config_signin] // [START initialize_auth] // Initialize Firebase Auth mAuth = FirebaseAuth.getInstance(); // [END initialize_auth] + + // [START initialize_credential_manager] + // Initialize Credential Manager + credentialManager = CredentialManager.create(getBaseContext()); + // [END initialize_credential_manager] + + launchCredentialManager(); } // [START on_start_check_user] @@ -79,55 +83,101 @@ public void onStart() { } // [END on_start_check_user] - // [START onactivityresult] - @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 == RC_SIGN_IN) { - Task task = GoogleSignIn.getSignedInAccountFromIntent(data); - try { - // Google Sign In was successful, authenticate with Firebase - GoogleSignInAccount account = task.getResult(ApiException.class); - Log.d(TAG, "firebaseAuthWithGoogle:" + account.getId()); - firebaseAuthWithGoogle(account.getIdToken()); - } catch (ApiException e) { - // Google Sign In failed, update UI appropriately - Log.w(TAG, "Google sign in failed", e); - } + private void launchCredentialManager() { + // [START create_credential_manager_request] + // Instantiate a Google sign-in request + GetGoogleIdOption googleIdOption = new GetGoogleIdOption.Builder() + .setFilterByAuthorizedAccounts(true) + .setServerClientId(getString(R.string.default_web_client_id)) + .build(); + + // Create the Credential Manager request + GetCredentialRequest request = new GetCredentialRequest.Builder() + .addCredentialOption(googleIdOption) + .build(); + // [END create_credential_manager_request] + + // Launch Credential Manager UI + credentialManager.getCredentialAsync( + getBaseContext(), + request, + new CancellationSignal(), + Executors.newSingleThreadExecutor(), + new CredentialManagerCallback<>() { + @Override + public void onResult(GetCredentialResponse result) { + // Extract credential from the result returned by Credential Manager + handleSignIn(result.getCredential()); + } + + @Override + public void onError(GetCredentialException e) { + Log.e(TAG, "Couldn't retrieve user's credentials: " + e.getLocalizedMessage()); + } + } + ); + } + + // [START handle_sign_in] + private void handleSignIn(Credential credential) { + // Check if credential is of type Google ID + if (credential instanceof CustomCredential customCredential + && credential.getType().equals(TYPE_GOOGLE_ID_TOKEN_CREDENTIAL)) { + // Create Google ID Token + Bundle credentialData = customCredential.getData(); + GoogleIdTokenCredential googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credentialData); + + // Sign in to Firebase with using the token + firebaseAuthWithGoogle(googleIdTokenCredential.getIdToken()); + } else { + Log.w(TAG, "Credential is not of type Google ID!"); } } - // [END onactivityresult] + // [END handle_sign_in] // [START auth_with_google] private void firebaseAuthWithGoogle(String idToken) { AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null); mAuth.signInWithCredential(credential) - .addOnCompleteListener(this, new OnCompleteListener() { - @Override - public void onComplete(@NonNull Task task) { - if (task.isSuccessful()) { - // Sign in success, update UI with the signed-in user's information - Log.d(TAG, "signInWithCredential:success"); - FirebaseUser user = mAuth.getCurrentUser(); - updateUI(user); - } else { - // If sign in fails, display a message to the user. - Log.w(TAG, "signInWithCredential:failure", task.getException()); - updateUI(null); - } + .addOnCompleteListener(this, task -> { + if (task.isSuccessful()) { + // Sign in success, update UI with the signed-in user's information + Log.d(TAG, "signInWithCredential:success"); + FirebaseUser user = mAuth.getCurrentUser(); + updateUI(user); + } else { + // If sign in fails, display a message to the user + Log.w(TAG, "signInWithCredential:failure", task.getException()); + updateUI(null); } }); } // [END auth_with_google] - // [START signin] - private void signIn() { - Intent signInIntent = mGoogleSignInClient.getSignInIntent(); - startActivityForResult(signInIntent, RC_SIGN_IN); + // [START sign_out] + private void signOut() { + // Firebase sign out + mAuth.signOut(); + + // When a user signs out, clear the current user credential state from all credential providers. + ClearCredentialStateRequest clearRequest = new ClearCredentialStateRequest(); + credentialManager.clearCredentialStateAsync( + clearRequest, + new CancellationSignal(), + Executors.newSingleThreadExecutor(), + new CredentialManagerCallback<>() { + @Override + public void onResult(@NonNull Void result) { + updateUI(null); + } + + @Override + public void onError(@NonNull ClearCredentialException e) { + Log.e(TAG, "Couldn't clear user credentials: " + e.getLocalizedMessage()); + } + }); } - // [END signin] + // [END sign_out] private void updateUI(FirebaseUser user) { diff --git a/auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/GoogleSignInActivity.kt b/auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/GoogleSignInActivity.kt index 8e296bc38..1ff6874fb 100644 --- a/auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/GoogleSignInActivity.kt +++ b/auth/app/src/main/java/com/google/firebase/quickstart/auth/kotlin/GoogleSignInActivity.kt @@ -1,48 +1,54 @@ package com.google.firebase.quickstart.auth.kotlin -import android.app.Activity -import android.content.Intent import android.os.Bundle import android.util.Log -import com.google.android.gms.auth.api.signin.GoogleSignIn -import com.google.android.gms.auth.api.signin.GoogleSignInClient -import com.google.android.gms.auth.api.signin.GoogleSignInOptions -import com.google.android.gms.common.api.ApiException +import androidx.appcompat.app.AppCompatActivity +import androidx.credentials.ClearCredentialStateRequest +import androidx.credentials.Credential +import androidx.credentials.CredentialManager +import androidx.credentials.CustomCredential +import androidx.credentials.GetCredentialRequest +import androidx.credentials.exceptions.ClearCredentialException +import androidx.credentials.exceptions.GetCredentialException +import androidx.lifecycle.lifecycleScope +import com.google.android.libraries.identity.googleid.GetGoogleIdOption +import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential +import com.google.android.libraries.identity.googleid.GoogleIdTokenCredential.Companion.TYPE_GOOGLE_ID_TOKEN_CREDENTIAL import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.FirebaseUser import com.google.firebase.auth.GoogleAuthProvider import com.google.firebase.auth.auth import com.google.firebase.Firebase import com.google.firebase.quickstart.auth.R +import kotlinx.coroutines.launch /** * Demonstrate Firebase Authentication using a Google ID Token. */ -class GoogleSignInActivity : Activity() { +class GoogleSignInActivity : AppCompatActivity() { // [START declare_auth] private lateinit var auth: FirebaseAuth // [END declare_auth] - private lateinit var googleSignInClient: GoogleSignInClient + // [START declare_credential_manager] + private lateinit var credentialManager: CredentialManager + // [END declare_credential_manager] override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - // [START config_signin] - // Configure Google Sign In - val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN) - .requestIdToken(getString(R.string.default_web_client_id)) - .requestEmail() - .build() - - googleSignInClient = GoogleSignIn.getClient(this, gso) - // [END config_signin] - // [START initialize_auth] // Initialize Firebase Auth auth = Firebase.auth // [END initialize_auth] + + // [START initialize_credential_manager] + // Initialize Credential Manager + credentialManager = CredentialManager.create(baseContext) + // [END initialize_credential_manager] + + launchCredentialManager() } // [START on_start_check_user] @@ -54,25 +60,53 @@ class GoogleSignInActivity : Activity() { } // [END on_start_check_user] - // [START onactivityresult] - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - super.onActivityResult(requestCode, resultCode, data) - // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...); - if (requestCode == RC_SIGN_IN) { - val task = GoogleSignIn.getSignedInAccountFromIntent(data) + private fun launchCredentialManager() { + // [START create_credential_manager_request] + // Instantiate a Google sign-in request + val googleIdOption = GetGoogleIdOption.Builder() + // Your server's client ID, not your Android client ID. + .setServerClientId(getString(R.string.default_web_client_id)) + // Only show accounts previously used to sign in. + .setFilterByAuthorizedAccounts(true) + .build() + + // Create the Credential Manager request + val request = GetCredentialRequest.Builder() + .addCredentialOption(googleIdOption) + .build() + // [END create_credential_manager_request] + + lifecycleScope.launch { try { - // Google Sign In was successful, authenticate with Firebase - val account = task.getResult(ApiException::class.java)!! - Log.d(TAG, "firebaseAuthWithGoogle:" + account.id) - firebaseAuthWithGoogle(account.idToken!!) - } catch (e: ApiException) { - // Google Sign In failed, update UI appropriately - Log.w(TAG, "Google sign in failed", e) + // Launch Credential Manager UI + val result = credentialManager.getCredential( + context = baseContext, + request = request + ) + + // Extract credential from the result returned by Credential Manager + handleSignIn(result.credential) + } catch (e: GetCredentialException) { + Log.e(TAG, "Couldn't retrieve user's credentials: ${e.localizedMessage}") } } } - // [END onactivityresult] + + // [START handle_sign_in] + private fun handleSignIn(credential: Credential) { + // Check if credential is of type Google ID + if (credential is CustomCredential && credential.type == TYPE_GOOGLE_ID_TOKEN_CREDENTIAL) { + // Create Google ID Token + val googleIdTokenCredential = GoogleIdTokenCredential.createFrom(credential.data) + + // Sign in to Firebase with using the token + firebaseAuthWithGoogle(googleIdTokenCredential.idToken) + } else { + Log.w(TAG, "Credential is not of type Google ID!") + } + } + // [END handle_sign_in] // [START auth_with_google] private fun firebaseAuthWithGoogle(idToken: String) { @@ -85,7 +119,7 @@ class GoogleSignInActivity : Activity() { val user = auth.currentUser updateUI(user) } else { - // If sign in fails, display a message to the user. + // If sign in fails, display a message to the user Log.w(TAG, "signInWithCredential:failure", task.exception) updateUI(null) } @@ -93,18 +127,28 @@ class GoogleSignInActivity : Activity() { } // [END auth_with_google] - // [START signin] - private fun signIn() { - val signInIntent = googleSignInClient.signInIntent - startActivityForResult(signInIntent, RC_SIGN_IN) + // [START sign_out] + private fun signOut() { + // Firebase sign out + auth.signOut() + + // When a user signs out, clear the current user credential state from all credential providers. + lifecycleScope.launch { + try { + val clearRequest = ClearCredentialStateRequest() + credentialManager.clearCredentialState(clearRequest) + updateUI(null) + } catch (e: ClearCredentialException) { + Log.e(TAG, "Couldn't clear user credentials: ${e.localizedMessage}") + } + } } - // [END signin] + // [END sign_out] private fun updateUI(user: FirebaseUser?) { } companion object { private const val TAG = "GoogleActivity" - private const val RC_SIGN_IN = 9001 } }