Facebook sdk error : Cross-site request forgery validation failed. The "state" param from the URL and session do not match - facebook-php-sdk

Anyone why i got this error? I am trying to log-in via Facebook.
It give me this error:
Cross-site request forgery validation failed. The "state" param from
the URL and session do not match.

This is my code!
$helper = $fb->getRedirectLoginHelper();
$this->facebook['callback_url'] = Yii::$app->urlManager->createAbsoluteUrl('users/user/set-info') . '&social_code=21g36fsdfe135e5';
$this->facebook['login_url'] = $helper->getLoginUrl('https://example.com/index.php?r=users/user/set-info&social_code=21g36fsdfe135e5', $this->facebook['permissions']);
try {
// Get the Facebook\GraphNodes\GraphUser object for the current user.
// If you provided a 'default_access_token', the '{access-token}' is optional.
$accessToken = $helper->getAccessToken();
} catch(Facebook\Exceptions\FacebookResponseException $e) {
// When Graph returns an error
echo 'Graph returned an error: ' . $e->getMessage();
exit;
} catch(Facebook\Exceptions\FacebookSDKException $e) {
// When validation fails or other local issues
echo 'Facebook SDK returned an error: ' . $e->getMessage();
exit;
}
if (isset($accessToken)) {
$this->setUserData([
'facebook' => [
'access_token' => (string) $accessToken
]
]);
// OAuth 2.0 client handler
$oAuth2Client = $fb->getOAuth2Client();
// Exchanges a short-lived access token for a long-lived one
$longLivedAccessToken = $oAuth2Client->getLongLivedAccessToken($_SESSION['facebook_access_token']);
$_SESSION['facebook_access_token'] = (string) $longLivedAccessToken;
// setting default access token to be used in script
$fb->setDefaultAccessToken($_SESSION['facebook_access_token']);
$response = $fb->get('/me?fields=email,id,name,first_name,last_name,link,gender,locale,timezone,updated_time,verified,location,friends', $accessToken);
$tmp = $response->getGraphObject();
echo 'Logged in as ' . $tmp->getName();
$this->user_information = [
'social_id' => $tmp['id'],
'social_name' => 'facebook',
'email' => $tmp['email'],
'public_profile' => $tmp['link'],
'first_name' => $tmp['first_name'],
'last_name' => $tmp['last_name'],
'gender' => $tmp['gender'],
'home_address' => $tmp['location']['name'],
'user_friends' => $tmp['friends'],
];
$friends_response = $fb->get('/me/taggable_friends?fields=id,name,picture,email&limit=5000', $accessToken);
$temp = $friends_response->getGraphEdge();
$friends = array();
for ($i = 0; $i < count($temp); ++$i) {
$friends[] = $temp[$i];
}
$_SESSION['friends'] = $friends;
$this->social_loggedIn = true;
}
else {
$this->social_loggedIn = false;
}

Please Go to the file
src/Facebook/PersistentData/PersistentDataFactory.php
In Your Facebook SDK
find this Code
if ('session' === $handler) {
new FacebookSessionPersistentDataHandler();
}
And Replace with
if ('session' === $handler) {
return new FacebookSessionPersistentDataHandler();
}

Related

WP API Authentication can not set the cookie

i try to make API authentication with my WP app
i have write the add the below code to add new fields and upon login it send data to External API if it user exist in API return login or create new WP user if not just don't do anything or gives an error, but i have the issue with Cookie now and get the "Error: Cookies are blocked due to unexpected output."
here is my code:
add_action('login_form', 'businessId', 10, 1);
function businessId()
{
?>
<div class="businessid_wrap">
<label for="businessId">business ID</label>
<input type="text" id="businessId" name="businessId" value=""/>
</div>
<?php
}
function au_auth($user, $username, $password)
{
$endpoint = 'will be my API endpoint url';
// Makes sure there is an endpoint set as well as username and password
if (!$endpoint || $user !== null || (empty($username) && empty($password))) {
return false;
}
$auth_args = [
'method' => 'POST',
'headers' => [
'Content-type: application/json',
],
'sslverify' => false,
'body' => [
'businessId' => $_POST['businessId'],
'userLogin' => $username,
'userPassword' => $password,
],
];
$response = wp_remote_post($endpoint, $auth_args);
$body = json_decode($response['body'], true);
var_dump ($response);
if (!$response) {
// User does not exist, send back an error message
$user = new WP_Error('denied', __('<strong>Error</strong>: Your username or password are incorrect.'));
} elseif ($response) {
/for now i just dumping the return data to check
var_dump ($response);
}
remove_action('authenticate', 'wp_authenticate_username_password', 20);
return $user;
}
add_filter('authenticate', 'au_auth', 10, 3);

