简体   繁体   中英

using wp_set_auth_cookie with out any hook

Wordpress version 4.7.5

I am signing up new users from Instagram, I am successfully able signup the new user. after signup I am trying to logged in the user.

I can use hook, but would like better solution than the dirty one, I have posted as that will be totally unuseful .

if( $user_created ) {
    $new_user = get_user_by( 'id', $user_created ); 
    //$loggedin = programmatic_login( $new_user->user_login );
    //ob_start();
    if ( !is_user_logged_in() ) {
        wp_clear_auth_cookie();
        wp_set_current_user( $user_created, $new_user->user_login );
        wp_set_auth_cookie( $user_created, true );
        do_action( 'wp_login', $new_user->user_login );
        // wp_safe_redirect(site_url() . '/profile/');
        // exit;
        // $redirect_to=user_admin_url();
        // wp_safe_redirect($redirect_to);
        // exit();
    }
    //ob_end_clean();
} ?>
<script>jQuery(document).ready(function(){ window.location.href = "<?php echo site_url() . '/profile/'; ?>";});</script> <?php

also tried with a custom programmatic_login function from another post.

if I am trying to var_dump wp_get_current_user() and $_COOKIE below this, I am getting user object for wp_get_current_user() and array(1) { ["wordpress_test_cookie"]=> string(15) "WP Cookie check" } for $_COOKIE .

Important Edit

The code is inside a function, which is hooked to a hook, that is called in side a page that is after header is getting displayed, so we could not use init here. any other way of doing it and also because of this wp_safe_redirect() or header('Location: ') also not working .

Important Update with what I have just tried

A dirty work around

when I created the user from Instagram login, After successful creation I redirected the user to a page with get parameter something like ?user_id=$inserted_id and on wp hook, I tried to get the GET['user_id'] and logged it and it worked, trying to find a proper solution.

if ( $wpdb->insert_id ){  //that is registration with instagram
   ?>
    <script>jQuery(document).ready(function(){ window.location.href = "<?php echo get_bloginfo('url') . '/profile/?id=' . $wpdb->insert_id; ?>";});</script>
   <?php
}

and then

add_action( 'wp', 'login_current_user' );
function login_current_user(){
    if ( is_page() && get_the_id() == 863 ){
        if ( isset( $_GET['id'] ) ){
            if ( !is_user_logged_in() ) {
                $user_id = $_GET['id'];
                $user = get_user_by( 'id', $user_id ); 
                wp_clear_auth_cookie();
                wp_set_current_user( $user_id, $user->user_login );
                wp_set_auth_cookie( $user_id, true );
                do_action( 'wp_login', $user->user_login );
                if ( is_user_logged_in() ){
                    $redirect_to=site_url() . '/profile';
                    wp_safe_redirect($redirect_to);
                    exit();
                }
            }
        }
    }
}

Proble with dirty trick. If the id we are passing as get parameter exists in wp_users table then with no verification that will be logged in .

Update

I created a user_meta before redirecting to profile page and after verification login the user and removed the usermeta, just like an OTP . Trying to make it better if possible.

Below the code:-

if ( $wpdb->insert_id ){  //that is registration with instagram
    $temporary_token = sha1(rand());
    update_user_meta( $wpdb->insert_id, 'temporary_token', $temporary_token);
   ?>
    <script>jQuery(document).ready(function(){ window.location.href = "<?php echo get_bloginfo('url') . '/profile/?id=' . $wpdb->insert_id . '&token=' . $temporary_token; ?>";});</script>
   <?php
}

and then

add_action( 'wp', 'login_current_user' );
    function login_current_user(){
        if ( is_page() && get_the_id() == 863 ){
            if ( isset( $_GET['id'] ) ){
                if ( !is_user_logged_in() ) {
                    $user_id = $_GET['id'];
                    $user = get_user_by( 'id', $user_id );
                    if ( $_GET['token'] == get_user_meta( $user_id, 'temporary_token', true ) ){
                        delete_user_meta( $user_id, 'temporary_token', $_GET['token'] ); 
                        wp_clear_auth_cookie();
                        wp_set_current_user( $user_id, $user->user_login );
                        wp_set_auth_cookie( $user_id, true );
                        do_action( 'wp_login', $user->user_login );
                        if ( is_user_logged_in() ){
                            $redirect_to=site_url() . '/profile';
                            wp_safe_redirect($redirect_to);
                            exit();
                        }
                    }
                }
            }
        }
    }

If headers have been sent before wp_clear_auth_cookie() or wp_set_auth_cookie() are called then neither will work as both rely on PHP's setcookie function. The after_setup_theme action will occur before headers have been sent so hooking that and setting the cookies there should fix the issue.

