Firebase Auth not updating once password reset - angularjs

I can't quite seem to figure out how to reset the Firebase Auth object once it has loaded for the first time.
I am looking for the bool true value in auth.password.isTemporaryPassword which forces the user to reset their password. Once the user has carried this out this procedure and reset, the auth.password.isTemporaryPassword remains true.
The only way around this I have found is to log the user out and log them in again which refreshes the auth object.
login:
var ref = new Firebase(environment);
$firebaseAuth(ref)
.$authWithPassword({
email: email,
password: password
},sessionObj)
.then(function(authData) {
if (password.isTemporaryPassword === true) {
$state.go('resetpassword');
}
})
.catch(function(error) {
deferred.reject(error);
});
reset password:
$scope.reset.oldPassword = "oldPass";
$scope.reset.newPassword = "newPass";
$scope.reset.email = "usermail";
ref.changePassword($scope.reset, function(err) {
if(err) {
...
}
else {
$state.go('home')
}
})
password.isTemporaryPassword remains true until I log the user in again which seems hacky.

You should be able to use the onAuth function to listen for changes to authentication state:
ref.onAuth(function(authData) {
//user authenticated & needs to change her password
if(authData && authData.password.isTemporaryPassword) {
$state.go('resetpassword');
}
//else user is logged in with valid password
else if(authData) {
}
//else user is logged out
else {
}
});

Related

How to use navigator.credentials to store passwords in a React application?

