Forget Password Page, Creating a Generated Password to Email to the User

How to show the user their automatically generated password after social login?

You can allow the user to ask for a new password he/she specifies. The user will specify the password twice (password and confirm password fields) and then you:

  • encrypt the password the user asked for
  • store the encrypted value somewhere as password candidate (metadata, perhaps)
  • send an email to the user so he/she can confirm that he/she indeed asked for a password
  • once the user clicks on the link you have sent to him/her, replace the value of the password with the password candidate and remove the password candidate

Don't forget that the user is already logged in when he/she changes his/her password, adding an email validation to the password he/she asked for is pretty safe.

How to generate random password, or temporary URL, for resetting password in Zend Framework?

Zend Framework does not have a password-generating class. Here's an article on how to use the PEAR module Text_Password to generate a password:
https://web.archive.org/web/1/http://blogs.techrepublic%2ecom%2ecom/howdoi/?p=118

However, it's not a good security practice to send the password in a plain email. Instead, you should reset their account so they can temporarily log in without giving a password (given an expiring URL you send them in the email), and once they log in, require them to update their own password to something they know. Then store the salted hash of their password.


Here's some suggestion off the top of my head for doing this in Zend Framework:

  • Define a table AccountReset with fields: reset_id (GUID primary key), account_id (reference to Accounts.account_id), and expiration (timestamp).
  • Implement an action called AccountController::resetAction(), i.e. in the same controller you use for creating accounts, logging in, changing passwords, etc.
  • When a user chooses to reset his account, insert a new row in an AccountReset table with a new GUID, a reference to the user's account, and an expiration 30 minutes or so in the future.
  • Send an email to the address on file for that user, including an URL he should click on: "https.../account/reset/reset_id/<GUID>" (if you're clever with routing rules, you can shorten that URL, but keep the GUID in it).
  • When AccountController::resetAction() receives the request, it looks up its reset_id param in the AccountReset table. If that GUID exists and the expiration time has not passed, present the user with a form to change his password (without requiring he is authenticated and logged in).
  • If resetAction() receives a request with no GUID, or the GUID doesn't exist in the database, or that row has passed its expiration, then this action may instead present the user with a button to initiate a new reset request, and send an email with a new GUID. Remember to make this button a POST request!

Because the GUID is communicated only in email to the address for that user, no one else can gain access to change the password. Even if the user's email gets intercepted, there's only a limited time the GUID would grant that access.

If you want to be even more cautious, you could make note of the client IP address in the AccountReset table, and require the password be changed from a client with the same IP address, within that 30 minute window.

This is only off-the-cuff, and I haven't implemented it or evaluated it for proper security. If you are responsible for implementing security, it's your duty to read up on security issues. A well-regarded resource for PHP security is http://phpsecurity.org/.

Get Sitefinitys Generated Password Reset URL

Since you already have the URL of the reset password page, I guess your issue is getting the proper query string to pass to that page.

Looking at the source code with JustDecompile, the query string is made up of this:

?vk=userValidationKeyEncoded&cp=pr

The cp=pr seems to be hardcoded, so we leave it as is, the question is how the userValidationKeyEncoded is made.

Again, looking in the code, it is this line:

 string userValidationKeyEncoded = UserManager.GetUserValidationKeyEncoded(userByEmail);

And finally:

private static string GetUserValidationKeyEncoded(User user)
{
object[] providerName = new object[] { user.ProviderName, ',', user.Id, ',', DateTime.UtcNow };
string str = string.Format("{0}{1}{2}{3}{4}", providerName);
return SecurityManager.EncryptData(str).UrlEncode();
}

You can use the above code to manually generate the validationKey.

Send an email notification with the generated password on WooCommerce user creation

There are some mistakes in your code regarding WC_Order properties that are not accessible anymore since WooCommerce 3 and replaced by getter and setter methods, see this thread…

As you are creating some users programmatically, to send the Customer New Account email notification, you can use WC_Email_Customer_New_Account trigger() method that has 3 arguments variables:

  • $user_id -- The User ID (required)
  • $user_pass -- The User password (optional) - Required in your case.
  • $password_generated -- Whether the password was generated automatically or not (true or false). This optional argument displays the password on the email notification when is set to true (default is false).

To make the generated password displayed in "Customer New Account" email notification, you also need to enable in WooCommerce > Settings > Accounts & Privacy the option line:

"When creating an account, automatically generate an account password"

Once done, your working code is going to be:

// Customer Billing Email
$order_email = $order->get_billing_email();

// Generate a random password with 12 chars
$user_pass = wp_generate_password();

// Create new user with email as username & newly generated password
$user_id = wp_create_user( $order_email, $user_pass, $order_email );

$user = new WP_User($user_id); // Get the WP_User Object instance from user ID
$user->set_role('customer'); // Set the WooCommerce "customer" user role

// Get all WooCommerce emails Objects from WC_Emails Object instance
$emails = WC()->mailer()->get_emails();

// Send WooCommerce "Customer New Account" email notification with the password
$emails['WC_Email_Customer_New_Account']->trigger( $user_id, $user_pass, true );

//WC guest customer identification
update_user_meta( $user_id, 'guest', 'yes' );

update_user_meta( $user_id, 'first_name', $order->$order->get_billing_first_name() );
update_user_meta( $user_id, 'last_name', $order->get_billing_last_name() );

//user's billing data
update_user_meta( $user_id, 'billing_address_1', $order->get_billing_address_1() );
update_user_meta( $user_id, 'billing_address_2', $order->get_billing_address_2() );
update_user_meta( $user_id, 'billing_city', $order->get_billing_city() );
update_user_meta( $user_id, 'billing_company', $order->get_billing_company() );
update_user_meta( $user_id, 'billing_country', $order->get_billing_country() );
update_user_meta( $user_id, 'billing_email', $order_email );
update_user_meta( $user_id, 'billing_first_name', $order->get_billing_first_name() );
update_user_meta( $user_id, 'billing_last_name', $order->get_billing_last_name() );
update_user_meta( $user_id, 'billing_phone', $order->get_billing_phone() );
update_user_meta( $user_id, 'billing_postcode', $order->get_billing_postcode() );
update_user_meta( $user_id, 'billing_state', $order->get_billing_state() );

// user's shipping data
update_user_meta( $user_id, 'shipping_address_1', $order->get_shipping_address_1() );
update_user_meta( $user_id, 'shipping_address_2', $order->get_shipping_address_2() );
update_user_meta( $user_id, 'shipping_city', $order->get_shipping_city() );
update_user_meta( $user_id, 'shipping_company', $order->get_shipping_company() );
update_user_meta( $user_id, 'shipping_country', $order->get_shipping_country() );
update_user_meta( $user_id, 'shipping_first_name', $order->get_shipping_first_name() );
update_user_meta( $user_id, 'shipping_last_name', $order->get_shipping_last_name() );
update_user_meta( $user_id, 'shipping_method', $order->get_shipping_method() );
update_user_meta( $user_id, 'shipping_postcode', $order->get_shipping_postcode() );
update_user_meta( $user_id, 'shipping_state', $order->get_shipping_state() );

// link past orders to this newly created customer
wc_update_new_customer_past_orders( $user_id );

Now as you will see a notification is sent to the customer, with its login and password, with the link to the login area...

Sample Image


Template customizations for "Customer new account email":

The related template path is plugins/woocommerce/templates/emails/customer-new-account.php
and can be overridden by copying it to yourtheme/woocommerce/emails/customer-new-account.php

The available arguments (variables) passed to this template are:

  • $email_heading -- The email_header,
  • $user_login -- User Login,
  • $user_pass -- User password,
  • $blogname -- Title of the site,
  • $password_generated -- Whether the password was generated automatically or not,
  • $sent_to_admin (false by default),
  • $plain_text (false by default),
  • $email -- The email instance Object.


Related Topics



Leave a reply



Submit