Firebase/Swift 2 - How to get an authenticated users password and email - ios

I'm trying to setup a password reset within an app using swift 2 and Firebase.
Following Firebases example:
let ref = Firebase(url: "https://<YOUR-FIREBASE-APP>.firebaseio.com")
ref.changePasswordForUser("bobtony#example.com", fromOld: "correcthorsebatterystaple",
toNew: "batteryhorsestaplecorrect", withCompletionBlock: { error in
if error != nil {
// There was an error processing the request
} else {
// Password changed successfully
}
})
How can I access an authenticated users email & password in order to pass those values to this function instead of the current mock data?
I'm not interested in sending a temporary password in a pass reset email.
I was thinking that I'd be able to access these values by something like:
let ref = Firebase(url: firebaseURL)
ref.authData.providerData.someValueHere
But I haven't been able to figure it out.
How can I access these values from the currently authenticated user?

How can I access an authenticated users email & password
Firebase does not store the user's password. Instead it stores a hash of the user's password. That means that there is no API from Firebase that returns a user's password.

Related

Given a users UID can I access his profile info?

I know that I can save user info to his profile with firebase. But I am wondering if I am able to get this same info when all I have is a UID?
As I understand it I can only do this to get the info:
Auth.auth().currentUser.displayName...
It seems like If I want to be able to fetch other users info I would have to keep a copy of their data in a users node.
Am I correct? Or can I access their profile info withought having to keep a copy?
If you use firebase authentication, then you can retrieve the current user info. So, if currently user X is logged in and he is authenticated, you can retrieve the following info about him:
let user = Auth.auth().currentUser
if let user = user {
// The user's ID, unique to the Firebase project.
// Do NOT use this value to authenticate with your backend server,
// if you have one. Use getTokenWithCompletion:completion: instead.
let uid = user.uid
let email = user.email
let photoURL = user.photoURL
// ...
}
If you want to retrieve information about other users, then in that case you need to use firebase database:
users
userId (firebase authentication)
name : user X
userId
name : user Y
Depending on the reason you need this data, you can actually get access to an auth user by using the firebase-admin package.
inside of your firebase function - or node.js backend - (this is only for backend node.js functions, not for front-end), you can get the user by doing the following:
const admin = require("firebase-admin");
const authUser = await admin.auth().getUser(uid);
authUser = authUser.toJSON(); // Optional
You can read more about retrieving user data here
If you want to load in multiple users at once, you can easily use the getUsers function and it's also possible to load in the user based on other information like email:
getUser(uid)
getUserByEmail(email)
getUserByPhoneNumber(phoneNumber)

How to check after login user is login through Facebook in firebase for ios swift?

My app is having facebook & email password login with firebase. Now for those user who are signed with Facebook, I don't want to verify their emails. but in Auth.auth().currentUser?.isEmailVerified its return false always. so is there any other method to detect user is logged in with facebook. I know i can store value inside user default before login but after uninstall & reinstall app i will lost that userdefault. while firebase keep user logged in. i can use keychain for that but if firebase directly provide that then that will make easy for coding.
I find one solution with firebase methods:
if let providerData = Auth.auth().currentUser?.providerData {
for userInfo in providerData {
switch userInfo.providerID {
case "facebook.com":
print("Facebook Login")
//isVerifiededUser = true
default:
print("provider is \(userInfo.providerID)")
}
}
}
You can use:
if let user = Auth.auth().currentUser {
if FBSDKAccessToken.current() != nil {
// logged in using facebook
}
else {
// logged in using manual email/password method
}
}
so you can send verification emails to only those who are logged in using email/password method.
Firebase doesn't provide a method to show which was the first method used to create Firebase account. You will have a list of the all the providers attached to a firebase user with their emails/ phone number attached to them.
Firebase by default only set emails verified for Google SignIn, for other providers Firebase behavior is to set false (although some times it do set the email verified true randomly). The reason is that Firebase cannot guarantee that email is verified by facebook on their platform but incase of Google firebase has trust.
One option is you always send verification email no matter facebook or Email Auth. Second is that you ditch Email password login and instead use new Email Link Authentication, which eliminates the email auth needed in password login.
EDIT:
if you only allow one method to be used at a time then you can get the providers list from the firebase user and check if the providers list has 'password' signin method present, send a verification email after checking email verified, else don't send the email and continue the app
Here is the resource to email link authentication: https://firebase.google.com/docs/auth/ios/email-link-auth
This code means that at some point the user registered using Facebook, but it does not mean that at this point the user is using this provider for access. If the user has these providers ["google.com", "facebook.com"] it will also return true . 😊🖤
fileprivate func userHasFBProvider() -> Bool{
var fBProvider = false
guard let providerData = Auth.auth().currentUser?.providerData else {
return fBProvider
}
for userInfo in providerData {
switch userInfo.providerID {
case "facebook.com":
fBProvider = true
default:
fBProvider = false
}
}
return fBProvider
}

