From 177b92b150c0b3785d6b30d09d7b6d466e284288 Mon Sep 17 00:00:00 2001 From: Francis Pineda Date: Thu, 7 Mar 2024 21:26:35 +0800 Subject: [PATCH 1/6] ALWP-1(feat): WooCommerce Support --- Affinidi.php | 12 +- assets/css/affinidi-login.css | 42 +-- includes/functions.php | 272 +++++++++++++++++-- includes/wp-affinidi-login-admin-options.php | 111 ++++++-- includes/wp-affinidi-login-callback.php | 87 +++--- includes/wp-affinidi-login-rewrites.php | 4 - templates/countries-list.php | 244 +++++++++++++++++ 7 files changed, 657 insertions(+), 115 deletions(-) create mode 100644 templates/countries-list.php diff --git a/Affinidi.php b/Affinidi.php index e1f150f..879fd1f 100644 --- a/Affinidi.php +++ b/Affinidi.php @@ -13,14 +13,14 @@ class Affinidi public static $_instance = null; protected $default_settings = [ - 'active' => 0, 'client_id' => '', 'backend' => '', - 'organization' => '', - 'server_oauth_trigger' => 'oauth', - 'server_auth_endpoint' => 'auth', - 'server_token_endpont' => 'token', - 'server_user_endpoint' => 'userinfo' + 'redirect_user_origin' => 0, + 'enable_ecommerce_support' => '', + 'ecommerce_sync_address_info' => 'billing', + 'ecommerce_show_al_button' => 'top_form', + 'affinidi_login_loginform_header' => 'Log in passwordless with', + 'affinidi_login_regform_header' => 'Sign up seamlessly with', ]; public function __construct() diff --git a/assets/css/affinidi-login.css b/assets/css/affinidi-login.css index e49f750..24a03db 100644 --- a/assets/css/affinidi-login.css +++ b/assets/css/affinidi-login.css @@ -1,7 +1,7 @@ @import url('https://fonts.googleapis.com/css2?family=Figtree:ital,wght@0,600;1,600&display=swap'); #affinidi-login-m { - border: 0; + border: 0 !important; width: 188px; height: 48px; display: flex; @@ -13,39 +13,49 @@ padding: 12px 20px; object-fit: contain; border-radius: 48px; - background: url('data:image/svg+xml,') no-repeat 20px center; - background-color: #1d58fc; - color: #ffffff; + background: url('data:image/svg+xml,') no-repeat 20px center !important; + background-color: #1d58fc !important; + color: #ffffff !important; padding-left: 60px; flex-grow: 0; - font-family: Figtree; - font-size: 16px; - font-weight: 600; + font-family: Figtree !important; + font-size: 16px !important; + font-weight: 600 !important; font-stretch: normal; font-style: normal; line-height: 1.25; letter-spacing: 0.6px; - text-decoration: none; + text-decoration: none !important; } #affinidi-login-m:hover { - background-color: #4a79fd; - filter: contrast(90%); + background-color: #4a79fd !important; + filter: contrast(90%) !important; } #affinidi-login-m:active { - background-color: #1d58fc; + background-color: #1d58fc !important; } #affinidi-login-m-loading { - background: url('data:image/svg+xml,') no-repeat center; - background-color: #4a79fd; - filter: contrast(90%); + background: url('data:image/svg+xml,') no-repeat center !important; + background-color: #4a79fd !important; + filter: contrast(90%) !important; } #affinidi-login-m:disabled { - background: url('data:image/svg+xml,') no-repeat 20px center; - background-color: #e6e6e9; + background: url('data:image/svg+xml,') no-repeat 20px center !important; + background-color: #e6e6e9 !important; +} + +div.form-affinidi-login { + margin: 10px 0 !important; + display: block; + text-align: center; +} + +div.form-affinidi-login a.affinidi-login { + margin: 0 auto; } \ No newline at end of file diff --git a/includes/functions.php b/includes/functions.php index d0aec98..8258824 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -6,10 +6,14 @@ function defaults() { return [ - 'client_id' => '', - 'backend' => '', - 'redirect_to_dashboard' => 0, - 'login_only' => 0, + 'client_id' => '', + 'backend' => '', + 'redirect_user_origin' => 0, + 'enable_ecommerce_support' => '', + 'ecommerce_sync_address_info' => 'billing', + 'ecommerce_show_al_button' => 'top_form', + 'affinidi_login_loginform_header' => 'Log in passwordless with', + 'affinidi_login_regform_header' => 'Sign up seamlessly with', ]; } @@ -73,6 +77,8 @@ function get_affinidi_login_url(string $redirect = ''): string */ function affinidi_login_form_button() { + + $redirect_to = affinidi_get_user_redirect_url(); ?>