Login WP - Connect single field to an external api

I made a plugin to allow wordpress login with external api.
Everything works, now what I have to do is that when a user logs in for the first time, the plugin checks to see if it is already present on wp, and where it was not already present, it creates a new user by taking behind username, email and password.
The new user is created but I would like it to bring with it also the id field from the external api saving it in an ACF field.
This is the code created so far:
function au_auth($user, $username, $password)
{
$options = get_option('au_options');
$endpoint = $options['au_apiurl'];
$user_email_key = 'email';
$password_key = 'password';
// Makes sure there is an endpoint set as well as username and password
if (!$endpoint || $user !== null || (empty($username) && empty($password))) {
return false;
}
// Check user exists locally
$user_exists = wp_authenticate_username_password(null, $username, $password);
if ($user_exists && $user_exists instanceof WP_User) {
$user = new WP_User($user_exists);
return $user;
}
// Build the POST request
$login_data = array(
$user_email_key => $username,
$password_key => $password
);
$auth_args = array(
'method' => 'POST',
'headers' => array(
'Content-type: application/x-www-form-urlencoded'
),
'sslverify' => false,
'body' => $login_data
);
$response = wp_remote_post($endpoint, $auth_args);
// Token if success; Not used right now
$response_token = json_decode($response['response']['token'], true);
$response_code = $response['response']['code'];
if ($response_code == 400) {
// User does not exist, send back an error message
$user = new WP_Error('denied', __("<strong>Error</strong>: Your username or password are incorrect."));
} else if ($response_code == 200) {
// External user exists, try to load the user info from the WordPress user table
$userobj = new WP_User();
// Does not return a WP_User object but a raw user object
$user = $userobj->get_data_by('email', $username);
if ($user && $user->ID) {
// Attempt to load the user with that ID
$user = new WP_User($user->ID);
}
} else {
// The user does not currently exist in the WordPress user table.
// Setup the minimum required user information
$userdata = array(
'user_email' => $username,
'user_login' => $username,
'user_pass' => $password
);
// A new user has been created
$new_user_id = wp_insert_user($userdata);
// Assign editor role to the new user (so he can access protected articles)
wp_update_user(
array(
'ID' => $new_user_id,
'role' => 'editor'
)
);
// Load the new user info
$user = new WP_User ($new_user_id);
}
}
// Useful for times when the external service is offline
remove_action('authenticate', 'wp_authenticate_username_password', 20);
return $user;
}
Anyone have any way how to help me?
Resolved! I hope this will help those who have found themselves in the same situation as me:
add_filter('authenticate', 'au_auth', 10, 3);
add_filter('register_new_user', 'au_registration', 10, 3);
// add_filter('profile_update', 'au_profile_update', 10, 3);
// add_filter('edit_user_profile_update', 'au_profile_edit', 10, 3);
function au_auth($user, $username, $password)
{
$options = get_option('au_options');
$endpoint = $options['au_apiurl'];
// Makes sure there is an endpoint set as well as username and password
if (!$endpoint || $user !== null || (empty($username) && empty($password))) {
return false;
}
$auth_args = [
'method' => 'POST',
'headers' => [
'Content-type: application/x-www-form-urlencoded',
],
'sslverify' => false,
'body' => [
'email' => $username,
'password' => $password,
],
];
$response = wp_remote_post($endpoint, $auth_args);
// Token if success; Not used right now
$response_token = json_decode($response['response']['token'], true);
$body = json_decode($response['body'], true);
$response_status_code = $response['response']['code'];
$success = $body !== 'KO';
if (!$success) {
// User does not exist, send back an error message
$user = new WP_Error('denied', __('<strong>Error</strong>: Your username
or password are incorrect.'));
} elseif ($success) {
$idExternal = $body['Id'];
$nome = $body['Name'];
$cognome = $body['Surname'];
$email = $body['Email'];
$userobj = new WP_User();
$user = $userobj->get_data_by('email', $email);
if ($user && $user->ID) {
$user = new WP_User($user->ID);
} else {
$userdata = [
'user_email' => $email,
'user_login' => join(' ', [$name, $surname]),
'user_pass' => '----',
];
$new_user_id = wp_insert_user($userdata);
$new_user_composite_id = 'user_' . $new_user_id;
update_field('field_60084ad3970a8', $idExternal, $new_user_composite_id);
update_field('field_5f22ca201c7b0', $name, $new_user_composite_id);
update_field('field_5f22ccd498f40', $surname, $new_user_composite_id);
update_field('field_5f22ce7b7c1db', $email, $new_user_composite_id);
$user = new WP_User($new_user_id);
}
}
remove_action('authenticate', 'wp_authenticate_username_password', 20);
return $user;
}

How avoid form resubmission on page refresh?

I'm doing a simple feedback form on WordPress. And like many people, I encountered the problem of resending the form when refresh the browser page. I know that this problem is solved through the use of the pattern "Post/Redirect/Get". Which says that you need after processing the data $_POST, request the same page using the $_GET method. But I can not use the result of the wp_mail function for redirection.
if(wp_mail($email, $email_subject, $email_message, $headers)) {
add_action('send_headers', 'simplemail_add_header');
}
function simplemail_add_header() {
header("Location: http://google.com");
}
It just does not work.
UPD
Here is my full code:
class SimpleMailer {
private $nonce = 'feedback_nonce';
public function __construct() {
add_action('phpmailer_init', array($this, 'simplemail_smtp_config'));
add_shortcode('simplemail', array($this, 'simplemail_sendmail'));
}
public function simplemail_smtp_config($phpmailer) {
$phpmailer->isSMTP();
$phpmailer->SetFrom("admin#mail.com");
$phpmailer->addAddress("sender#mail.com");
$phpmailer->Host = "ssl://smtp.mail.com";
$phpmailer->SMTPAuth = true;
$phpmailer->Port = 465;
$phpmailer->Username = "admin#mail.com";
$phpmailer->Password = "password";
$phpmailer->SMTPSecure = 'ssl';
}
public function simplemail_sendmail($shortcode_attributes) {
global $wp;
$result = "";
$error = false;
$data = array();
$required_fields = array("feedback_name", "feedback_email", "feedback_message");
$atts = shortcode_atts(array(
"email" => get_bloginfo('admin_email'),
"form_action" => home_url($wp->request),
"form_cls" => '',
"mail_subject" => "Feedback message from",
"pls_name" => 'Your Name',
"pls_email" => 'Your E-mail Address',
"pls_message" => 'Your Message',
"label_submit" => 'Submit',
"error_common" => 'There was some mistake. Try again, a little later.',
"error_empty" => 'Please fill in all the required fields.',
"error_noemail" => 'Please enter a valid e-mail address.',
"success" => 'Thanks for your e-mail! We\'ll get back to you as soon as we can.'
), $shortcode_attributes);
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
foreach ($_POST as $field => $value) {
if (get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
$data[$field] = trim(strip_tags($value));
}
foreach ($required_fields as $required_field) {
$value = trim($data[$required_field]);
if(empty($value)) {
$error = true;
$result = $atts['error_empty'];
}
}
if(!empty($data["feedback_blank"])) {
$error = true;
$result = $atts['error_empty'];
}
if(!is_email($data['feedback_email'])) {
$error = true;
$result = $atts['error_noemail'];
}
if(!wp_verify_nonce($data[$this->nonce],'simplemail_nonce')) {
$error = true;
$result = $atts['error_common'];
}
if ($error == false) {
$email_subject = $atts['mail_subject']." [".get_bloginfo('name')."]";
$email_message = $data['feedback_message']."\n\n";
$headers = "From: ".$data['feedback_name']." <".$data['feedback_email'].">\n";
$headers .= "Content-Type: text/plain; charset=UTF-8\n";
$headers .= "Content-Transfer-Encoding: 8bit\n";
if(wp_mail(null, $email_subject, $email_message, $headers)) {
add_action('send_headers', array($this, 'simplemail_add_header', 10, $atts['form_action']));
// wp_redirect( 'http://google.com', 301 );
// exit;
}
$data = array();
$result = $atts['success'];
}
}
return $this->simplemail_draw_form($atts, $data, $result);
}
public function simplemail_draw_form($atts, $data, $result) {
$output = "<form action='".$atts['form_action']."' class='".$atts['form_cls']."' method='post'>".PHP_EOL.
"<input type='text' name='feedback_name' placeholder='".$atts['pls_name']."' value='".#$data['feedback_name']."'>".PHP_EOL.
"<input type='text' name='feedback_blank'>".PHP_EOL.
"<input type='email' name='feedback_email' placeholder='".$atts['pls_email']."' value='".#$data['feedback_email']."'>".PHP_EOL.
"<textarea name='feedback_message' cols='30' rows='10' placeholder='".$atts['pls_message']."'>".#$data['feedback_message']."</textarea>".PHP_EOL;
$output .= wp_nonce_field('simplemail_nonce', $this->nonce, false);
$output .= ($result != "") ? '<div class="feedback-info">'.$result.'</div>' : '<div class="feedback-info"></div>';
$output .= "<button type='submit'>".$atts['label_submit']."</button>".PHP_EOL."</form>";
return $output;
}
public function simplemail_add_header($location) {
header("Location: {$location}");
}
}
$simplemailer = new SimpleMailer();
And I get this error if I uncomment the redirect. And nothing at all, if you try to use simplemail_add_header
Warning: Cannot modify header information - headers already sent by (output started at /var/www/vhosts/12/151953/webspace/httpdocs/skgk.kz/wp-includes/nav-menu-template.php:256) in /var/www/vhosts/12/151953/webspace/httpdocs/skgk.kz/wp-includes/pluggable.php on line 1216
I think you need to add a token in a hidden textbox and within the form to be submitted, the text in this text box will be the token and it need to change on every page load. Save this token in a session variable. Then add a condition at the top of the page to validate the token, if the token is different kill the loading process or display a message or whatever you feel is needed. You may also add token longevity to allow submitting of a page within certain amount of time.
The token creation, token validation and token longevity are normally a function somewhere that is called as needed and form different pages.
Edit:
If all you want is redirect the user to a different page then do:
if(mail succeed) {
header('location: thankyou.html');
}

Woocommerce Login Custome API Endpoint

I am developing an app using woocommerece store and using the Woocommerce REST API for Fetching the Products and Order details, but now I am facing the problem in login because Woocommerce didn't provide this type of API.
So I am creating a custom endpoint and trying this but I am getting the error 404, no rest route available.
Here is my custome end point which i registered.
add_action( 'rest_api_init', function () {
register_rest_route( 'wc/v2', '/login/)', array(
'methods' => 'POST',
'callback'=> 'my_awesome_func',
'args' => array(
),
) );
} );
Here is the login of Login but i think i am doing anything wrong at someplace so please check and help me .
function my_awesome_func( WP_REST_Request $request ) {
global $wpdb;
$username = $request['email'];
$password = $request['password'];
$db = new DbOperation();
$response = array();
$login_data = array();
$login_data['user_login'] = $username;
$login_data['user_password'] = $password;
$results = $wpdb->get_row( "SELECT ID FROM rd_users WHERE user_email='".$username."'");
$activation_id = $results->ID;
$activation_key = get_user_meta( $activation_id, 'has_to_be_activated', true );
if($activation_key != false ){
$results = 2;//if activation key exists than show the error
}
else{
$user_verify = wp_signon( $login_data, false );
if ( is_wp_error($user_verify) )
{
$results = 0; //show invalid username and password.
}
else {
$results = 1; //login success.
}
}
if ($results== 1) {
$user_info = get_userdata($student[0]->ID);
$response['id'] = $user_info->ID;
$response['name'] = $user_info->display_name;
$response['fname'] = $user_info->first_name;
$response['lname'] = $user_info->last_name;
$response['email'] = $user_info->user_email;
$response['status'] = 1;
$response["error"] = false;
$response['message'] = "You have successfully Logedin!";
} else {
if($results == 0){
$response['status'] = 0;
$response["error"] = true;
$response['message'] = "Invalid username or password";
}
else{
$response['status'] = 2;
$response["error"] = true;
$response['message'] ="Your account has not been activated yet.
To activate it check your email and clik on the activation link.";
}
}
return $response;
}
See what i have found,
used https authentication. In postman, instead of using oAuth1.0 as the authentication, use Basic authentication and pass consumer key as the username. And the password should be consumer secret.
I hope that would work.

Creating database schema on the fly

I would like to create database for user when he register. The code for database creation looks like this
$connectionFactory = $this->container->get('doctrine.dbal.connection_factory');
$connection = $connectionFactory->createConnection(array(
'driver' => 'pdo_mysql',
'user' => 'root',
'password' => 'mysecretpassword',
'host' => 'localhost',
'dbname' => 'userdatabase',
));
$params = $connection->getParams();
$name = isset($params['path']) ? $params['path'] : $params['dbname'];
unset($params['dbname']);
$tmpConnection = DriverManager::getConnection($params);
// Only quote if we don't have a path
if (!isset($params['path'])) {
$name = $tmpConnection->getDatabasePlatform()->quoteSingleIdentifier($name);
}
$error = false;
try {
$tmpConnection->getSchemaManager()->createDatabase($name);
echo sprintf('<info>Created database for connection named <comment>%s</comment></info>', $name);
} catch (\Exception $e) {
echo sprintf('<error>Could not create database for connection named <comment>%s</comment></error>', $name);
echo sprintf('<error>%s</error>', $e->getMessage());
$error = true;
}
$tmpConnection->close();
I have entities created for that database in AccountBundle but do not know how to create database schema when user database is created.
It is often used in the tests. An example can be seen in LiipFunctionalTestBundle.
$metadatas = $om->getMetadataFactory()->getAllMetadata();
$schemaTool = new SchemaTool($om);
$schemaTool->dropDatabase($name);
if (!empty($metadatas)) {
$schemaTool->createSchema($metadatas);
}

Resources