Firebase verifying email while being logged in

I have the following logic in my iOS app:
User registers
Firebase sends an email confirmation
Returns to login screen
Now if the user logs in, without verifying the email, then we have a user session and isEmailVerified is false.
I only need to check the isEmailVerified in a certain point in the app.
Also I think signing the user in, checking the field and signing the user out would be bad practise.
I'd need to reauthenticate the user, what is the best way of doing this? How can I, after the user has logged in, switch the status of isEmailVerified?
Thanks
First, you need to have the email and password to create a credential. Your user already provided this on the login page... So the email and password to persistent storage on iOS. In Android, the equivalent would be SharedPreferences.
I do not code in iOS, but this will give you the idea for the logic.
Then, when you get to that point in your app where email verified is called:
if (user.isEmailVerified) == true {
// you do not need to hold the email and password in persistent storage anymore.
// go into your persistent storage and delete the data.
} else {
// get the email and password the user saved in persistent storage.
String email = persistentStorage.getEmail();
String password = persistentStorage.getPassword();
var user = firebase.auth().currentUser;
var credentials = firebase.auth.EmailAuthProvider.credential(email, password);
user.reauthenticate(credentials);
// then, when finished reauthenticating, check whether isEmailVerified() == true;
}

Firebase Auth (with Custom Token, for Linkedin) returns a user with no email and no data (only uid)

I'm trying to login with Linkedin and Firebase. I generate on my server the custom token, I have my private key, I use RS256 and this is my payload:
"iss" : service_account_email
"sub" : service_account_email
"aud", "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
"iat", Date().timeIntervalSince1970
"exp", Date().timeIntervalSince1970.advanced(by: 3600)
"uid", String.randomString(length:28)
I create the token, send it back to the app and from this I do:
Auth.auth().signIn(withCustomToken: token!, completion: { (user, error) in
I receive no error and a user back, so the token is valid. The problem is that the user has no values (no email, no displayName etc). the only thing is the uid which is the one that I set with: String.randomString(length:28)
How can I retrieve the user email and other info? In my linkedin account I have a displayname, email, picture etc. But here nothing.
Thanks
You have to set that manually. Firebase Auth has APIs to update profile (photo URL and display name) as well as email. You can send this LinkedIn data along with the custom token to your app, sign in with custom token and then update profile and email on that signed in custom token user.
By the way, set the LinkedIn ID as the UID for that user. Do not use a random string. Otherwise the next time you sign in with LinkedIn, the same user will map to another one.

Create Firebase User on ios without auto-signin [duplicate]

This question already has answers here:
Firebase kicks out current user
(19 answers)
Closed 6 years ago.
i'm writing an ios-app with firebase as backend.
In my app, there are some admins, who should be able to create new users. A new user should not be able to create an account on his own.
On web, i'm using the function
ref.createUser({
email: ctrl.user.email,
password: ctrl.user.password
}, function(error, userData) { // }
with a random password and reset the password afterwards. So the user will receive an email with a password reset link and can set a new password and log in after that. After creating the user, i'm storing all relevant userdata to the database.
On ios i'm trying to create a new user with:
FIRAuth.auth()?.createUser(withEmail: email, password: password) { (user, error) in }
But if I do it this way, I'm signed out with my admin-account and logged in with my fresh created account. Due to this, I'm not able, to store the userdata to the database, because this is restricted to admins....
Is there a way on ios to only create an user, without to auto-signin with this user?
Best wishes
Tobi
EDIT
I've written an AWS lambda function with the firebase admin sdk for node.js and create the user inside the function and trigger the function via a webservice-call from my ios-app.
Not perfect, but working....
Yes, calling createUser(withEmail:, password:) will log in a new user. To achieve what you are trying to do, I recommend a workaround by doing something like this (assume that currently an Admin is logged in):
// Create the values
var email = alreadySelectedUserEmail
var password = arc4random_uniform(1000000) // or another random number
// Send the information to the database
FIRDatabase.database().reference().child("user_data").child(email) .
setValue("lorem ipsum") // or another value
// THEN create the user, AFTER sending the data
// This will automatically log you in to the new account
FIRAuth.auth()?.createUser(withEmail: email,
password: password) { (user, error) in
// Check for any errors
if let error = error {
print error
} else {
// If there are none, LOG OUT…
try! FIRAuth.auth()!.signOut()
// …and log back into Admin (with whatever login info they have)
FIRAuth.auth()?.signIn(withEmail: adminEmail,
password: adminPassword) { (user, error) in
// Check for any errors
if let error = error {
print error
} else {
// All done, new account created!
}
}
}

Resources