Android Firebase why do I get signed out after changing email? - android

When the user wants to change his password, I prompt him with a Dialog to Re-authenticate. In this dialog, he can re-auth with password or via Google/Facebook. But when I update the firebase email, the user gets signed out and I want to avoid this.
Consider this code:
private fun btnGoogle(){
val acct = GoogleSignIn.getLastSignedInAccount(context)
Timber.d(acct?.email)
if (acct != null) {
val credential = GoogleAuthProvider.getCredential(acct.idToken, null)
auth(credential)
}
}
private fun btnFacebook(){
val token = AccessToken.getCurrentAccessToken()
if(token!=null){
val credential = FacebookAuthProvider.getCredential(token.token)
auth(credential)
}else{
activity?.showBackgroundToast(getString(R.string.no_facebook_auth), Toast.LENGTH_LONG)
}
}
private fun auth(credential: AuthCredential) {
FirebaseAuth.getInstance().currentUser!!.reauthenticate(credential)
.addOnFailureListener{e -> activity?.showBackgroundToast(e.localizedMessage, Toast.LENGTH_LONG)}
.addOnCompleteListener { task ->
if (task.isSuccessful) {
mListener.onReAuthentication(true)
dialog.dismiss()
} else {
activity?.showBackgroundToast(task.exception?.localizedMessage, Toast.LENGTH_LONG)
}
}
}
Then I call this function to actually update the email:
fun updateEmail(newEmail: String): Completable {
return Completable.create { emitter ->
val currentUser = FirebaseAuth.getInstance().currentUser
currentUser!!.updateEmail(newEmail).addOnCompleteListener {
if (it.isSuccessful) {
Timber.d("updated email to %s", newEmail)
emitter.onComplete()
} else {
emitter.onError(Throwable(it.exception?.localizedMessage))
}
}
}
}
Everything works fine until I finally update the email. When I do, Firebase signs the user out every time!! (the following is from Android Studio logcat)
D/FirebaseAuth: Notifying id token listeners about a sign-out event.
D/FirebaseAuth: Notifying auth state listeners about a sign-out event.
It only happens when I change the email. Since I have an auth state listener, the user gets redirected to login screen after successfully updating the email, which makes no sense to me. Why? How can I avoid this?

Related

Android App Google OAuth2 Fails returning Code 10

