Start a new topic

Unable to login with generated password

Hello,


I'm working on enabling push notifications on my cordova application using the Kinvey javascript SDK.
I'm creating Kinvey users on the first login to the application using Kinvey.User.signup and only giving a username, so the password is generated by the library.
My idea was to store the generated password in my database and check if it exists to determine whether I want to login an existing user or create a new user.
I tried this, but it seems that I'm unable to log in users using the stored password. I get an InvalidCredentialsError.

Am I doing something wrong or am I not supposed to use the generated passwords for future authentication? I could always just generate the password myself and pass it along the username during the signup. This just seems a bit silly, so I'm wondering if there's a cleaner solution.


Thoughts and comments appreciated, thanks!


- Tim


Hi Timothy,

From the provided description I assume the issue is one of the following:

  • The passed username or password are incorrect. You may first review the passed username and password with console.log() to make sure they are taken and passed correctly. 
  • There is an option that the Kinvey instance has a stored active user with expired token. Thus, when performing the Kinvey.User.login() method with the expired access token would result in an InvalidCredentialsError. Therefore, please consider this approach, which checks if there is a logged-in user rather than a stored password on the device and then checks if the available active user access token has not expired:

        let appId = 'your-app-Id';
        let appSecret = 'your-app-sercret';
    
        Kinvey.init({
            appKey: appId,
            appSecret: appSecret
        });
    
        // Get the locally stored activeUser
        let activeUser = Kinvey.User.getActiveUser();
        let userPromise;
    
        if (activeUser === null) {
            // Sign up user using implicit signup (the username and password will be auto-generated)
            userPromise = Kinvey.User.signup();
    
        } else {
            // Make a request to the server to get the latest user object properties and check if the access token has not expired
            userPromise = activeUser.me();
        }
    
        userPromise
            // Skipped if no error
            .catch(userError => {
                if (userError.name === 'InvalidCredentialsError') {
                    // Clear the activeUser using logout and then initiate login and return login response
                    return Kinvey.User.logout()
                        .then((logoutResult) => {
                            let storedUser = JSON.parse(window.localStorage.getItem("kinveyUser"));
    
                            return Kinvey.User.login(storedUser.username, storedUser.password);
                        });
                }
                // If the error is different from InvalidCredentialsError, forward it down the chain
                return Promise.reject(userError);
            })
            .then(user => {
                if (user.data.password) {
                    // New user is created
                    let kinveyUser = {
                        username: user.data.username,
                        password: user.data.password
                    };
    
                    window.localStorage.setItem("kinveyUser", JSON.stringify(kinveyUser));
                }
            })
            .then(()=> {
                registerDeviceToKinvey();
            })
            .catch(e => console.log(e));


    Let me know if this was the case and if the above approach has helped.


1 person likes this

Hi Timothy,


Thank you for posting what the problem was, it is indeed a valid use case - I have logged it in our backlog for fixing.


I am glad that you were able to move pass this issue.


Regards

Martin

Hi Timothy,


I assume you are using the Kinvey Phonegap SDK for your Cordova application.


You should be able to login with the auto-generated password and username just fine. 

Could you please provide a code snippet on the signup and login procedure you are following in order to further determine what is causing the issue?


Regards

Martin

Hi Martin,

Thank you for letting me know it is supposed to work, I will keep trying.
My logic for signup and logging in is roughly as follows:
 

if (!kinveyPasswordFromDB) {
	// signup
	var promise = Kinvey.User.signup({
		username: usernameFromDB
	})
	.then(function(user) {
		storeKinveyPassword(user.data.password);
		registerDeviceToKinvey();
	})
	.catch(function(error) {
		console.log(error);
	});
} else {
	// login
	var promise = Kinvey.User.login({
		username: usernameFromDB,
		password: kinveyPasswordFromDB
	})
	.then(function(user) {
		registerDeviceToKinvey();
	})
	.catch(function(error) {
		console.log(error);
	});
}

   

The way I am testing this right now is logging into my app with a fresh user.  A kinvey user is created using Kinvey's signup function, which generates a password that I save into my database. I then log out the user from the app, which includes calling Kinvey's logout function. I then log in again with this user, and since I have a password stored for this user in my database, I can determine that a Kinvey user already exists and so I attempt to log in using the stored username + password combination, but I get a 401 error 

about invalid credentials.

Okay I tried using the signup with a hardcoded password and it still doesn't allow me to sign the user in after logging out.

So we can rule out the problem being with the generated password. My whole logic is roughly as follows:


 

initializeKinvey() {
	var passwordFromDB = getPassword();
	var usernameFromDB = getUsername();
	Kinvey.init(settings);
	var promise = Kinvey.ping()
	.then(function (response) {
		console.log('Kinvey Ping Success. Kinvey Service is alive, version: ' + response.version + ', response: ' + response.kinvey);
		signupOrLogin(usernameFromDB, passwordFromDB);
	})
	.catch(function (error) {
		console.log(error);
	});
}

signupOrLogin(usernameFromDB, passwordFromDB) {
	if (!passwordFromDB) {
		// signup
		var promise = Kinvey.User.signup({
			//password: '123',
			username: usernameFromDB
		})
		.then(function(user) {
			storeKinveyPassword(user.data.password);
			registerDeviceToKinvey();
		})
		.catch(function(error) {
			console.log(error);
		});
	} else {
		// login
		var promise = Kinvey.User.login({
			username: usernameFromDB,
			password: passwordFromDB
		})
		.then(function(user) {
			registerDeviceToKinvey();
		})
		.catch(function(error) {
			console.log(error);
		});
	}
}

 

Reading through the docs, could it have something to do with the logout invalidating the user's auth token?

"Logout destroys the session’s associated auth token, such that subsequent attempts to re-use that token will yield a 401 Unauthorized (error) response."

I managed to solve this by converting my username to a string instead of an integer before signing up. Looking at the Kinvey SDK source, it looks like you are converting usernames to string in the login function, but not doing so in the signup function: https://github.com/Kinvey/js-sdk/blob/master/src/core/user/user.js#L185

If I am not mistaken this would allow me to sign up a user with the username: 123, but when I try to login my username would be converted to "123" by the SDK. This would explain my issues logging in.

- Tim




Login or Signup to post a comment