Firebase Email Verification Redirect Url - ios

I incorporated Firebase's email verification for my iOS mobile app and am trying to resolve the following issues:
The length of the redirect url appears extremely long. It looks like it repeats itself.
https://app.page.link?link=https://app.firebaseapp.com//auth/action?apiKey%3XXX%26mode%3DverifyEmail%26oobCode%3XXX%26continueUrl%3Dhttps://www.app.com/?verifyemail%253Demail#gmail.com%26lang%3Den&ibi=com.app.app&ifl=https://app.firebaseapp.com//auth/action?apiKey%3XXX%26mode%3DverifyEmail%26oobCode%3XXX%26continueUrl%3Dhttps://www.app.com/?verifyemail%253Demail#gmail.com%26lang%3Den
When I set handleCodeInApp equal to true, and am redirected back to the app when I click on the redirect url, the user's email is not verified. Whereas when I set it to false and go through Firebase's provided web widget, it does get verified. Wasn't able to find documentation that outlined handling the former in swift...
Any thoughts are appreciated.
func sendActivationEmail(_ user: User) {
let actionCodeSettings = ActionCodeSettings.init()
let redirectUrl = String(format: "https://www.app.com/?verifyemail=%#", user.email!)
actionCodeSettings.handleCodeInApp = true
actionCodeSettings.url = URL(string: redirectUrl)
actionCodeSettings.setIOSBundleID("com.app.app")
Auth.auth().currentUser?.sendEmailVerification(with: actionCodeSettings) { error in
guard error == nil else {
AlertController.showAlert(self, title: "Send Error", message: error!.localizedDescription)
return
}
}
}

Make sure you're verifying the oobCode that is part of the callback URL.
Auth.auth().applyActionCode(oobCode!, completion: { (err) in
if err == nil {
// reload the current user
}
})
Once you have done that, try reloading the the user's profile from the server after verifying the email.
Auth.auth().currentUser?.reload(completion: {
(error) in
if(Auth.auth().currentUser?.isEmailVerified)! {
print("email verified")
} else {
print("email NOT verified")
}
})

Related

SwiftUI Firebase: Sending a message to the mail

In the function I want to add sending a message to the confirmation email, if you confirm, then you get to Homescreen(), else SignUp().
What do I need to add to my code?
func register(){
if self.email != ""{
if self.pass == self.repass{
Auth.auth().createUser(withEmail: self.email, password: self.pass) { (res, err) in
if err != nil{
self.error = err!.localizedDescription
self.alert.toggle()
return
}
print("success")
UserDefaults.standard.set(true, forKey: "status")
NotificationCenter.default.post(name: NSNotification.Name("status"), object: nil)
}
}
else{
self.error = "Password mismatch"
self.alert.toggle()
}
}
else{
self.error = "Please fill all the contents properly"
self.alert.toggle()
}
}
SignUp() - View where registration takes place
Homescreen() - View where the message about successful registration appears
You can first try to sign the user in with email using following code:
Auth.auth().signIn(withEmail: email, link: self.link) { authResult, error in
// ...
}
If there is an error, present the error alert to the user.
If sign in was successful, you can use the following code to get the current user:
if let user = Auth.auth().currentUser {
}
And inside of the curly brackets just check if current user has already verified the E-Mail with user.isEmailVerified
If that is the case, then simply present your Homescreen
If current user has not verified his E-Mail yet, you can present an alert, where the user can choose if he wants to have the verification E-Mail sent out again. If that is the case, you can simply resend the E-Mail with
user.sendEmailVerification {error in
}
and the user will get his verification E-Mail or there can occur an error while sending the Email so you should handle that error aswell!
Good luck!
You can also check the Firebase docs for Email Verification

Getting Twitter profile info with Firebase Auth Swift

I'm trying to get basic details of a user signing into my app with their Twitter account. I am able to sign them in but not too sure where to go from here.
I'm pretty sure I need to use this get request but am unsure how to structure the request. Am also a little lost which token I include.
I haven't had much experience with the REST API as you could tell. I have Postman set up so if someone could point me in the right direction about accessing the data I could take it from there.
Thanks
#IBAction func twitterSignupPress() {
provider.getCredentialWith(nil) { credential, error in
if error != nil {
print("Error attempting to sign up using Twitter: \(error!)")
} else {
Auth.auth().signIn(with: credential!) { authResult, error in
if error != nil {
print("Error with Twitter signin")
} else {
print("Successful signin using Twitter")
let oAuthCredential = authResult?.credential as! OAuthCredential
print(oAuthCredential.accessToken!) // Prints token
print(oAuthCredential.idToken) // Prints nil
}
}
}
}
}
Was as simple as adding authResult?.additionalUserInfo?.profile

Failure to login straight after verifying but successful on second tap

