Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Wordpress: Simple Ajax Login Form
<?php
//Simple Ajax Login Form
//Source: http://natko.com/wordpress-ajax-login-without-a-plugin-the-right-way/
?>
//html
<form id="login" action="login" method="post">
<h1>Site Login</h1>
<p class="status"></p>
<label for="username">Username</label>
<input id="username" type="text" name="username">
<label for="password">Password</label>
<input id="password" type="password" name="password">
<a class="lost" href="<?php echo wp_lostpassword_url(); ?>">Lost your password?</a>
<input class="submit_button" type="submit" value="Login" name="submit">
<a class="close" href="">(close)</a>
<?php wp_nonce_field( 'ajax-login-nonce', 'security' ); ?>
</form>
<?php
//add this within functions.php
function ajax_login_init(){
wp_register_script('ajax-login-script', get_template_directory_uri() . '/ajax-login-script.js', array('jquery') );
wp_enqueue_script('ajax-login-script');
wp_localize_script( 'ajax-login-script', 'ajax_login_object', array(
'ajaxurl' => admin_url( 'admin-ajax.php' ),
'redirecturl' => home_url(),
'loadingmessage' => __('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' );
}
// Execute the action only if the user isn't logged in
if (!is_user_logged_in()) {
add_action('init', 'ajax_login_init');
}
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) ){
wp_set_current_user($user_signon->ID);
wp_set_auth_cookie($user_signon->ID);
echo json_encode(array('loggedin'=>true, 'message'=>__('Login successful, redirecting...')));
}
die();
}
//Create a file ajax-login-script.js within theme's directory and paste this js
jQuery(document).ready(function($) {
// Show the login dialog box on click
$('a#show_login').on('click', function(e){
$('body').prepend('<div class="login_overlay"></div>');
$('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){
$('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;
}
}
});
e.preventDefault();
});
});
?>
@EazyServer
Copy link

EazyServer commented Jul 13, 2016

see on line 26: admin_url( 'admin-ajax.php' ) sometimes give different version of the site url which then browsers trigger XSS flag and may even stop the request like in Chrome!
I think it would be best if changed to home_url() . '/wp-admin/admin-ajax.php'

@Faisalawanisee
Copy link

Faisalawanisee commented Sep 13, 2016

Thanks for such a nice thing.

@JeancarloPerez
Copy link

JeancarloPerez commented Oct 22, 2016

Is there a way to login with user email?

@Sanghamitranew
Copy link

Sanghamitranew commented Nov 23, 2017

great.Is working perfect

@Guley
Copy link

Guley commented Oct 23, 2018

Hi,
Great work but need some updates.

Please replace these line after login success

if ( !is_wp_error($user_signon) ){
wp_set_current_user($userinfo->ID);
wp_set_auth_cookie($userinfo->ID);
echo json_encode(array('loggedin'=>true, 'message'=>__('Login successful, redirecting...')));
}

Thanks

@avitorio
Copy link

avitorio commented Dec 24, 2018

A quick note on @Guley's answer:

$userinfo->ID should be $user_signon->ID

@rcarhuaricra
Copy link

rcarhuaricra commented Oct 3, 2019

tengo un problema cuando es admin no redirecciona

Copy link

ghost commented Oct 17, 2019

How can i redirect on particular page as per role. This code it work very nicely but i have to change redirect as per role. So is it possible?
i have two role like 'user'and 'salesperson'. If login as user then redirect on 'my account page' and login as salesperson then redirect on 'listing page'. please help any one if know about it.

@smartrashed
Copy link

smartrashed commented Nov 7, 2019

really awesome

@JohnDeeBDD
Copy link

JohnDeeBDD commented Apr 21, 2020

So my understanding of nonces, is that they provide CORS protection for actions, vis-a-vi a user and action pair. So do you need a nonce to login? You should use a nonce for that user AFTER they are logged in, but this for seems to be using one for the login activity itself. Is that required? In other words, what is the security, the user isn't logged in yet?

@tetagord
Copy link

tetagord commented May 30, 2020

Thank you!

@amitbiswas06
Copy link

amitbiswas06 commented Aug 10, 2020

My problem is - I have a form "X" which requires login to submit. I am doing the ajax login before submitting the form "X". But after ajax login, the nonce of the form "X" remains same. How can I update the nonce of form "X" once the user is logged in via ajax login? I am doing like the following code -

My form "X"

<form name="x" action="<?php echo esc_url( admin_url('admin-post.php') ); ?>" method="post">
      <label for="checkbox_one"><?php echo esc_html__("Checkbox Name", "text-domain"); ?></label>
      <input type="checkbox" name="checkbox_one" id="checkbox_one" >
      <input type="hidden" name="action" value="my_action">
      <?php wp_nonce_field( "action_name", "nonce_name" ); ?>
      <input type="submit" value="Submit">
</form>
<a href="#"><?php echo esc_html__("Click me to login first. An ajax login modal will open.", "text-domain"); ?></a>

Now, before user can submit the form "X" above, user have to be logged in. So user logged in via ajax login form as prescribed above.
But the nonce is getting updated also. I am verifying and returning ajax login success data as below -

function login(){
        
        //bail early if found suspecious with nonce verification.
	if ( !isset( $this->values['_login_nonce'] ) || ! wp_verify_nonce( $this->values['_login_nonce'], 'ajax_login' ) ) {
        
            wp_send_json_error([
                'login'     => false,
                'message'   => esc_html__('Security check unsuccessful.','text-domain')
            ]);
        
        }

        if( isset($this->values['_username']) && isset($this->values['_password']) ){

            $creds = array(
                'user_login'    => sanitize_user($this->values['_username']),
                'user_password' => $this->values['_password'],
                'remember'      => true
            );
         
            $user = wp_signon( $creds, false );
         
            if ( is_wp_error( $user ) ) {
                wp_send_json_error([
                    'login'     => false,
                    'message'   => esc_html($user->get_error_message())
                ]);
            }else{
                wp_set_current_user($user->ID);
                wp_set_auth_cookie($user->ID);
                wp_send_json_success([
                    'login'     => true,
                    'message'   => esc_html__('Login Successful.', 'cqfs'),
                    'status'    => esc_html__('You are logged in.', 'cqfs'),
                    'nonce'     => wp_create_nonce('action_name'),
                ]);
            }
            
        }

        exit();
}

You can see that after successful login via ajax form, I am again creating the nonce with same nonce action of form "X" which is wp_create_nonce('action_name').

But unfortunately, this nonce is not working when I am trying to authenticate form "X" submission after the ajax login. I check the browser and found the nonce is different. I will appreciate any help form the community here.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment