Hello @Pavel_Duchovny and MongoDB team,
I think this shouldn’t be overlooked, to change a user email on the fly would be the best experience for the user.
My understanding is that their Auth ID would retain the same, and we would need to listen to a trigger “on user change email” on our Realm app to change the user data’s email.
Anyway, meanwhile a solution I found is to have sequence of 4 actions:
- Re-login the user (re-asking their password);
- Register a new user with the new email and old pass;
- Run a custom function to change the old email to the new one;
- Delete the Realm user and logout of the app;
I reckon this is not the best experience because the user will have to login again and click the confirmation email before doing so. Also the confirmation email may well have a message to welcome the user as it were new, which it isn’t.
Here is my personal code in case helps anyone:
// the user data has a "authId" field to attach the Realm User ID to it, also the email too;
// we need a on Login trigger that gets the user data by email and updates it with the new authId;
export async function changeEmail(email, password, newEmail) {
isLoading.value = true
let status = 'fail'
let code = 0
let error = ''
email = String(email).toLowerCase()
try {
// re-login
const credentials = Realm.Credentials.emailPassword(email, password)
const user = await app.logIn(credentials)
// create new account
// confirmation email will be sent
await app.emailPasswordAuth.registerUser(newEmail, password)
// custom function to change user data to new email
// the user data will have the new email, and still the old authId
await user.functions.userChangeEmail(newEmail)
// note this function must throw an Error if needed so this try block breaks
// delete old account
// WARNING if you have a Realm Trigger on user delete make sure it
// doesn't mess with the user data. In my case the trigger checks for the
// user email, so as it was just changed above, the user wouldn't be found,
// and the code would exit without changing anything.
await app.deleteUser(user)
// clean local user data
localStorage.clear()
sessionStorage.clear()
user.value = false
userData.value = {}
// IMPORTANT, this is our current state:
// - the user is logged out;
// - they will have to confirm their new email before login in;
// - the user data is still attached to the old authId;
// - we do have a login trigger that gets the user data by email and updates it
// with the new authId, that's basically why this works;
// at this point it was successful
// notify user they need to confirm their email and re-login
status = 'success'
// SUMMARY
// This is not the best experience, because the user will have to login again
// and click the confirmation email before doing so. Also the confirmation email
// may well have a message to welcome the user as it were new, which it isn't.
}
catch (err) {
console.log('Failed to change email', err, err.statusCode, err.error, err.errorCode, err.message)
code = +err.statusCode
error = err.error
}
isLoading.value = false
return { status, code, error }
}
If that is a bad practice, or if there are improvements to it, please let me know.