I am creating an app that allow user sign up/login through Firebase API. The flow is that the user signs up a new account, is taken to an email verification page (the user is sent a verification email at this point), then they may login after verifying their account. The problem is, on the first time they tap "Login", the alert is shown that they still need to be verified (even after verifying) but when they tap again it will successfully log them in. I want the user to be able to login successfully first time straight after verifying. Thank you in advance for the help.
private func login() {
let userEmail = textFrom(loginEmail)
let userPassword = textFrom(loginPassword)
let authUser = Auth.auth().currentUser
self.loginButton.loadingIndicator(show: true)
guard let isVerified = authUser?.isEmailVerified else { return }
Auth.auth().signIn(withEmail: userEmail, password: userPassword, completion: {(user, error) in
if let firebaseError = error {
self.loginButton.loadingIndicator(show: false)
self.showError(firebaseError)
}
if authUser != nil && !isVerified {
self.loginButton.loadingIndicator(show: false)
self.presentAlert(withTitle: "Verify Email", message: "Please verify your email first before logging in")
self.clearFields()
} else {
self.loginButton.loadingIndicator(show: false)
self.transitionToHome()
}
})
}
Also, I know this isn't Github but I am new to using Firebase, if you think my logic can be improved (this function is called in the IBAction of the login button) then please let me know. Thank you :)
Are you positive that the alert you quoted is the one being returned? No other similarly worded alerts coming from somewhere else?
If so, then the only way it can be shown is if isVerified is false and authUser is not nil (which is redundant, because if it was nil, the guard let ... optional chaining would have immediately returned from the function).
So it looks like authUser.isEmailVerified is returning false. You can verify this by adding a breakpoint at the line: if authUser != nil && !isVerified {
Without knowing more it's impossible to say what's going on.

iOS/Swift/Firebase Authentication: Help Needed on Accessing "isNewUser"

In my iOS/Swift/Firebase app, I am trying to access the "isNewUser" parameter after a user successfully signs in via email/password so that I can pop a window to compel them to reset their password from the temporary one initially assigned upon user creation.
Any insights would be appreciated. Thanks.
The .isNewUser Bool is available from the FirebaseAuth AdditionalUserInfo class.
Here is the link. In order to utilize this code, please see a demo sign in function I wrote below.
Auth.auth().signIn(with: credential) { (result, error) in
if let error = error {
print("Error: \(error)");
return;
}
// Fetch the user's info
guard let uid = result?.user.uid else {return}
// Safely unwrap the boolean value rather than forcing it with "!" which could crash your app if a nil value is found
guard let newUserStatus = result?.additionalUserInfo?.isNewUser else {return}
// Test the value
print("\nIs new user? \(newUserStatus)\n")
if newUserStatus == true {
// Provide your alert prompt
}
else{
// Transition view to continue into the app
}
}

Firebase unlink email/password auth from user on iOS

I'm trying to unlink email/password authentication from a user in Swift on iOS. I've read the documentation and managed to link and unlink Facebook authentication without a problem. However, after linking email/password credentials successfully, the providerData object is nil. The providerID is "Firebase" but when I pass that to the unlink code the following error is thrown:
Error Domain=FIRAuthErrorDomain Code=17016 "User was not linked to an account with the given provider." UserInfo={NSLocalizedDescription=User was not linked to an account with the given provider., error_name=ERROR_NO_SUCH_PROVIDER}
The unlink code I'm using is:
let providerId = (FIRAuth.auth()?.currentUser?.providerID)!
print("Trying to unlink:",providerId) // providerId = "Firebase"
FIRAuth.auth()?.currentUser?.unlinkFromProvider(providerId) { user, error in
if let error = error {
print("Unlink error:", error)
} else {
// Provider unlinked from account successfully
print("Unlinked...user.uid:", user!.uid, "Anonymous?:", user!.anonymous)
}
}
Reading the docs and having got it working for Facebook, I expected the providerData array to be populated with something after email authentication. So is my linking code wrong (it doesn't throw an error and appears to work fine)?
My linking code:
let credential = FIREmailPasswordAuthProvider.credentialWithEmail(email, password: password)
FIRAuth.auth()?.currentUser!.linkWithCredential(credential) { (user, error) in
if user != nil && error == nil {
// Success
self.success?(user: user!)
dispatch_async(dispatch_get_main_queue(), {
self.dismissViewControllerAnimated(true, completion: nil)
if type == "new" {
print("New user logged in...")
}
if type == "existing" {
print("Existing user logged in...")
}
})
} else {
print("Login error:",error)
self.showOKAlertWithTitle("Login Error", message: error!.localizedDescription)
}
}
Any pointers of how I can modify my approach would be great.
To get the profile information retrieved from the sign-in providers linked to a user, use the providerData property.
if let user = FIRAuth.auth()?.currentUser {
for profile in user.providerData {
// Id of the provider (ex: facebook.com)
let providerID = profile.providerID
}
} else {
// No user is signed in.
}
Calling FIRAuth.auth()?.currentUser?.providerID will result to "firebase".

Resources