In a react app I need to access MySQL servers, for which I need the user's credentials. In order to avoid having the user enter them every time a connection is opened I'd like to store the password in the browser's password store/manager.
According to MDN all major browsers should support the Credentials Management API. So I tried it like this:
private requestPassword = (commandId: string, args?: any[]): void => {
if (args && args.length > 0) {
// First check if we already have a password and don't ask for it, if so.
const request: IServicePasswordRequest = args[0];
navigator.credentials.get({
password: true,
mediation: "silent",
} as any).then((credential) => {
if (credential) {
const id = 0;
} else {
// Opens the password dialog.
this.setState({ request }, () => this.dialogRef.current?.open());
}
});
}
};
private closePanel = (e: React.SyntheticEvent, props: IButtonProperties): void => {
// Called when either OK or Cancel was clicked by the user, in the password dialog.
if (props.id === "ok") {
const { request } = this.state;
const options = {
password: {
id: request!.serviceId,
name: request!.user,
password: "root", // Just for test.
},
};
navigator.credentials.create(options as any).then((credential) => {
if (credential) {
navigator.credentials.store(credential).then((value) => {
console.log("Success: " + value);
}).catch((e) => {
console.log("Error: " + e);
});
}
});
}
this.dialogRef.current?.close();
};
However there are several problems with that:
The password member (as documented on the CredentialContainer.create() page is unknown to Typescript. I worked around that with an any cast. The returned credential is a PasswordCredential structure, and the content looks fine.
When storing the credentials, the success branch is taken but the promise value is null. Not sure if that's relevant at all.
When I call navigator.credentials.get I never get any credential back. And in fact I'm not surprised. Shouldn't it be necessary to pass in id and user name to find credentials? But the API doesn't allow that.
So, what's the correct approach here?

Firebase handle reset password emails for not verified users

When a new user registers the web application a verification email is sent to him. I prevent new users to log in before verification.
Meanwhile if the verification link expires and the user forgets the password he will click the reset password link and will receive an email.
So I think that I should handle reset password action together with verification at once. Otherwise user will not be able to login even after changing the password.
function handleResetPassword(auth, actionCode) {
auth.verifyPasswordResetCode(actionCode)
.then(function (email) {
// Showing the reset screen and ask the user for
// the new password.
}).catch(function (error) {
//
});
};
When user saves the new password:
function saveNewPassword() {
auth.confirmPasswordReset(actionCode, vm.form.password).then(function (resp) {
// Password reset has been confirmed and new password updated.
// Now auto sign in user
auth.signInWithEmailAndPassword(vm.email, vm.form.password).catch(function (error) {
// Handle Errors here.
});
firebase.auth().onAuthStateChanged(function (user) {
if (user) {
// user signed in.
// check whether the user is verified
// if not set true
user.updateProfile({ emailVerified: true })
}
});
}).catch(function (error) {
//
});
}
But the code below doesn't work as I expected as it has no affect. I can change other user data (e.g. displayName) but not (emailVerified). It only works with firebase email verification.
user.updateProfile({ emailVerified: true })
What is the recommended approach for this type of user scenario ?
You can't update emailVerified from the client, otherwise any unverified user would be able to do that without enforcing actual ownership of the email.
You would need to do it with the Admin SDK using an HTTP endpoint (you can use Firebase Functions for that too). However, you need to ensure that the password reset code succeeded. So in this case you need to run your code on the server. Here is how it would work:
var firebase = require('firebase');
var admin = require('firebase-admin');
// Initialize the client and admin instances.
// firebase.initializeApp(clientConfig);
// admin.initializeApp(adminConfig);
// Send the reset code and the new password to your backend.
var email = null;
// Get email corresponding to code.
firebase.auth().checkActionCode(actionCode)
.then(function(info) {
email = info.email;
// Confirm password reset.
firebase.auth().confirmPasswordReset(actionCode, password)
});
.then(function() {
// Get uid of user with corresponding email.
return admin.auth().getUserByEmail(email);
}).then(function(userRecord) {
// Password reset succeeded. Email can be verified as the user
// must have received the code via their email confirming
// ownership.
return admin.auth().updateUser(userRecord.uid, {emailVerified: true});
});

NativeScript Firebase plugin execution order

I'm learning NativeScript/Angular 2 and would need to get help with this issue.
In order to implement a multi-role login system within the Firebase platform I thought about this solution
Login the user through Firebase authentication
Query the /stores/ path for a store which has a merchantEmail field same as the e-mail that has just logged in
If I find it, I set the store ID inside a BackendService service which uses getString/setString to store tokens, then route to a MerchantDashboardComponent
If I don't find it, just route to a BuyerDashboardComponent
This is part of my code in the login.service:
login (email: string, password: string) {
return firebase.login({
type: firebase.LoginType.PASSWORD,
email: email,
password: password
}).then(
(result: any) => {
firebase.query(
(_result) => { // Here I set BackendService.storeID
Inside the .query() callback I am assigning the tokens I need in the application.
This is the method I'm using in my login.component:
doLogin () {
this.isAuthenticating = true;
if (!this.validateEmail()) {
alert("Please insert a valid email");
return false;
}
this.loginService.login(this.email, this.password).then(
() => {
this.isAuthenticating = false;
if (BackendService.loginError)
alert(BackendService.loginError)
else if (BackendService.storeID != '') {
this.router.navigate(['/merchant-dashboard'], {clearHistory: true});
}
else {
this.router.navigate(['/home/categories'], {clearHistory: true});
}
}
);
}
Everything works except for the fact that the Merchant gets routed to the Buyer dashboard. I've managed to discover that the execution order is not what I expected to be, in fact:
firebase.login() gets executed and returns a Promise
.then() handler is executed inside the doLogin() method
Only after this, the firebase.query() method completes the callback and my tokens are available, but doLogin() has already navigated the user because storeID is still empty when I need it
I hope I've been clear as much as possible.
Thanks for your attention.
Greetings,
Davide
So, the problem was in the login service method.
I now return the Promise generated by firebase.query(), which causes then() calls to chain in the correct order.
Yep that was exactly was I was going to propose to wrap it in a promise and create a chain.
example code
return new Promise<any>((resolve, reject) => {
firebase.login({ loginArguments })
.then((result: any) => {
var onQueryEvent = function (result) {
};
return firebase.query(
onQueryEvent,
"/owner",
{
// query arguments follows here
}
).then(res => {
return res;
})
})
.then(finalResult => {
console.log(finalResult);
try {
resolve(finalResult);
} catch (e) {
reject(e);
}
})
});

Getting Username from Firebase after email/password login [React Native]

I have created a simple login app using react native that let's users signup, login, and logout. my signup function takes a username that is then used in the createUser callback to generate a db entry with the uid as the key, and the username entered as a value. The answer in this post is the structure I followed - How do you include a username when storing email and password using Firebase (BaaS) in an Android app?
After the user is logged in, I'd like to get the username and display it but I'm having trouble figuring this out.
This is the code I currently have to attempt and do it:
var ref = new Firebase("https://myreactapp.firebaseio.com");
module.exports = React.createClass({
getInitialState: function() {
var authData = ref.getAuth();
var user = ref.child("users/" + authData.uid + "/username");
return {
username: user
};
},
This is how the code looks when I signup and the structure of my db.
var self = this;
let ref = new Firebase("https://myreactapp.firebaseio.com");
ref.createUser({
email : this.state.email,
password : this.state.password
}, function(error, authData) {
if (error) {
return this.setState({errorMessage: 'Error creating user'});
} else {
ref.child("users").child(authData.uid).set({
username: self.state.username
});
console.log("Successfully created user account with uid:", authData.uid);
ToastAndroid.show('Account Created', ToastAndroid.SHORT)
return self.props.navigator.pop();
}
});
----------------Not actual code-------------------------------------------------
DB
+users
--<uid>
-username -> value
--<uid>
-username -> value
I try to login and get an error of maximum call stack exceeded, but I have a feeling I'm going at this the wrong way. I've looked online, but everything I found was for retrieving data that is either being added, changed or deleted. All I want is to get this username once.

Login mechanism using AngularJS

Hi in my application login is working fine but one problem is for example my password is- secret if i enter SECRET with capital or SEcret also it is logging in, If i give wrong password it will return false any solution
Login Controller
app.controller('LoginController',function(loginService, $rootScope,$scope, $http,$location) {
$scope.login = function () {
$scope.log=loginService.getLogin( $scope.emailId , $scope.password).
then(function (response) {
console.log($scope.log);
console.log(response)
if (response.data.LoginVerificationResult.length === 0) {
alert('details are not Available for this emailId');
$scope.error=true;
} else {
$rootScope.name=response.data.LoginVerificationResult[0].UserName;
$scope.abc=response.data.LoginVerificationResult[0].UserType
console.log($scope.abc+"from.......");
sessionStorage.setItem("EmaiId",$scope.emailId);
sessionStorage.setItem("User Id",response.data.LoginVerificationResult[0].UserID);
sessionStorage.setItem("UserName",response.data.LoginVerificationResult[0].UserName);
sessionStorage.setItem("UserType",response.data.LoginVerificationResult[0].UserType);
$scope.UserType = sessionStorage.getItem("UserType");
console.log($scope.UserType +"from login controller")
if ($scope.UserType =='Hr') {
$location.path('/empRegister')
}
else if ($scope.UserType =='Admin') {
$location.path('/patientRegister')
}
else {
$location.path('/dashboard')
}
}
});
};
});
All scenarios are working fine but problem is with password mentioned above
The password matching is happening server-side.
Currently is set to match your passwords in a case-insensitive way. You should change this to match case-sensitive passwords

Resources