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 toAccounts.account_id
), andexpiration
(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 anexpiration
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 itsreset_id
param in theAccountReset
table. If that GUID exists and theexpiration
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 itsexpiration
, 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 totrue
(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...
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
Woocommerce: Display Some Reviews Randomly on Home Page
(Mysql, PHP) How to Get Auto_Increment Field Value Before Inserting Data
MySQL Select from Tables Based on Multiple Rows
Relative Path in Require_Once Doesn't Work
How to Echo the Whole Content of a .HTML File in PHP
Send Xml Data to Webservice Using PHP Curl
Php: Why Isn't Exec() Returning Output
$Stmt->Execute():How to Know If Db Insert Was Successful
How to Define Global Functions in PHP
Performance in Pdo/Php/Mysql: Transaction Versus Direct Execution
What Is the "" Symbol in Url Used for in PHP
Simplexml: Working with Xml Containing Namespaces
Reconnection of Client When Server Reboots in Websocket
Stop Script Execution Upon Notice/Warning