function myPlugin_createUser(){
  // Probably need to put code that creates user here too otherwise $user_created will never return true
  if( $user_created ) {
      $new_user = get_user_by( 'id', $user_created ); 
      if ( !is_user_logged_in() ) {
          wp_clear_auth_cookie();
          wp_set_current_user( $user_created, $new_user->user_login );
          wp_set_auth_cookie( $user_created, true );
          do_action( 'wp_login', $new_user->user_login );
      }
  } 
}

add_action( 'after_setup_theme', 'myPlugin_createUser' );

Update:

If you're outputting view elements before triggering your createUser function it won't work so we need to make sure they run completely independent of each other. Below I've put together a simple example of how to achieve this - to the view we output a link which passes a GET parameter, this parameter is picked up by the plugin and runs the action before anything is rendered allowing us to set the cookie.

my-plugin.php

// Note: you'll need to include a completed version of myPlugin_createUser() function as above for these examples to work
add_shortcode( 'my-plugin', function() {  
   // I've used a GET request for simplicity- a form + POST request may be more practical for your purposes and will prevent caching issues.
   echo "<a href='?my_plugin_login_user=1'>Login</a>";
});

// Check for our GET parameter 
if( isset( $_GET['my_plugin_login_user'] ) ) {
  // Nothing should be rendered yet as plugin template hasn't even started loading yet so cookies should set fine
  add_action( 'plugins_loaded', 'myPlugin_createUser' ); 
}

page-my-template.php

<div> ...
    <?php 
        do_shortcode( 'my-plugin' ); 
    ?>
</div>

Update 2: If using Instagrams Authentication API the explicit flow outlined https://www.instagram.com/developer/authentication/ (most of the examples used below are taken from there) is probably the best approach. Below I'll give a brief rundown of how you could implement it. Much of it is taken from there with notes added.

Send the user off to https://api.instagram.com/oauth/authorize/?client_id=CLIENT-ID&redirect_uri=REDIRECT-URI&response_type=code

You could include the WordPress user ID as a parameter on the callback URL or if the user hasn't yet been created and you need to maintain state then you'll need to generate a temporary token that you can use later that's been associated with said data or store that data client side if it's not sensitive which is probably easier and better as it doesn't require a user to be logged in to function.

The user will then login

Not much to say about this step - if an error occurs they'll be redirected to http://your-redirect-uri?error=access_denied&error_reason=user_denied&error_description=The+user+denied+your+request

If login is successful the user will be redirected to http://your-redirect-uri?code=CODE

The CODE passed back on the redirect URL we can redeem for an access token.

So from here there's a multitude of ways we can handle it but essentially what we need is an endpoint for the redirect that we have sufficient control over to send HTTP headers before any of the HTTP response body is sent.

Methods of approaching this (not an exhaustive list):

  • Conditionally hooking on pages Instagram auths are allowed (as in your examples). This has the advantage of not requiring an additional redirect.
  • Custom page template
  • External script that manually bootstraps WordPress does what we need, then redirects back in

So now once we've got an endpoint setup we need to redeem the CODE for an access token. Adapted this snippet from https://gist.github.com/arturmamedov/7f5a90b85a20e06e344ebb88dc898d25

$uri = 'https://api.instagram.com/oauth/access_token'; 
$data = [
    'client_id' => '213esdaedasdasd12...YOUR_CLIENT_ID', 
    'client_secret' => 'a8b4aaf06c0da310...YOUR_CLIENT_SECRET', 
    'grant_type' => 'authorization_code', 
    'redirect_uri' => 'http://www.YOUR_REDIRECT_URL.it',      // The exact redirect URL as used previously
    'code' => $_GET['code']  
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $uri); // uri
curl_setopt($ch, CURLOPT_POST, true); // POST
curl_setopt($ch, CURLOPT_POSTFIELDS, $data); // POST DATA
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // RETURN RESULT true
curl_setopt($ch, CURLOPT_HEADER, 0); // RETURN HEADER false
curl_setopt($ch, CURLOPT_NOBODY, 0); // NO RETURN BODY false / we need the body to return
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); // VERIFY SSL HOST false
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); // VERIFY SSL PEER false
$result = json_decode(curl_exec($ch));

$result will be an object representation of the JSON response:

{
"access_token": "fb2e77d.47a0479900504cb3ab4a1f626d174d2d",
"user": {
    "id": "1574083",
    "username": "snoopdogg",
    "full_name": "Snoop Dogg",
    "profile_picture": "..."
  }
}

From here we just create our user/authenticate with WordPress and redirect to the desired page/render the template (no need to redirect if handled via conditional hooks) and restore the page state if needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM