I am using ajax to submit log in and log out credentials. The log in and log out forms are replaced with html returned by a successful response. No page loading is happening page content is loaded via an ajax get request upon successful log in or log out.
I can successfully log in and then log out, but when I attempt to log in a second time I am receiving a nonce failure (-1) from check_admin_referer(). I have verified the nonce being sent during the second log in is different then the first submission, but that as far as I understand with nonce. This nonce is sent back to the ajax request during the log out process.
Have I over looked the need for something to be refreshed or stored somewhere in a session or global variable? My code works during the first attempt for logging in and logging out sharing my code is not likely beneficial here.
Does anyone have any idea why the nonce I receive is invalid?
EDITS BELOW
Please see my code, it’s a mix of php and javascript
<?php
/* the php sidebar menu for a logged in user
* this is also fetched by the ajax log in action
*/
function not_logged_in_menu() { ?>
<div class="login-form">
<h2>Login</h2>
<form method="post" action="<?php site_url(); ?>/wp-login.php" class="wp-user-form">
<div class="input-login">
<div class="loader"></div>
<input type="submit" class="login ui-btn" name="Login" value="Login" />
<span class="gzp-icon-login"></span>
</div>
<div class="input-prepend">
<span class="add-on icon-username"></span>
<input type="text" name="log" value="" class="input-medium" id="user_login" placeholder="Username" />
</div>
<?php /*<br class="clearer" />*/ ?>
<div class="input-prepend">
<span class="add-on icon-password"></span>
<input type="password" name="pwd" value="" id="user_pass" class="input-medium" placeholder="Password" />
</div>
<?php wp_nonce_field( 'ajax-login-nonce', 'security' ); ?>
</form>
</div> <?php
}
/* the php sidebar menu for a logged out user
* this is also fetched by the ajax log out action
*/
function logged_in_menu() {
global $user_identity; ?>
<div class="login-form">
<h2 class="welcome">Welcome<br /><?php echo $user_identity; ?></h2>
<a href="https://wordpress.stackexchange.com/questions/170410/<?php echo wp_logout_url( home_url() ); ?>" id="logout" class="btn btn-inverse" title="Logout">Logout</a>
<div class="loader"></div>
<div class="clearer"></div>
</div> <?php
}
/* the php login ajax action */
function ajax_login(){
check_ajax_referer( 'ajax-login-nonce', 'security' ); // on the second log in attempt with no page refresh this
// function fails her
// 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 = wp_signon( $info, false );
if ( is_wp_error($user) ){
echo json_encode(array('loggedin'=>false, 'message'=>__('Wrong username or password.')));
die();
}
//setting the user variables so the globals have content without an actual page load
wp_set_current_user( $user->ID, $user->user_login );
wp_set_auth_cookie( $user->ID, true, false );
do_action( 'wp_login', $user->user_login );
ob_start();
gzp_logged_in_menu();
$menu_content = ob_get_contents();
ob_end_clean();
echo json_encode(array('loggedin'=>true, 'message'=>__('Login successful, redirecting...'), 'menu_content'=>$menu_content,'user_signon'=>$user));
die();
}
add_action( 'wp_ajax_nopriv_ajaxlogin', 'ajax_login' );
/* the php log out ajax action */
function ajax_logout(){
// First check the nonce, if it fails the function will break
wp_verify_nonce( $_POST['security'], 'log-out' );
wp_logout();
ob_start();
gzp_not_logged_in_menu();
$menu_content = ob_get_contents();
ob_end_clean();
echo json_encode(array('loggedout'=>true, 'message'=>__('Logout successful, redirecting...'), 'menu_content'=>$menu_content));
die();
}
add_action( 'wp_ajax_ajaxlogout', 'ajax_logout' );
?>
<script type="text/javascript">
/* javascripted loaded in the head of page on page load */
jQuery(document).ready(function(event) {
admin_bar_login();
admin_bar_logout();
});
/* the ajax post for a log in attempt */
function admin_bar_login() {
/* login action */
jQuery('form.wp-user-form').on('submit', function(e) {
e.preventDefault();
jQuery('.login-form input.login').parent('.input-login').addClass('loading').show();
console.log(jQuery('form.wp-user-form #security').val());
jQuery.ajax({
type: 'POST',
dataType: 'json',
url: ajaxurl,
data: {
'action': 'ajaxlogin', //calls wp_ajax_nopriv_ajaxlogin
'username': jQuery('form.wp-user-form #user_login').val(),
'password': jQuery('form.wp-user-form #user_pass').val(),
'security': jQuery('form.wp-user-form #security').val()
},
success: function(data){
if (data.loggedin == true){
jQuery('.navigation-right .menu').html(data.menu_content);
AAPL_loadPage(document.location.toString(),1); //refresh the #content of the page
admin_bar_logout(); //this adds the event handler to the log out content just added
jQuery.bootstrapGrowl(data.message);
}
else if(data.loggedin == false) {
jQuery('.login-form input.login').parent('.input-login').removeClass('loading');
jQuery.bootstrapGrowl(data.message);
}
},
fail: function(data){
if(data.loggedin == 'false')
jQuery.bootstrapGrowl(data.message);
}
});
});
}
/* the ajax post for a log out attempt */
function admin_bar_logout() {
//logout action
jQuery('#logout').on('click', function(e) {
e.preventDefault();
jQuery(this).parent('.login-form').addClass('loading').show();
var href = jQuery(this).attr('href'),
vars = href.split("&"),
wp_nonce="_wpnonce",
security = '';
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == wp_nonce){security = pair[1];}
}
jQuery.ajax({
type: 'POST',
dataType: 'json',
url: ajaxurl,
data: {
'action': 'ajaxlogout', //calls wp_ajax_ajaxlogout
'security': security,
},
success: function(data){
if (data.loggedout == true){
jQuery('.navigation-right .menu').html(data.menu_content);
AAPL_loadPage(document.location.toString(),1); //refresh the #content of the page
admin_bar_login(); //this adds the event handler to the log in content just added
jQuery.bootstrapGrowl(data.message);
}
else if(data.loggedin == false) {
jQuery('.login-form input.login').parent('.input-login').removeClass('loading');
jQuery.bootstrapGrowl(data.message);
}
},
fail: function(data){
if(data.loggedin == 'false')
jQuery.bootstrapGrowl(data.message);
}
});
});
}
</script>
Solution Below
The correct answer for my issue was marked below, but I also had another issue with my user not actually being logged out. The nonce being returned was a logged in nonce. When I tried to log back in as an anonymous user the nonce was invalid to wp_verify_nonce()
.
I have found that simply using wp_logout()
to log out wasnt enough in my case. The $current_user
variable still retained all of the user data and is_user_logged_in()
returned true. It wasnt until I set wp_set_current_user(0)
did I see the user was actually logged out.
I have also removed the need for a nonce during log in.
See this post for discussion on that topic
wp_logout Not Logging Me Out
Best Answers
I hadn’t run your code, but my educated guess is that the fault in your code flow is that nonces are user specific. While anonymous nonce is possible, it is useless for its purpose because it would be same for all anonymous users.
So there is likely mismatch somewhere and you are trying to use nonce of specific user, while being anonymous.