• Resolved Amit Biswas

    (@amitbiswas06)


    Hi all,

    I am trying to achieve the following –

    1. I have a custom form “X” which requires login to submit.
    2. I also have a ajax login form.

    Workflow –
    1. When a not logged in user comes to the custom form “X”, he/she fill up the form and when trying to submit, ajax login popup opens and user login via that ajax login form. After that, they can submit the form “X”.

    Issue –
    I am using nonce for form “X” which generates a nonce value for not logged in users. But after the ajax login is done, the nonce value requires to be updated. I am generating a new nonce after login is done. But that nonce is also not working and form “X” cannot be nonce verified.

    Code of 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>
    

    Code of ajax login submission handle via admin-ajax.php

    
    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.', 'text-domain'),
                        'new_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') which I intend to inject in the form “X” after login is done.

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

    Thanks!

Viewing 7 replies - 1 through 7 (of 7 total)
  • You should change the workflow. Don’t show the form unless the user is logged in.

    Thread Starter Amit Biswas

    (@amitbiswas06)

    @joyously Thanks for the reply. However that’s not a coding solution. I don’t think WordPress cannot offer solutions for this type of situation. I am expecting a coding solution for this as there is no issues with my workflow. I must allow users to fill up the form whether they are logged in or not.

    Think about what the nonce is for. You want to make sure the action is not hijacked, and that the user intends the action on the object.
    So when generating the nonce, you use something to tie the user to the action.
    Well, when you are filling out a form when not logged in, you can’t tie a user to the object, because there is no user. Does that mean there should be no nonce or no form?
    There is no point in putting a nonce in a form that won’t be used. The PHP has to be able to compute the same nonce, in order to verify it. So trying to send a new nonce in AJAX is pointless. How would the AJAX function know whether it was the real user or a hijack?
    You need to change the flow.

    Thread Starter Amit Biswas

    (@amitbiswas06)

    @joyously no point talking the other way. For instance, yes the form nonce will be used as there is both option to submit. Not logged in user and logged in user both can submit the form. Not logged in user will have to fill up email id for that. My issue is when a registered user decides to submit the form with logged in, I must enable them to submit without refreshing the entire page which will cost them to re enter every data in the form. Hope this make sense?

    If the non-logged in user can submit, then don’t put the link for the AJAX login.
    It sounds like you need two different action hooks, one for logged in and one for not logged in, which you accomplish with the _priv addition to the hook name.

    Thread Starter Amit Biswas

    (@amitbiswas06)

    @joyously it seems you are missing the point that I am talking about. I am already using both hooks for form “X”. I just wanted to create and return the logged in nonce after ajax login. Which in this case is returning but that is different. If you see my code below this line $user = wp_signon( $creds, false );, you shall get it.

    Thread Starter Amit Biswas

    (@amitbiswas06)

    I just found the solution here – at stackoverflow

    The main issue was – after the ajax login success, the nonce were being created with old session cookie while the session updates on the next request. So I have to use the set_logged_in_cookie action hook to update the session cookie immediately after the ajax login is done. Here is the code –

    
    add_action( 'set_logged_in_cookie', 'my_update_cookie' );
    function my_update_cookie( $logged_in_cookie ){
        $_COOKIE[LOGGED_IN_COOKIE] = $logged_in_cookie;
    }
    

    Similar issue was also discussed few years ago in this forum – Ajax login nonce creation

    Thanks!

Viewing 7 replies - 1 through 7 (of 7 total)
  • The topic ‘Ajax login and nonce verification’ is closed to new replies.