I am using firebase auth UI (FirebaseUI-Android) in an android app, where the user can signup with personal email, Facebook, number and Gmail accounts. My question is I need to get email verification when user sign's up with his personal email id.
List<AuthUI.IdpConfig> providers = Arrays.asList(
new AuthUI.IdpConfig.Builder(AuthUI.EMAIL_PROVIDER).build(),
new AuthUI.IdpConfig.Builder(AuthUI.PHONE_VERIFICATION_PROVIDER).build(),
new AuthUI.IdpConfig.Builder(AuthUI.FACEBOOK_PROVIDER).build(),
new AuthUI.IdpConfig.Builder(AuthUI.GOOGLE_PROVIDER).build());
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setIsSmartLockEnabled(true)
.setTheme(R.style.GreenTheme)
.setTosUrl("https://termsfeed.com/blog/terms-conditions-mobile-apps/")
.setPrivacyPolicyUrl("https://superapp.example.com/privacy-policy.html")
.setAvailableProviders(providers)
.build(),
RC_SIGN_IN);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// RC_SIGN_IN is the request code you passed into startActivityForResult(...) when starting the sign in flow.
if (requestCode == RC_SIGN_IN) {
IdpResponse response = IdpResponse.fromResultIntent(data);
// Successfully signed in
if (resultCode == RESULT_OK) {
startActivity(new Intent(Login.this,MainActivity.class));
finish();
return;
} else {
// Sign in failed
if (response == null) {
Toasty.error(getApplicationContext(),"Sign in cancelled",Toast.LENGTH_SHORT, true).show();
return;
}
if (response.getErrorCode() == ErrorCodes.NO_NETWORK) {
Toasty.error(getApplicationContext(),"No internet connection",Toast.LENGTH_SHORT, true).show();
return;
}
if (response.getErrorCode() == ErrorCodes.UNKNOWN_ERROR) {
Toasty.error(getApplicationContext(),"Unkown Error",Toast.LENGTH_SHORT, true).show();
return;
}
}
Toasty.error(getApplicationContext(),"Unknown sign in response",Toast.LENGTH_SHORT, true).show();
}
}
Here is my intent for sign up options.
You can simply do it as follows,
Get Current Firebase User Instance,
final FirebaseUser currentUser = mAuth.getCurrentUser();
Check if the provider is password indicating that the login method used is Email Auth,
if(null != currentUser) {
if("password".equals(currentUser.getProviderData().get(0).getProviderId())) {
/* Handle Verification */
}
}
Reference Link: https://firebase.google.com/docs/reference/android/com/google/firebase/auth/EmailAuthProvider#PROVIDER_ID
Check if user is already verified,
currentUser.isEmailVerified();
If user is not verified then the following code can be used to send a verification EMail,
if (!currentUser.isEmailVerified()) {
/* Do Something */
}
/* Send Verification Email */
currentUser.sendEmailVerification()
.addOnCompleteListener(this, new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
/* Check Success */
if (task.isSuccessful()) {
Toast.makeText(getApplicationContext(),
"Verification Email Sent To: " + currentUser.getEmail(),
Toast.LENGTH_SHORT).show();
} else {
Log.e(TAG, "sendEmailVerification", task.getException());
Toast.makeText(getApplicationContext(),
"Failed To Send Verification Email!",
Toast.LENGTH_SHORT).show();
}
}
});
Once you have all the pieces in place, the final code snippet should look something like below:
Final Code Snippet:
if (requestCode == RC_SIGN_IN) {
IdpResponse response = IdpResponse.fromResultIntent(data);
/* Success */
if (resultCode == RESULT_OK) {
final FirebaseUser currentUser = mAuth.getCurrentUser();
if(null != currentUser) {
if("password".equals(currentUser.getProviderData().get(0).getProviderId())) {
if(!currentUser.isEmailVerified()) {
/* Send Verification Email */
currentUser.sendEmailVerification()
.addOnCompleteListener(this, new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
/* Check Success */
if (task.isSuccessful()) {
Toast.makeText(getApplicationContext(),
"Verification Email Sent To: " + currentUser.getEmail(),
Toast.LENGTH_SHORT).show();
} else {
Log.e(TAG, "sendEmailVerification", task.getException());
Toast.makeText(getApplicationContext(),
"Failed To Send Verification Email!",
Toast.LENGTH_SHORT).show();
}
}
});
/* Handle Case When Email Not Verified */
}
}
/* Login Success */
startActivity(new Intent(Login.this, MainActivity.class));
finish();
return;
}
} else {
/* Handle Failure */
}
}
#user2004685 answer above gives very good hint. But it does not work at least for the latest firebase-ui because currentUser.getProviderData().get(0).getProviderId() returns 'firebase'.
So the updated solution is
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == RC_SIGN_IN) {
IdpResponse response = IdpResponse.fromResultIntent(data);
/* Success */
if (resultCode == RESULT_OK) {
final FirebaseUser currentUser = mAuth.getCurrentUser();
if(null != currentUser) {
if(currentUser.getEmail()!=null) {
if(!currentUser.isEmailVerified()) {
/* Send Verification Email */
currentUser.sendEmailVerification()
.addOnCompleteListener(this, new OnCompleteListener() {
#Override
public void onComplete(#NonNull Task task) {
/* Check Success */
if (task.isSuccessful()) {
Toast.makeText(getApplicationContext(),
"Verification Email Sent To: " + currentUser.getEmail(),
Toast.LENGTH_SHORT).show();
} else {
Log.e(TAG, "sendEmailVerification", task.getException());
Toast.makeText(getApplicationContext(),
"Failed To Send Verification Email!",
Toast.LENGTH_SHORT).show();
}
}
});
/* Handle Case When Email Not Verified */
}
}
/* Login Success */
startActivity(new Intent(Login.this, MainActivity.class));
finish();
return;
}
} else {
/* Handle Failure */
}
}
}
simply replace if("password".equals(currentUser.getProviderData().get(0).getProviderId())) with if(currentUser.getEmail()!=null)
Related
I have tried to use this however the recommended does not do anything:
Fitness.getConfigClient(this, GoogleSignIn.getLastSignedInAccount(this)).disableFit()
How I authenticate with Google:
if (!GoogleSignIn.hasPermissions(GoogleSignIn.getLastSignedInAccount(this), fitnessOptions)) {
GoogleSignIn.requestPermissions(this, REQUEST_OAUTH_REQUEST_CODE,
GoogleSignIn.getLastSignedInAccount(this),
fitnessOptions);
} else {
subscribe();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == Activity.RESULT_OK) {
if (requestCode == REQUEST_OAUTH_REQUEST_CODE) {
subscribe();
}
}
}
public void subscribe() {
Fitness.getRecordingClient(this, GoogleSignIn.getLastSignedInAccount(this))
.subscribe(DataType.TYPE_STEP_COUNT_CUMULATIVE)
.addOnCompleteListener(
new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.i(TAG, "Successfully subscribed!");
} else {
Log.w(TAG, "There was a problem subscribing.", task.getException());
}
}
});
}
I need to be able to get the google account which was last signed in and provide an option to the user to sign out of their google account.
For disconnecting Google account from your app you should use signOut method from GoogleSignIn which will preserve granted permissions or you can use revokeAccess method to do both signing out and revoke granted permissions:
val options = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.addExtension(getFitnessOptions())
.requestProfile()
.build()
GoogleSignIn.getClient(this, options).signOut() // or GoogleSignIn.getClient(this, options).revokeAccess()
i created a standard login and signup page and i added an alternative to sign in with a google account using the custom GogleSignInButton.
The button works welll. am able to select a google account and sign in but the credentials do not reflect in the firebase authentication console nor does it bring up the signup activity for new users like it does when using the standard firebase UI.
I already have a working login with email and password(if it helps).
I would like help in immplementing the storage of credentials and signing up new users with google accounts.
From the image below you can see there are no gmail accounts
SignInButton signInButton = findViewById(R.id.sign_in_button);
signInButton.setSize(SignInButton.SIZE_STANDARD);
GoogleSignInOptions gso = new
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestEmail()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
if (mAuth.getCurrentUser() != null) {
startActivity(new Intent(LoginActivity.this,
MainActivity.class));
finish();
}
signInButton.setOnClickListener(this);
private void signIn() {
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, RC_SIGN_IN);
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.sign_in_button:
signIn();
break;
}
}
#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<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
handleSignInResult(task);
}
}
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
try {
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
// Signed in successfully, show authenticated UI.
startActivity(new Intent(LoginActivity.this,MainActivity.class));
} catch (ApiException e) {
// The ApiException status code indicates the detailed failure reason.
// Please refer to the GoogleSignInStatusCodes class reference for more information.
Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());
Toast.makeText(this, "Authentication Failed", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onStart() {
// Check if user is signed in (non-null) and update UI accordingly.
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
if(account != null) {
startActivity(new Intent(LoginActivity.this,MainActivity.class));
}
super.onStart();
}
I am trying to set a logIn/signUp to a google account. I wrote the code and it should work but it doesn't(it always ends up with the failed toast I made).
I watch a bunch of videos and looked at google doc and my code is pretty much the same.
protected void onStart() {
if( getIntent().getBooleanExtra(ThirdActivity.extraLoggedIn, false) == false ) {
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this);
if (account != null) {
getDataFromFirebase(account);
//playerNameText.setText("Player Name: " + accountName);
} else {
startActivityForResult(mGoogleSignInClient.getSignInIntent(), 0);
//account = GoogleSignIn.getLastSignedInAccount(this);
//signUp(account);
}
loggedIn = true;
}
super.onStart();
changeLanguage(SingletonDemiClass.getInstance().getLanguage());
playerNameText.setText("Player Name: " + accountName);
}
#Override
public void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == 0){
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
//Toast.makeText(SecondActivity.this, task.getResult().getId(), Toast.LENGTH_LONG).show();
signUp(task);
}
}
//private void signUp(GoogleSignInAccount account) {
private void signUp(Task<GoogleSignInAccount> completedTask) {
try {
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
accountID = account.getId();
accountName = account.getDisplayName();
}
catch (ApiException ex) {
Log.w("Google Sign-In Error", "signInResult:failed code=" + ex.getStatusCode());
Toast.makeText(SecondActivity.this, "Failed", Toast.LENGTH_LONG).show();
//}
}
}
Logcat
I am using the Firebase AuthUI to sign in to my application, specifically with Facebook. I have verified within my console that my sign in was successful, as I see the user added.
However, my callback method is not triggering, I have toasts implemented and I do not know why the success method is not being called. I have logged the error code and do not know what issue it signifies. Am I capturing the error correctly? It is generating -1, which I do not see in the Firebase AuthUI docs:
public class LoginActivity extends AppCompatActivity {
private static final int RC_SIGN_IN = 123;
private static final String USERS = "Users";
private FirebaseAuth mAuth;
FirebaseDatabase mBaseRef;
DatabaseReference mUserRef;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mAuth = FirebaseAuth.getInstance();
mBaseRef = FirebaseDatabase.getInstance();
mUserRef = mBaseRef.getReference(USERS);
startActivityForResult(AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(Arrays.asList(
new AuthUI.IdpConfig.EmailBuilder().build(),
new AuthUI.IdpConfig.GoogleBuilder().build(),
new AuthUI.IdpConfig.FacebookBuilder().build()))
.build(), RC_SIGN_IN);
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// RC_SIGN_IN is the request code you passed into startActivityForResult(...) when starting the sign in flow.
if (requestCode == RC_SIGN_IN) {
IdpResponse response = IdpResponse.fromResultIntent(data);
Log.v("RESPONSE", String.valueOf(response.getErrorCode()));
// Successfully signed in
if (resultCode == RESULT_OK) {
Toast.makeText(getApplicationContext(), "SIGNED IN SUCCESSFULLY", Toast.LENGTH_LONG).show();
if (mAuth.getCurrentUser() != null) {
HashMap<String, Object> map = new HashMap<>();
map.put("TEST USER ", mAuth.getCurrentUser());
mUserRef.push().updateChildren(map);
Intent i = new Intent(getApplicationContext(), MainActivity.class);
startActivity(i);
finish();
} else {
//not signed in
Toast.makeText(getApplicationContext(), "SIGN IN FAILED", Toast.LENGTH_LONG).show();
return;
}
} else {
// Sign in failed
if (response == null) {
// User pressed back button
Toast.makeText(getApplicationContext(), "SIGN IN CANCELLED", Toast.LENGTH_LONG).show();
return;
}
if (response.getErrorCode() == ErrorCodes.NO_NETWORK) {
Toast.makeText(getApplicationContext(), "NO INTERNET CONNECTION", Toast.LENGTH_LONG).show();
return;
}
if (response.getErrorCode() == ErrorCodes.UNKNOWN_ERROR) {
Toast.makeText(getApplicationContext(), "UNKNOWN ERROR", Toast.LENGTH_LONG).show();
return;
}
}
}
}
}
EDIT: I have added the complete activity
EDIT: My log is running very quickly and then the error is automatically deleting before I can read it, it might actually be a StackOverflow.
The error code is only valid if an error actually occurred by checking the onActivityResult result code, otherwise it just returns -1 (Activity.RESULT_OK) as you've noticed. Here's an example from the sample:
private void handleSignInResponse(int resultCode, Intent data) {
IdpResponse response = IdpResponse.fromResultIntent(data);
// Successfully signed in
if (resultCode == RESULT_OK) {
startSignedInActivity(response);
finish();
} else {
// Sign in failed
if (response == null) {
// User pressed back button
showSnackbar(R.string.sign_in_cancelled);
return;
}
if (response.getError().getErrorCode() == ErrorCodes.NO_NETWORK) {
showSnackbar(R.string.no_internet_connection);
return;
}
showSnackbar(R.string.unknown_error);
Log.e(TAG, "Sign-in error: ", response.getError());
}
}
Sorry for my bad english.
I want to combine these 2 methods
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());
// 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(MainActivity.this, "Authentication failed.", Toast.LENGTH_SHORT).show();
}
}
});
}
private void firebaseAuthWithFacebook(AccessToken token) {
Log.d(TAG, "handleFacebookAccessToken:" + token);
AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
// 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(MainActivity.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
// ...
}
});
}
Only this line change
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
FacebookAuthProvider.getCredential(token.getToken());
I take this from FireBase documentation.
I am new on Android Programmation (I'm little C# game dev) so don't blame me.
And I don't enderstind this :https://firebase.google.com/docs/auth/android/account-linking#link-auth-provider-credentials-to-a-user-account
Please can I Have Help ?
Thank's in advance.
You can add both parameters acct and token in one method and check if each of them is null like this private void firebaseAuth(GoogleSignInAccount acct,AccessToken token).If acct is null then the user should be sign in using facebook Given that you checked that the request code is the one you provide when you sign in using Google in OnActivityResult(int requestCode, int resultCode, Intent data) and the result you got from Auth.GoogleSignInApi.getSignInResultFromIntent(data) is result.isSuccess().Same for Facebook as you pass the AccessToken from onSuccess() method of the FacebookCallback<LoginResult>() so you may do some thing like this:
CallbackManager mCallbackManager = CallbackManager.Factory.create();
LoginManager.getInstance().registerCallback(mCallbackManager,
new FacebookCallback<LoginResult>() {
#Override
public void onSuccess(LoginResult loginResult) {
Log.d(TAG, "facebook:onSuccess:" + loginResult);
firebaseAuth(null,loginResult.getAccessToken);
//null here is the google account as you sign in using facebook
}
#Override
public void onCancel() {
//Something to do with user cancel login
}
#Override
public void onError(FacebookException error) {
//Something to do with FacebookException
}
});
and in case of Google Sign in :
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == GOOGLE_SIGN_IN) {
/* request code you pass to
* startActivityForResult(intent, GOOGLE_SIGN_IN)
* where intent is what you get from intent =
* Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient)
*/
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
// Google Sign In was successful, authenticate with Firebase
GoogleSignInAccount account = result.getSignInAccount();
firebaseAuth(account,null);
/* null here is the facebook token
* as you sign in using Google
*/
} else if(result.getStatus().isInterrupted()){
// Google Sign In failed, update UI appropriately
}
}
}