WixUsers.approveByToken() fails with "the requested item no longer exists" error

Question:
Why does WixUsers.approveByToken() fail with “the requested item no longer exists” error?

Product:
Wix Velo backend code - i.e. http-functions.js

What are you trying to achieve:
Update 5/17/24

This is related to support ticket 1650663814. I can demonstrate the error easily with the code below. wixUsers.register() works and the result contains a registration token. I immediately use that token to attempt a wixUsers.approveByToken(), which fails with the error I showed in my original post:

        try {
            results = await wixUsers.register(memberEmail, password, {
                "contactInfo": {
                [FIRSTNAME_FIELD]: firstName,
                [LASTNAME_FIELD]: lastName}
            });
        } catch (error) {
            console.log("Could not register user, error was: " + error);
            response.body = {[RESULT_KEY]: false,[ERRORMSG_KEY] : "User already has been registered."};
            return ok(response);
        }
        userid = results.user.id;
        registrationtoken = results.approvalToken;
        // Simple test here to see if the token as passed will work immediately for approval
        try {
            console.log("Attempting to approveByToken using token: " + registrationtoken);
            await wixUsers.approveByToken(registrationtoken);
            response.body = {[RESULT_KEY]: true};
        } catch (error) {
            console.log("I had an error trying to approve the token for registration for: " + memberEmail + " error was: " + error);
            response.body= {[RESULT_KEY]:false, [ERRORMSG_KEY]: "I had an error trying to approve the token for registration for: " + memberEmail};
            return ok(response);
        }

This flow is nearly identical to the flow as shown in the API docs for this function:


   // Register the member
   const registration = await authentication.register(email, password, options);
   const approvalToken = registration.approvalToken;
   console.log('Member is now registered with the site and pending approval');

    // Approve the member and get session token, to be used to log in the member client-side
   const sessionToken = await authentication.approveByToken(approvalToken);
    console.log('Member is now approved, but not logged in');

    return {
      approved: true,
      sessionToken: sessionToken
    };

Can anyone help me understand why this is failing?


We created a mobile app that communicates with our Wix website via code in http-functions.js, in this case to register the user with the website. We have implemented a common two-factor authentication flow that has been working fine until somewhat recently (just got a notification from a potential customer that they could not register).

The flow goes like this:

‘requestregistration’ function within http-functions.js is called by our mobile app:

  1. The function is passed the user first/last name, email address, password, deviceID from the mobile device.
  2. This function performs some rudimentary checks (has the user previously registered, etc.).
  3. Then the Wixusers.register() function is called with the email, password, and first/last name info:
			try {
				results = await wixUsers.register(memberEmail, password, {
					"contactInfo": {
					[FIRSTNAME_FIELD]: firstName,
					[LASTNAME_FIELD]: lastName}
				});
			} catch (error) {
				console.log("Could not register user, error was: " + error);
				response.body = {[RESULT_KEY]: false,[ERRORMSG_KEY] : "User already has been registered."};
				return ok(response);
			}

This part of the flow works as expected. Our website is set up to require manual approval of new members, so this newly inserted member is in ‘pending’ status.

  1. The requestregistration function pulls the registration token from the results, and we have validated that it is a valid token:

            `registrationtoken = results.approvalToken;`
    
  2. Then the function creates a random 6 digit registration code, which is inserted into a collection, along with a timeout value (default is 10 minutes from when the function was called).

  3. The function then emails the user using the email address passed in including the registration code, and then returns the registration token token to the mobile app:

	try {
		console.log("Attempting to send registration email in production mode");
		await wixUsers.emailUser('verifyAppRegistration', userid, {
			"variables": {
				"subscriberFirstName": firstName,
				"verificationCode": generatedCode,
				"expirationDate" : expirationDateString
			}
		});
		console.log("Registration email in production mode sent successfully.");
		response.body = {[RESULT_KEY]: true,[REGISTRATIONTOKEN_ARG]:registrationtoken,[USERID_ARG] : userid};

	} catch (error) {
		console.error("Within app registration, got error emailing confirmation of registration to user: " + memberEmail + " error was: " + error);
		response.body = {[RESULT_KEY]: false,[ERRORMSG_KEY] : "Could not generate email with verification code."};
	}			

        return ok(response);

On the mobile app side, when it receives the return value from the website, it saves the registration token, then presents a screen to the user to enter the 6 digit code that was sent to the email address they entered. When they enter the 6 digit code, a separate function in http-function.js named ‘validateappregcoe’ is called. It does the following:

  1. Pulls the email address, validation code and approval token from the request. We have validated that this subsequent call properly uses the exact same approval token that was returned from the first function call. This is done within 5 minutes of having received it.

  2. Validates that the timeout on the validation code has not expired.

  3. Then attempts to approve the member and move them from pending to active like this:

			try {
				console.log("Attempting to approveByToken using token: " + approvalToken);
				await wixUsers.approveByToken(approvalToken);
				response.body = {[RESULT_KEY]: true};
			} catch (error) {
				console.log("I had an error trying to approve the token for registration for: " + memberEmail + " error was: " + error);
				response.body= {[RESULT_KEY]:false, [ERRORMSG_KEY]: "I had an error trying to approve the token for registration for: " + memberEmail};
				return ok(response);
			}

This always returns an error (it used to work fine), from the logs it looks like this:

Error: Not Found: the requested item no longer exists.

Why does approveByToken() no longer work?

What have you already tried:
I have searched the forum, and found similar errors to the register() function, but nothing about approveByToken(). I did file a ticket with support: 1650663814, but no response yet.

Additional information:

Have you tried using the wix-members library? The wix-users library is deprecated.

anthony -

Thanks - we notice the docs say ‘will continue to work’, but understand they may not be getting updated - will check out the new library!

Update 5/22/24 -

This now appears to be working, initially it took some time for the triggered email to show up, subsequent tests now show it is showing up within 2-3 minutes. Our authentication flow is back to working!

==========
OK - well I have made progress - we had to change to using these imports:

import { triggeredEmails } from 'wix-crm-backend';
import { members } from 'wix-members-backend';
import {getSecret} from 'wix-secrets-backend';
import {authentication} from 'wix-members-backend';

Now the registration function still works:

				results = await authentication.register(memberEmail, password, {
					"contactInfo": {
					[FIRSTNAME_FIELD]: firstName,
					[LASTNAME_FIELD]: lastName}
				});

And I get a valid contact and pending site member created, just as before. I then pull out the id of the newly created member:

userid = results.member._id;

Then I use this to send a triggered email as before:

console.log("Attempting to send registration email in production mode");
await triggeredEmails.emailContact('verifyAppRegistration', userid, {
	"variables": {
			"subscriberFirstName": firstName,
			"verificationCode": generatedCode,
			"expirationDate" : expirationDateString
	}
});
console.log("Registration email in production mode sent successfully.");
response.body = {[RESULT_KEY]: true,[REGISTRATIONTOKEN_ARG]:registrationtoken,[USERID_ARG] : userid};
return ok(response);

This all processes with no errors, we show in the logs it all seems happy:

except…we never get the email that was sent. This is to a valid email address we use for testing.

Is there some other setup that has to be done that didn’t have to be done before such that the email can be sent? It is using the email address of the newly registered member, who is in ‘pending’ status.

We also tried the ‘emailContact’ API, with similar results: no errors thrown but no email received either.

We believe we have correctly followed the steps as documented to send the triggered email, but maybe we are missing some sort of other setup that has to happen?

Thanks!

Tad

1 Like

Awesome, glad you got it resolved!