Log in passwordless with

- Affinidi Login +
'Affinidi Login', - 'class' => 'button', + 'class' => 'affinidi-login', 'target' => '_self', 'text' => 'Affinidi Login' ], $atts); - return '' . $a['text'] . ''; + $redirect_to = affinidi_get_user_redirect_url(); + + return '' . $a['text'] . ''; } add_shortcode('affinidi_login', 'affinidi_login_button_shortcode'); +function get_wc_login_form_button($atts = array()) { + + $options = array_shift(get_options(array('affinidi_options'))); + + $display_button_header = $options['affinidi_login_loginform_header']; + + return ' +
' . affinidi_login_button_shortcode($atts) . '
'; +} + +function get_wc_regs_form_button($atts = array()) { + + $options = array_shift(get_options(array('affinidi_options'))); + + $display_button_header = $options['affinidi_login_regform_header']; + + return ' +
' . affinidi_login_button_shortcode($atts) . '
'; +} + /** * Get user login redirect. * Just in case the user wants to redirect the user to a new url. @@ -167,21 +200,218 @@ function affinidi_login_button_shortcode($atts) */ function affinidi_get_user_redirect_url(): string { - $options = get_option('affinidi_options'); - // Retrieves the URL to the user’s dashboard. - $user_redirect_set = $options['redirect_to_dashboard'] == '1' ? 'wp-admin' : 'index.php'; - $user_redirect = apply_filters('affinidi_user_redirect_url', $user_redirect_set); + // Global WP instance + global $wp; + + // Homepage as default redirect + $redirect_url = home_url(); + + // Redirect users if directly logging-in from wp-login.php form or redirect to dashboard option is set + if ( $GLOBALS['pagenow'] == 'wp-login.php' ) { + $redirect_url = admin_url(); + } + + // Check if we are passing redirect_to value, use it + if ( isset( $_REQUEST['redirect_to'] ) ) { + $redirect_url = esc_url_raw( wp_unslash( $_REQUEST['redirect_to'] ) ); + } else { + // Get the current page of the user where the button is triggered (if redirect to dashboard is not set) + if ( affinidi_get_option('redirect_user_origin') == 1) { + if ( ! empty( $wp->request ) ) { + if ( ! empty( $wp->did_permalink ) && $wp->did_permalink == true ) { + // build url from the current page with query strings attached + $redirect_url = home_url( add_query_arg( $_GET, trailingslashit( $wp->request ) ) ); + } else { + $redirect_url = home_url( add_query_arg( null, null ) ); + } + } else { + // homepage with query strings + if ( ! empty( $wp->query_string ) ) { + $redirect_url = home_url( '?' . $wp->query_string ); + } + } + } + } + + // generate random state + $state = md5( mt_rand() . microtime( true ) ); + // store redirect_to transient info to options + $affinidi_state_values = array( + $state => array( + 'redirect_to' => $redirect_url + ) + ); + set_transient("affinidi_user_redirect_to" . $state, $affinidi_state_values, 300); + + return $state; + +} + +function extract_claim($idToken, $field, $isCustom = true) { + + if ($isCustom) { + return isset($idToken['custom'][$field]) ? $idToken['custom'][$field] : ""; + } + // return from top-level + return isset($idToken[$field]) ? $idToken[$field] : ""; + +} + +function extract_user_info($info) { + + // extract user info + $email = extract_claim($info, 'email', false); + $firstName = extract_claim($info, 'given_name', false); + $lastName = extract_claim($info, 'family_name', false); + $displayName = trim("{$firstName} {$lastName}"); + + return array( + 'email' => $email, + 'first_name' => $firstName, + 'last_name' => $lastName, + 'display_name' => $displayName + ); + +} + +function extract_contact_info($info) { + // get list of countries for transformation + include_once(AFFINIDI_PLUGIN_DIR . '/templates/countries-list.php'); + // extract user info + $streetAddress = extract_claim($info['address'], 'street_address', false); + $locality = extract_claim($info['address'], 'locality', false); + $region = extract_claim($info['address'], 'region', false); + $postalCode = extract_claim($info['address'], 'postal_code', false); + $country = extract_claim($info['address'], 'country', false); + $phoneNumber = extract_claim($info, 'phone_number', false); + + // get the country code + $country = array_search($country, $countries_list); + + return array( + 'address_1' => $streetAddress, + 'city' => $locality, + 'state' => $region, + 'postcode' => $postalCode, + 'country' => $country, + 'phone' => $phoneNumber + ); +} + +function set_wc_billing_address($customer, $userInfo, $contactInfo) { + // set billing info + $customer->set_billing_first_name($userInfo['first_name']); + $customer->set_billing_last_name($userInfo['last_name']); + $customer->set_billing_email($userInfo['email']); + $customer->set_billing_phone($contactInfo['phone']); - return $user_redirect; + $customer->set_billing_address($contactInfo['address_1']); + $customer->set_billing_city($contactInfo['city']); + $customer->set_billing_state($contactInfo['state']); + $customer->set_billing_postcode($contactInfo['postcode']); + $customer->set_billing_country($contactInfo['country']); + + $customer->save(); +} + +function set_wc_shipping_address($customer, $userInfo, $contactInfo) { + // set billing info + $customer->set_shipping_first_name($userInfo['first_name']); + $customer->set_shipping_last_name($userInfo['last_name']); + $customer->set_shipping_phone($contactInfo['phone']); + + $customer->set_shipping_address($contactInfo['address_1']); + $customer->set_shipping_city($contactInfo['city']); + $customer->set_shipping_state($contactInfo['state']); + $customer->set_shipping_postcode($contactInfo['postcode']); + $customer->set_shipping_country($contactInfo['country']); + + $customer->save(); } -function extractProp($data, $name) { - $val = null; - foreach ($data as $customData) { - if (isset($customData[$name])) { - $val = $customData[$name]; - break; +function sync_address_info($userId, $userInfo, $contactInfo, $isSignup) { + // is WC support enabled? + if (is_woocommerce_activated()) { + // Get the WC_Customer instance object from user ID + $customer = new WC_Customer( $userId ); + // sync address info from Vault + if ($isSignup) { + set_wc_billing_address($customer, $userInfo, $contactInfo); + set_wc_shipping_address($customer, $userInfo, $contactInfo); + } else if (affinidi_get_option('ecommerce_sync_address_info') == "billing") { + set_wc_billing_address($customer, $userInfo, $contactInfo); + } else { + set_wc_billing_address($customer, $userInfo, $contactInfo); + set_wc_shipping_address($customer, $userInfo, $contactInfo); } } - return $val; } + + +function wp_users_can_signup() { + return is_multisite() ? users_can_register_signup_filter() : get_site_option( 'users_can_register' ); +} + + +function filter_woocommerce_customer_login_form( $html ) { + // display affinidi login button + printf(get_wc_login_form_button(array())); +} + +function filter_woocommerce_customer_regs_form( $html ) { + // display affinidi login button + printf(get_wc_regs_form_button(array())); +} + +function filter_position_al_button_wc_myaccount_form() { + + if (!is_woocommerce_activated()) { + return; + } + + $options = array_shift(get_options(array('affinidi_options'))); + + $display_button_opt = $options['ecommerce_show_al_button']; + + if ($display_button_opt == "") { + // do nothing + return; + } + + $button_position = $display_button_opt == 'top_form' ? 'woocommerce_login_form_start' : 'woocommerce_login_form_end'; + + add_filter( $button_position, 'filter_woocommerce_customer_login_form' ); +} + +function filter_position_al_button_wc_reg_form() { + + if (!is_woocommerce_activated()) { + return; + } + + $options = array_shift(get_options(array('affinidi_options'))); + + $display_button_opt = $options['ecommerce_show_al_button']; + + if ($display_button_opt == "") { + // do nothing + return; + } + + $button_position = $display_button_opt == 'top_form' ? 'woocommerce_register_form_start' : 'woocommerce_register_form_end'; + + add_filter( $button_position, 'filter_woocommerce_customer_regs_form' ); +} + +/** + * Check if WooCommerce is activated + */ +if ( ! function_exists( 'is_woocommerce_activated' ) ) { + function is_woocommerce_activated() { + if ( class_exists( 'woocommerce' ) ) { return true; } else { return false; } + } +} + +// filter display button for wc +filter_position_al_button_wc_myaccount_form(); +filter_position_al_button_wc_reg_form(); diff --git a/includes/wp-affinidi-login-admin-options.php b/includes/wp-affinidi-login-admin-options.php index eae29d5..4d67b62 100644 --- a/includes/wp-affinidi-login-admin-options.php +++ b/includes/wp-affinidi-login-admin-options.php @@ -47,7 +47,7 @@ public function add_page() public function options_do_page() { ?> -
+ +
+

There's no active supported e-commerce plugin configured on this WordPress site. E-Commerce Settings is disabled. To learn more about the supported e-commerce plugins, click here.

+

WooCommerce Settings

- + @@ -156,11 +168,11 @@ public function options_do_page() @@ -169,7 +181,7 @@ public function options_do_page() @@ -178,7 +190,7 @@ public function options_do_page()
Sync address info on loginSync customer profile from Vault -

Affinidi Login will always populate both Billing and Shipping Address info on Signup.

+

Select whether to sync the user profile from Vault whenever the user logs in to their WooCommerce account or only sync their profile on sign-up. Sign-up will populate the customer's billing and shipping address info.

+

Remember to modify the Presentation Definition and ID Token Mapping using the E-Commerce template to request the user's profile from Affinidi Vault.

Display Affinidi Login button -

If you choose "Don't display on Login Form", use the shortcode [affinidi_login] to display the button on your desired page.

+

If you choose "Use shortcode to display the button", use the shortcode [affinidi_login] and manually edit your desired page to display the button.

"/> -

+

Displays at the top of the Affinidi Login button in the Login Form of WooCommerce.

"/> -

+

Displays at the top of the Affinidi Login button in the Registration Form of WooCommerce.

From b18ef94f0a3935896e99e34996939294356471bb Mon Sep 17 00:00:00 2001 From: Francis Pineda Date: Thu, 14 Mar 2024 10:20:29 +0800 Subject: [PATCH 3/6] fix: added check for state --- includes/wp-affinidi-login-callback.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/includes/wp-affinidi-login-callback.php b/includes/wp-affinidi-login-callback.php index acb2ed4..8359645 100644 --- a/includes/wp-affinidi-login-callback.php +++ b/includes/wp-affinidi-login-callback.php @@ -22,9 +22,9 @@ // } // Authenticate Check and Redirect -if (!isset($_GET['code']) && !isset($_GET['error_description'])) { +if (!isset($_GET['code']) && !isset($_GET['error_description']) && !empty($_GET['state'])) { - // Grab a copy of the options and set the redirect location. + // Grab the state from the Auth URL and send to AL $state = $_GET['state']; // generate code verifier and challenge @@ -51,6 +51,16 @@ exit; } +// Check for error +if (empty($_GET['state'])) { + // log error description on server side + $log_message = "Affinidi Login: State is empty".PHP_EOL; + error_log($log_message); + // redirect user with error code + wp_safe_redirect($user_redirect . "?message=affinidi_login_failed"); + exit; +} + // retrieve state and get the transient info for redirect $state = sanitize_text_field($_GET['state']); $redirect_to = get_transient("affinidi_user_redirect_to".$state); From 8a0219506ddfa6e6a17be46a30cb1e0c8d30d78e Mon Sep 17 00:00:00 2001 From: Francis Pineda Date: Thu, 14 Mar 2024 11:28:10 +0800 Subject: [PATCH 4/6] feat: updated readme, bump version, and moved state checking --- README.md | 10 +++++--- includes/wp-affinidi-login-callback.php | 33 +++++++++++-------------- readme.txt | 14 +++++++---- wp-affinidi-login.php | 2 +- 4 files changed, 31 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 1b9e49c..910c085 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,12 @@ A paradigm shift in the registration and sign-in process, Affinidi Login is a ga |---|---|---| | Offers a secure and user-friendly alternative to traditional password-based authentication by eliminating passwords and thus removing the vulnerability to password-related attacks such as phishing and credential stuffing. | Leverages OID4VP to enable users to control their data and digital identity, selectively share their credentials and authenticate themselves across multiple platforms and devices without relying on a centralised identity provider. | Utilises OID4VP to enhance security of the authentication process by verifying user authenticity without the need for direct communication with the provider, reducing risk of tampering and ensuring data integrity. | +## Features ## + +- Passwordless login experience for users using Affinidi Login and Affinidi Vault. + +- Supports WooCommerce: Passwordless login, Seamless Customer Onboarding, and Customer profile creation. + ## Shortcode ## You can use the Affinidi Login as a shortcode in your editor. Just add the following to display the button in the page: @@ -63,6 +69,4 @@ We are here to help. Please [Contact Us](https://www.affinidi.com/get-in-touch) ## Changelog ## -### 1.0.0 ### - -* Initial release of Affinidi Login - Passwordless Authentication for Wordpress. \ No newline at end of file +Visit our [GitHub Releases](https://github.com/affinidi/wordpress-affinidi-login/releases) for the complete list of changes and releases. \ No newline at end of file diff --git a/includes/wp-affinidi-login-callback.php b/includes/wp-affinidi-login-callback.php index 8359645..122cb99 100644 --- a/includes/wp-affinidi-login-callback.php +++ b/includes/wp-affinidi-login-callback.php @@ -16,16 +16,24 @@ session_start(); } -// // Check for custom redirect -// if (!empty($_GET['redirect_uri'])) { -// $user_redirect = esc_url($_GET['redirect_uri']); -// } +// default to homepage if the state not found or expired +$user_redirect = home_url(); + +// Check for error, ensure state has value +if (empty($_GET['state'])) { + // log error description on server side + $log_message = "Affinidi Login: state is empty".PHP_EOL; + error_log($log_message); + // redirect user with error code + wp_safe_redirect($user_redirect . "?message=affinidi_login_failed"); + exit; +} // Authenticate Check and Redirect -if (!isset($_GET['code']) && !isset($_GET['error_description']) && !empty($_GET['state'])) { +if (!isset($_GET['code']) && !isset($_GET['error_description'])) { // Grab the state from the Auth URL and send to AL - $state = $_GET['state']; + $state = sanitize_text_field($_GET['state']); // generate code verifier and challenge $verifier_bytes = bin2hex(openssl_random_pseudo_bytes(32)); @@ -51,21 +59,9 @@ exit; } -// Check for error -if (empty($_GET['state'])) { - // log error description on server side - $log_message = "Affinidi Login: State is empty".PHP_EOL; - error_log($log_message); - // redirect user with error code - wp_safe_redirect($user_redirect . "?message=affinidi_login_failed"); - exit; -} - // retrieve state and get the transient info for redirect $state = sanitize_text_field($_GET['state']); $redirect_to = get_transient("affinidi_user_redirect_to".$state); -// default to homepage if the state not found or expired -$user_redirect = home_url(); // check if the state exists if (!empty($redirect_to) && !empty($redirect_to[$state]) && !empty($redirect_to[$state]['redirect_to'])) { // set the redirect url based on state @@ -81,7 +77,6 @@ error_log($log_message); // redirect user with error code wp_safe_redirect($user_redirect . "?message=affinidi_login_failed&error={$_GET['error']}"); - exit; } diff --git a/readme.txt b/readme.txt index 3084782..d98a542 100644 --- a/readme.txt +++ b/readme.txt @@ -1,10 +1,10 @@ === Affinidi Login - Passwordless Authentication === Contributors: affinidi -Tags: authentication, security, multi-factor, oauth2, sso +Tags: authentication, passwordless, multi-factor, sso, ecommerce Requires at least: 6.4 Tested up to: 6.4 Requires PHP: 7.4 -Stable tag: 1.0.0 +Stable tag: 1.1.0 License: MIT License URI: https://github.com/affinidi/wordpress-affinidi-login/blob/main/LICENSE @@ -26,6 +26,12 @@ Leverages OID4VP to enable users to control their data and digital identity, sel Utilises OID4VP to enhance security of the authentication process by verifying user authenticity without the need for direct communication with the provider, reducing risk of tampering and ensuring data integrity. += Features = + +- Passwordless login experience for users using Affinidi Login and Affinidi Vault. + +- Supports WooCommerce: Passwordless login, Seamless Customer Onboarding, and Customer profile creation. + = Shortcode = You can use the Affinidi Login as a shortcode in your editor. Just add the following to display the button in the page: @@ -83,6 +89,4 @@ We are here to help. Please [Contact Us](https://www.affinidi.com/get-in-touch) == Changelog == -= 1.0.0 = - -* Initial release of Affinidi Login - Passwordless Authentication for Wordpress. \ No newline at end of file +Visit our [GitHub Releases](https://github.com/affinidi/wordpress-affinidi-login/releases) for the complete list of changes and releases. \ No newline at end of file diff --git a/wp-affinidi-login.php b/wp-affinidi-login.php index 05bddad..74e32b9 100644 --- a/wp-affinidi-login.php +++ b/wp-affinidi-login.php @@ -18,7 +18,7 @@ * Plugin Name: Affinidi Login - Passwordless Authentication * Plugin URI: https://github.com/affinidi/wordpress-affinidi-login * Description: A paradigm shift in the registration and sign-in process, Affinidi Login is a game-changing solution for developers. With our revolutionary passwordless authentication solution your user's first sign-in doubles as their registration, and all the necessary data for onboarding can be requested during this streamlined sign-in/signup process. End users are in full control, ensuring that they consent to the information shared in a transparent and user-friendly manner. This streamlined approach empowers developers to create efficient user experiences with data integrity, enhanced security and privacy, and ensures compatibility with industry standards. - * Version: 1.0.0 + * Version: 1.1.0 * Requires at least: 6.4 * Requires PHP: 7.4 * Author: Affinidi From 830ecfa54bf8084862ea16ef20c6986e81f333b0 Mon Sep 17 00:00:00 2001 From: Francis Pineda Date: Thu, 14 Mar 2024 19:00:27 +0800 Subject: [PATCH 5/6] fix: added esc on button html --- includes/functions.php | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/includes/functions.php b/includes/functions.php index 409e86b..35d6c96 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -167,7 +167,7 @@ function affinidi_login_button_shortcode($atts = array()) $redirect_to = affinidi_get_user_redirect_url(); - return '' . $a['text'] . ''; + return '' . esc_html($a['text']) . ''; } add_shortcode('affinidi_login', 'affinidi_login_button_shortcode'); @@ -179,7 +179,7 @@ function get_wc_login_form_button($atts = array()) { $display_button_header = $options['affinidi_login_loginform_header']; return ' - '; + '; } function get_wc_regs_form_button($atts = array()) { @@ -189,7 +189,7 @@ function get_wc_regs_form_button($atts = array()) { $display_button_header = $options['affinidi_login_regform_header']; return ' - '; + '; } /** @@ -357,12 +357,18 @@ function wp_users_can_signup() { function filter_woocommerce_customer_login_form( $html ) { // display affinidi login button - printf(get_wc_login_form_button(array())); + // HTML attr and text already escaped + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + return printf(get_wc_login_form_button(array())); + // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped } function filter_woocommerce_customer_regs_form( $html ) { // display affinidi login button - printf(get_wc_regs_form_button(array())); + // HTML attr and text already escaped + // phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped + return printf(get_wc_regs_form_button(array())); + // phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped } function filter_position_al_button_wc_myaccount_form() { From 4bf09981ae0a4608fcc0fd2600e9d6ec1541de4e Mon Sep 17 00:00:00 2001 From: Francis Pineda Date: Thu, 14 Mar 2024 22:07:39 +0800 Subject: [PATCH 6/6] fix: random generator using wp_rand --- includes/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/functions.php b/includes/functions.php index 35d6c96..c5eba45 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -234,7 +234,7 @@ function affinidi_get_user_redirect_url(): string } // generate random state - $state = md5( mt_rand() . microtime( true ) ); + $state = md5( wp_rand() . microtime( true ) ); // store redirect_to transient info to options $affinidi_state_values = array( $state => array(