title: Stuck with ajax login/logout script in WordPress
body: <p>i've got some problems on login/logout script for my ajax-driven page.</p>
  
  <p>First the scenario:
  The website should be fully ajax. On ajax request only the content and the menu should be changed. This works fine for normal pages and post, but login / logout give me some trouble on security with wp_create_nonce and check_ajax_referer.</p>
  
  <p>Here's the relevant code:</p>
  
  <p>functions.php</p>
  
  <pre><code>/* Login */
  function ajax_login_init() {
  
      wp_register_script('ajax-login-script', get_stylesheet_directory_uri() . '/js/ajax.login.script.js', array('jquery') ); 
      wp_enqueue_script('ajax-login-script');
  
      wp_localize_script( 'ajax-login-script', 'ajax_login_object', array( 
          'ajaxurl' =&gt; admin_url( 'admin-ajax.php' ),
          'redirecturl' =&gt; home_url(),
          'loadingmessage' =&gt; __('Sending user info, please wait...')
      ));
  
      // Enable the user with no privileges to run ajax_login() in AJAX
      add_action( 'wp_ajax_nopriv_ajaxlogin', 'ajax_login' );
  }
  
  function ajax_login(){
  
      // First check the nonce, if it fails the function will break
      check_ajax_referer( 'ajax-login-nonce', 'security' );
  
      // Nonce is checked, get the POST data and sign user on
      $info = array();
      $info['user_login'] = $_POST['username'];
      $info['user_password'] = $_POST['password'];
      $info['remember'] = true;
  
      $user_signon = wp_signon( $info, false );
      if ( is_wp_error($user_signon) ){
          echo json_encode(array('loggedin'=&gt;false, 'message'=&gt;__('Wrong username or password.')));
      } else {
          echo json_encode(array('loggedin'=&gt;true, 'message'=&gt;__('Login successful, redirecting...')));
      }
  
      wp_die();
  }
  
  /** Logout */
  function ajax_logout_init() {   
  
      wp_register_script('ajax-logout-script', get_stylesheet_directory_uri() . '/js/ajax.logout.script.js', array('jquery') );   
      wp_enqueue_script('ajax-logout-script');
  
      global $current_user;
  
      wp_localize_script( 'ajax-logout-script', 'ajax_logout_object', array( 
          'LoggedIn' =&gt; is_user_logged_in(),
          'username' =&gt; $current_user-&gt;display_name,
          'logoutURL' =&gt; wp_logout_url(),
          'ajax_url' =&gt; admin_url('admin-ajax.php'),
          'logout_nonce' =&gt; wp_create_nonce('ajax-logout-nonce')
      ));
  
      add_action( 'wp_ajax_ajaxlogout', 'ajax_logout' );  
  }
  
  function ajax_logout(){
  
      // First check the nonce, if it fails the function will break
      check_ajax_referer( 'ajax-logout-nonce', 'security' );
      //check_ajax_referer( 'ajax-logout-nonce', 'ajaxsecurity' );
      wp_clear_auth_cookie();
      wp_logout();
      ob_clean(); // probably overkill for this, but good habit
      wp_die();
  }
  
  add_action('init', 'ajax_login_init');
  add_action('init', 'ajax_logout_init');
  </code></pre>
  
  <p>ajax.login.script.js</p>
  
  <pre><code>jQuery(document).ready(function($) {
  
      // Show the login dialog box on click
      $('body').on('click', '.modal-login a', function(e) {
          $('body').prepend('&lt;div class="login_overlay"&gt;&lt;/div&gt;');
          $('form#login').fadeIn(500);
          $('div.login_overlay, form#login a.close').on('click', function(){
              $('div.login_overlay').remove();
              $('form#login').hide();
          });
          e.preventDefault();
      });
  
      // Perform AJAX login on form submit
      $('form#login').on('submit', function(e){
          //console.log(ajax_login_object);
          $('form#login p.status').show().text(ajax_login_object.loadingmessage);
          $.ajax({
              type: 'POST',
              dataType: 'json',
              url: ajax_login_object.ajaxurl,
              data: { 
                  'action': 'ajaxlogin', //calls wp_ajax_nopriv_ajaxlogin
                  'username': $('form#login #username').val(), 
                  'password': $('form#login #password').val(), 
                  'security': $('form#login #security').val() },
              success: function(data){
                  $('form#login p.status').text(data.message);
                  if (data.loggedin == true){
                      //document.location.href = ajax_login_object.redirecturl;
                      $('div.login_overlay').remove();
                      $('form#login').hide();
                      $( ".logo a" ).trigger( "click" );
                  }
              },
              error: function(xhr, status, error) {
                  var err = eval("(" + xhr.responseText + ")");
                  alert(err.Message);
              }
          });
          e.preventDefault();
      });
  
  });
  </code></pre>
  
  <p>ajax.logout.script.js</p>
  
  <pre><code>jQuery(document).ready(function($) {
  
      // Perform AJAX logout on Click
      $('body').on('click','.modal-logout a', function(e) {
          //console.log(ajax_logout_object);
          $.ajax({
              type: 'POST',
              url: ajax_logout_object.ajax_url,
              data: {
                  'action': 'ajaxlogout',
                  'ajaxsecurity': ajax_logout_object.logout_nonce,
              },
              success: function(data){
                  console.log(data);
                  $( ".logo a" ).trigger( "click" );
              },
              error: function(xhr, status, error) {
                  var err = eval("(" + xhr.responseText + ")");
                  alert(err.Message);
              }
          });
          e.preventDefault();
      });
  
  });
  </code></pre>
  
  <p>The login/logout process works really fine if i do not use the function</p>
  
  <pre><code>check_ajax_referer( 'ajax-login-nonce', 'security' );
  </code></pre>
  
  <p>If i enable this code, check_ajax_referer always returns -1, but the ajax query will success. On research it seems that the nonce cannot be verified.</p>
  
  <p>So if i got a refresh of the page i can login without problems, but cannot logout straight afterwards. I need to refresh the page again (which i don't want cause of continious background music). Logout and direct login again has the same problem.</p>
  
  <p>So here are my questions:</p>
  
  <ol>
  <li>Do i need check_ajax_referer?</li>
  <li>Why can i login with activated check_ajax_referer, but not logout direct after login (without nee to refresh page)</li>
  <li>Same as 2. but other direction</li>
  </ol>
  
  <p>Thanks in advance
  Regards, Bandicut</p>