I am using Google OneTap SignIn in my app.
I am getting this error when no user is found and when I click my google profile to login:
error message
So it seems to be working with the signIn function, but not the signUp function? Why?
// USE one tap sign in client to do login.
oneTapClient = Identity.getSignInClient(this)
First I have a SignIn Request to sign in any previously signed in user.
signInRequest = BeginSignInRequest.builder()
.setPasswordRequestOptions(
BeginSignInRequest.PasswordRequestOptions.builder()
.setSupported(true)
.build()
)
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
// Your server's client ID, not your Android client ID.
.setServerClientId(Constants.OAUTH_CLIENT_ID_WEB)
// Only show accounts previously used to sign in.
.setFilterByAuthorizedAccounts(true)
.build()
)
// Automatically sign in when exactly one credential is retrieved.
.setAutoSelectEnabled(true)
.build()
Then I have a SignUp Request to sign the user up for OneTap if there are no credentials found.
// Sign up OneTap if no credentials found:
signUpRequest = BeginSignInRequest.builder()
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
// Your server's client ID, not your Android client ID.
.setServerClientId(Constants.OAUTH_CLIENT_ID_WEB)
// Show all accounts on the device.
.setFilterByAuthorizedAccounts(false)
.build()
)
.build()
Here are both functions I have that call the One Tap request:
// launch the OneTap sign in request
private fun signIn() {
println("Attempting One Tap...")
oneTapClient.beginSignIn(signInRequest)
.addOnSuccessListener(this) { result ->
try {
startIntentSenderForResult(
result.pendingIntent.intentSender, REQ_ONE_TAP,
null, 0, 0, 0, null
)
} catch (e: IntentSender.SendIntentException) {
Log.e(TAG, "Couldn't start One Tap UI: ${e.localizedMessage}")
}
}
.addOnFailureListener(this) { e ->
println("No saved credentials found")
// No saved credentials found. Launch the One Tap sign-up flow, or
// do nothing and continue presenting the signed-out UI.
e.localizedMessage?.let { Log.d(TAG, it) }
signUp()
}
}
// launch the OneTap sign up request
private fun signUp() {
oneTapClient.beginSignIn(signUpRequest)
.addOnSuccessListener(this) { result ->
try {
startIntentSenderForResult(
result.pendingIntent.intentSender, REQ_ONE_TAP,
null, 0, 0, 0
)
} catch (e: IntentSender.SendIntentException) {
Log.e(TAG, "Couldn't start One Tap UI: ${e.localizedMessage}")
}
}
.addOnFailureListener(this) { e ->
// No Google Accounts found. Just continue presenting the signed-out UI.
e.localizedMessage?.let { Log.d(TAG, it) }
}
}
And this is the onResultListener
#Deprecated("Deprecated in Java")
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
when (requestCode) {
REQ_ONE_TAP -> {
try {
val credential = oneTapClient.getSignInCredentialFromIntent(data)
val idToken = credential.googleIdToken
when {
idToken != null -> {
// Got an ID token from Google. Use it to authenticate
// with your backend.
Log.d(TAG, "Got ID token: $idToken")
}
else -> {
// Shouldn't happen.
Log.d(TAG, "No ID token or password!")
}
}
} catch (e: ApiException) {
when (e.statusCode) {
CommonStatusCodes.CANCELED -> {
Log.d(TAG, "One-tap dialog was closed.")
// Don't re-prompt the user.
showOneTapUI = false
}
CommonStatusCodes.NETWORK_ERROR -> {
Log.d(TAG, "One-tap encountered a network error.")
// Try again or just ignore.
}
else -> {
Log.d(
TAG, "Couldn't get credential from result." +
" (${e.localizedMessage})"
)
}
}
Log.e("Error", e.message.toString())
}
}
}
}
I've tried to make sure the package name is good on my Google Console and that my AndroidManifest.xml has the same package name. I also got the debug keystore from Android Studio, and that made the first signIn function work, but the signUp function still gets the error code 10.
For what its worth, I'm using Kotlin Multiplatform Mobile to try and make this a cross-platform app, but right now I'm having these issues on the Android side of things.

Firebase Android - how to login as different user (after signing in with Google)

Edit - a key thing that I didn't realise at when writing is that this happens when you use Google as an authentication provider
I've set up my Android app so that I can log in and out using Firebase Authentication.
But when I log in, I'm not presented with any options that would let me log in as a different use - it just auto-logs me into the same account I logged into last time.
How can I switch the user account I use to log in?
Code from my main Activity:
// Authentication stuff
private lateinit var auth: FirebaseAuth
private val btnSignIn: Button by lazy { findViewById(R.id.btnSignIn) }
val signInLauncher = registerForActivityResult(FirebaseAuthUIActivityResultContract()) { res ->
if (res.resultCode == RESULT_OK) {
refreshSigninInfo()
} else {
showToast("Sign in failed - do you have internet connection?")
}
}
private fun refreshSigninInfo() { // Called in onCreate()
auth = FirebaseAuth.getInstance()
auth.currentUser?.let {
btnSignIn.text = "Signed in as ${it.email}\nTap to sign out"
btnSignIn.setOnClickListener {
auth.signOut()
refreshSigninInfo()
}
} ?: run {
btnSignIn.text = "Tap to sign in"
btnSignIn.setOnClickListener {
val signInIntent = AuthUI.getInstance()
.createSignInIntentBuilder()
.setAvailableProviders(arrayListOf(AuthUI.IdpConfig.EmailBuilder().build(), AuthUI.IdpConfig.GoogleBuilder().build()))
.build()
signInLauncher.launch(signInIntent)
// HERE, upon launch, this this should give the user
// the option of selecting a different sign-in account
// but instead, if the user has previously signed in,
// it just directly signs the user in without the option
// to change account
}
}
}
Finally got it thanks to this answer.
Key thing was to sign out with:
AuthUI.getInstance().signOut(this).addOnCompleteListener {
refreshSigninInfo()
}
Instead of auth.signOut(). This way you get signed out of both Google and the firebase auth, so you aren't automatically logged in next time through Google.
Full Code (in my main activity - includes some references to buttons and stuff that you won't have):
// Authentication stuff
private lateinit var auth: FirebaseAuth
private val textLoginInfo: TextView by lazy { findViewById(R.id.textLoginInfo) }
private val btnSignIn: ImageButton by lazy { findViewById(R.id.btnSignIn) }
val signInLauncher = registerForActivityResult(FirebaseAuthUIActivityResultContract()) { res ->
if (res.resultCode == RESULT_OK) {
refreshSigninInfo()
} else {
showToast("Sign in failed - do you have internet connection?")
}
}
private fun refreshSigninInfo() { // Called in onCreate()
auth = FirebaseAuth.getInstance()
auth.currentUser?.let {
btnSignIn.setImageResource(R.drawable.logout_white_24dp)
textLoginInfo.text = "Signed in: ${it.email}"
btnSignIn.setOnClickListener {
AuthUI.getInstance().signOut(this).addOnCompleteListener {
refreshSigninInfo()
}
}
} ?: run {
btnSignIn.setImageResource(R.drawable.login_white_24dp)
textLoginInfo.text = "Not Signed in"
btnSignIn.setOnClickListener {
val signInIntent = AuthUI.getInstance()
.createSignInIntentBuilder()
.setAlwaysShowSignInMethodScreen(true)
.setAvailableProviders(arrayListOf(AuthUI.IdpConfig.EmailBuilder().build(), AuthUI.IdpConfig.GoogleBuilder().build()))
.build()
signInLauncher.launch(signInIntent)
}
}
}

UI freezing when changing user password in Firebase Authentication

I am building an android app in MVVM architecture using Firebase. I am trying to do User's password change and whenever i start my code, application freezes or just stops responding. I spent a lot of time to search what is wrong with it and yet no fix. If anyone know why it behave like this I would appreciate your help. My code:
Function called in fragment:
private fun startChangePasswordDialog(){
val dialogView = LayoutInflater.from(activity).inflate(R.layout.dialog_change_password, null)
val builder = AlertDialog.Builder(activity).setView(dialogView)
val dialog: AlertDialog = builder.show()
val changePassword = dialogView.findViewById<Button>(R.id.changePasswordBT)
val cancel = dialogView.findViewById<Button>(R.id.changePasswordCancelBT)
val passwordET = dialogView.findViewById<EditText>(R.id.changePasswordET)
changePassword?.setOnClickListener {
val newPassword = passwordET.text.trim().toString()
if (TextUtils.isEmpty(newPassword) || newPassword.length < viewModel.PASSWORD_MIN_VALUE){
Toast.makeText(requireContext(), R.string.password_too_short, Toast.LENGTH_SHORT).show()
}
else{
viewModel.changeUsersPassword(newPassword)
viewModel.needUserAuthentication.observe(requireActivity(), {
if (it == true) reAuthenticateUser()
})
}
dialog.dismiss()
}
cancel?.setOnClickListener {
dialog.dismiss()
}
ViewModel function:
fun changeUsersPassword(password: String) {
Log.d(TAG,"Starting user's password change procedure")
when (repository.changeUserPassword(password)){
PasswordChangeCallbackEnum.FACEBOOK_USER -> {
_toastMessage.value = R.string.facebook_user_password_change
Log.d(TAG, "User's password will not be changed, logged in as Facebook user")
}
PasswordChangeCallbackEnum.PASSWORD_CHANGE_ERROR -> {
_toastMessage.value = R.string.password_change_error
Log.d(TAG, "Error while changing user's password")
}
PasswordChangeCallbackEnum.PASSWORD_CHANGED -> {
_toastMessage.value = R.string.password_change_success
Log.d(TAG, "User's password changed successfully")
}
PasswordChangeCallbackEnum.NEED_USER_AUTHENTICATION -> {
_needUserAuthentication.value = true
}
}
}
Firebase Repository (I have changed it several times when tried to fix this):
fun changeUserPassword(password: String): PasswordChangeCallbackEnum {
var result = PasswordChangeCallbackEnum.PASSWORD_CHANGE_ERROR
if (currentUser != null) {
for (userInfo in currentUser.providerData) {
if (userInfo.providerId == "facebook.com") {
Log.d(TAG, "Cannot change password for user logged in with facebook")
result = PasswordChangeCallbackEnum.FACEBOOK_USER
}
}
}
try{
val updateTask = authentication.currentUser?.updatePassword(password)
updateTask?.addOnSuccessListener {
Log.d(TAG, "User's password change state: SUCCESS")
result = PasswordChangeCallbackEnum.PASSWORD_CHANGED
}
}catch (exception: FirebaseAuthRecentLoginRequiredException){
Log.d(TAG, "Need user to authenticate again")
result = PasswordChangeCallbackEnum.NEED_USER_AUTHENTICATION
}
return result
}
The problem is, you are doing task in ui thread.
Use coroutines for the task to do in worker thread .
you can have more information about coroutines. here
You can also use RxJava for it or some Async task.
It will prevent the ui freezing

Google OneTap SignIn Pass or Error codes: 10 / 16

I'm trying to set up a Google OneTap SignIn button to my developed App (I'm not using Firebase to sign in) guiding by this source:
https://developers.google.com/identity/one-tap/android/get-started
I've created both OAuth & Web credentials on Cloud Console. To generate OAuth Id I took SHA1 which was provided by Android Studio in signing-in report (I took develop SHA-1, but they are all the same anyway).
I've put to R.string.default_web_client_id the Client Id from WebAuth (Not an Android Id from OAuth).
As I use Firebase RTDB for storing some data, I set this SHA-1 there as well. The project name in Manifest, Cloud Console and Firebase Console are the same. From Firebase I downloaded "google-services.json" and put it in app root. On Firebase I also set valid service email.
This is how I implemented OneTap on login activity:
class LoginActivity : AppCompatActivity() {
...
private lateinit var oneTapClient: SignInClient
private lateinit var signUpRequest: BeginSignInRequest
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
...
oneTapClient = Identity.getSignInClient(this)
signUpRequest = BeginSignInRequest.builder()
.setPasswordRequestOptions(BeginSignInRequest.PasswordRequestOptions.builder()
.setSupported(false)
.build())
.setGoogleIdTokenRequestOptions(BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
// 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(false)
.build())
// Automatically sign in when exactly one credential is retrieved.
.setAutoSelectEnabled(false)
.build()
}
// THIS CALLED FROM FRAGMENT WHEN GOOGLE BUTTON IS CLICKED
fun onGoogleClick() {
when (GoogleApiAvailability().isGooglePlayServicesAvailable(applicationContext)) {
0 -> {
beginGoogleSignIn()
}
1 -> {
toaster.show("Google services required")
}
2 -> {
toaster.show("Google services update required")
}
}
}
private fun beginGoogleSignIn() {
val tag = "$atag-beginGoogleSignIn"
oneTapClient.beginSignIn(signUpRequest)
.addOnSuccessListener(this) { result ->
try {
startIntentSenderForResult(
result.pendingIntent.intentSender, library.GOOGLE_SIGNIN_REQUEST_CODE,
null, 0, 0, 0)
} catch (e: IntentSender.SendIntentException) {
logg.d(atag, "Couldn't start One Tap UI: ${e.localizedMessage}")
}
}
.addOnFailureListener(this) { e ->
// No Google Accounts found. Just continue presenting the signed-out UI.
toaster.show("Please sign in to your google account on your phone")
logg.d(tag, e.localizedMessage)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
val tag = "$atag-onActivityResult"
super.onActivityResult(requestCode, resultCode, data)
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
if (requestCode == library.GOOGLE_SIGNIN_REQUEST_CODE) {
try {
val credential = oneTapClient.getSignInCredentialFromIntent(data)
token = credential.googleIdToken
when {
token != null -> {
// Got an ID token from Google. Use it to authenticate
// with your backend.
login = credential.id
name = credential.displayName
avatarUrl = credential.profilePictureUri.toString()
tryToLogin()
}
else -> {
// Shouldn't happen.
logg.d(atag, "No ID token!")
}
}
} catch (e: ApiException) {
when (e.statusCode) {
CommonStatusCodes.CANCELED -> {
toaster.show("Please sign in to your google account on your phone")
logg.d(tag, "One-tap dialog was closed.")
// Don't re-prompt the user.
}
CommonStatusCodes.NETWORK_ERROR -> {
logg.d(tag, "One-tap encountered a network error.")
// Try again or just ignore.
}
else -> {
logg.d(tag, "Couldn't get credential from result." +
" (${e.localizedMessage})")
}
}
}
}
}
}
The main problem is that on some of AVD it works well, on other AVD id gives an Error:
16: Cannot find a matching credential.
However on this AVD Google Services is up to date, and user is logged in to Google Play
On real device I got this error:
10: Caller not whitelisted to call this API.
Google services is also up to date here and user is logged in to Play Store.
Everywhere I used my real gmail address.
What can be wrong?
UPDATE
Spending a lot of time trying to solve this I have just figured out that OneTap is working on some devices, and is not working on other. Also tried to re-create credentials several times.
Not having very much time to solve this I just use both OneTap way and alternate way to sign in with Google credentials.
// In activity
lateinit var oneTapClient: SignInClient
lateinit var signUpRequest: BeginSignInRequest
private lateinit var gso: GoogleSignInOptions
lateinit var mGoogleSignInClient: GoogleSignInClient
private fun initApp() {
oneTapClient = Identity.getSignInClient(this)
signUpRequest = BeginSignInRequest.builder()
.setPasswordRequestOptions(
BeginSignInRequest.PasswordRequestOptions.builder()
.setSupported(false)
.build()
)
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
// 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(false)
.build()
)
// Automatically sign in when exactly one credential is retrieved.
.setAutoSelectEnabled(false)
.build()
gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestProfile()
.requestEmail()
.requestIdToken(getString(R.string.default_web_client_id))
.build()
mGoogleSignInClient = GoogleSignIn.getClient(this, gso)
}
// Somewhere else in fragment, 'parent' is reference to activity
// Call this when button clicked
private fun beginGoogleSignIn() {
parent.oneTapClient.beginSignIn(parent.signUpRequest)
.addOnSuccessListener(parent) { result ->
try {
startIntentSenderForResult(
result.pendingIntent.intentSender, state.library.GOOGLE_SIGNIN_REQUEST_CODE,
null, 0, 0, 0, null)
} catch (e: IntentSender.SendIntentException) {
stopSignIn("Couldn't start One Tap UI: ${e.localizedMessage}")
}
}
.addOnCanceledListener(parent) {
stopSignIn("Cancelled")
}
.addOnFailureListener(parent) { e ->
// Use alternate sign in
val signInIntent = parent.mGoogleSignInClient.signInIntent
startActivityForResult(signInIntent, state.library.GOOGLE_ALT_SIGNIN_REQUEST_CODE)
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
if (requestCode == state.library.GOOGLE_SIGNIN_REQUEST_CODE) {
try {
handleOneTapSignIn(data)
} catch (e: ApiException) {
val message: String
when (e.statusCode) {
CommonStatusCodes.CANCELED -> {
message = "Please sign in to your google account on your phone"
// Don't re-prompt the user.
}
CommonStatusCodes.NETWORK_ERROR -> {
// Try again or just ignore.
message = "One-tap encountered a network error."
}
else -> {
message = "Couldn't get credential from result." +
" (${e.localizedMessage})"
}
}
stopSignIn(message)
}
} else if (requestCode == state.library.GOOGLE_ALT_SIGNIN_REQUEST_CODE) {
try {
handleAlternateSignIn(data)
} catch (e: ApiException) {
if (e.statusCode == 12501) {
// Dismissed
stopSignIn()
} else {
stopSignIn("${e.statusCode}")
}
}
}
}
private fun handleOneTapSignIn(data: Intent?) {
val credential = parent.oneTapClient.getSignInCredentialFromIntent(data)
val token = credential.googleIdToken
when {
token != null -> {
// Got an ID token from Google. Use it to authenticate
// with your backend.
login = credential.id
avatarUrl = credential.profilePictureUri?.toString() ?: ""
tryToLogin()
}
else -> {
// Shouldn't happen.
stopSignIn("No ID token!")
}
}
}
private fun handleAlternateSignIn(data: Intent?) {
val task = GoogleSignIn.getSignedInAccountFromIntent(data)
try {
val account = task.getResult(ApiException::class.java)
// Signed in successfully, show authenticated UI.
login = account.email!!
token = account.idToken ?: ""
avatarUrl = account.photoUrl?.toString() ?: ""
tryToLogin()
} catch (e: ApiException) {
// The ApiException status code indicates the detailed failure reason.
// Please refer to the GoogleSignInStatusCodes class reference for more information.
val message = when (e.statusCode) {
CommonStatusCodes.NETWORK_ERROR -> {
"Could not reach network"
}
else -> {
"SignIn failed with exception $e"
}
}
stopSignIn(message)
}
}
UPDATE 2
It seems 16: Cannot find a matching credential on Android Emulators is related not to user credentials attempting to sign in, but an app credential in Google Cloud Console.
The issue is not reproduced in my case when I filled consent page at Google Cloud Console as described at Get started with One Tap sign-in and sign-up
(I have left empty fields for links to EULA, etc.). Then I have changed package name (for another reasons), then double check that this package name was the same in both credentials configs on Google Cloud Console and in google-services.json. Also I checked that google-services.json is located under [project_root]/app directory.
I will check this on real device in a few days.

Firebase isEmailVerify not working in Kotlin

NOTE: I was able to figure this out. There is no need to change the rules in Firebase. See code below.
ORIGINAL POST
I have an IOS app and I decided to build the Android/Kotlin version and I'm having a hard time with Firebase/isEmailVerify. I'm able to register a new user and send the email for verification, but, if I don't verify, I'm still able to login. I'm new at Kotlin. Any help is greatly appreciated.
UPDATED CODE
class LoginActivity : AppCompatActivity() {
lateinit var auth: FirebaseAuth
private var emailVerifier: Boolean = true
private val emailVerificationAlert = { _: DialogInterface, _: Int ->
Toast.makeText(this.applicationContext, android.R.string.yes, Toast.LENGTH_SHORT).show()
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
auth = FirebaseAuth.getInstance()
}
private fun verifyEmail() {
val user = FirebaseAuth.getInstance().currentUser
if (user != null) {
emailVerifier = user.isEmailVerified()
}
if (emailVerifier) {
finish()
} else {
userDidNotVerify()
auth.signOut()
}
}
fun loginBtnClicked(view: View) {
val email = loginEmailTxt.text.toString()
val password = loginPasswordTxt.text.toString()
auth.signInWithEmailAndPassword(email, password)
.addOnSuccessListener { exception ->
println("USER LOGGED IN")
verifyEmail()
}
.addOnFailureListener { exception ->
Log.e("Exception", "Could not sign in user - ${exception.localizedMessage}")
}
}
private fun userDidNotVerify() {
val builder = android.app.AlertDialog.Builder(this)
with(builder) {
this.setTitle("Confirm your email address.")
this.setMessage("A confirmation email has been sent to" + " " + (loginEmailTxt.text) + " " +
"." + " " + "Click on the confirmation link to activate your account")
this.setPositiveButton("OK", DialogInterface.OnClickListener(function = emailVerificationAlert))
this.show()
}
}
fun loginCreateClicked(view: View) {
val createIntent = Intent(this, CreateUserActivity::class.java)
startActivity(createIntent)
}
}
It's expected that the user can still sign in before the email is verified. This provides a way for your app to allow the user to request another verification email to be sent, in case something happened to the first one.
If you want to restrict what the user can do before the email is verified, you can check isEmailVerfied() on the UserInfo object, and you can use the auth.token.email_verified in security rules to limit their access to databases and storage also provided by Firebase.

Categories

Resources