CodeIgniter Forums
CSRF Protection with multiple js scripts - Printable Version

+- CodeIgniter Forums (https://forum.codeigniter.com)
+-- Forum: Using CodeIgniter (https://forum.codeigniter.com/forumdisplay.php?fid=5)
+--- Forum: General Help (https://forum.codeigniter.com/forumdisplay.php?fid=24)
+--- Thread: CSRF Protection with multiple js scripts (/showthread.php?tid=82382)



CSRF Protection with multiple js scripts - AgBRAT - 07-05-2022

I have a view profile page that uses two Ajax requests and thus two script files: profile_subscribe and profile_views. Either script works when it's the only script included with the view. It's when I include both scripts that only profile_views executes. 
Currently, profile_subscribe has a 403 forbidden error citing CSRF  protection as the issue. I regenerate the CSRF token with both Ajax requests so I'm not sure what is going wrong. I will include both scripts. If anything else is needed to troubleshoot, let me know.
profile_views.js
PHP Code:
<script>
    $(document).ready(function() { 
        var csrfName "<?= csrf_token(); ?>"
        var csrfHash "<?= csrf_hash(); ?>"
        
        
// If user views profile 
        $.ajax({
            type"POST",
            url"<?= base_url(); ?>/users/members/view_profile/<?= $profile->username;?>",
            dataType"JSON",
            data: {
                [csrfName]: csrfHash,
                "action"'view',
            },
            headers: {
                'X-Requested-With''XMLHttpRequest',
            },
            success: function(data) {
                var res data;

                // Update CSRF hash
                csrfName res.csrfName;
                csrfHash res.csrfHash;

                // display number of views
                $('#profileCount').html(res.viewCount);
            }
        });
    });
</
script

profile_subscribe.js:
PHP Code:
<script>
    $(document).ready(function() {  
        
var csrfName "<?= csrf_token(); ?>";
        var csrfHash "<?= csrf_hash(); ?>"

    // If user clicks the subscribe button
        $(".subscribe-button").on("click", function (event) {
            $clicked_btn = $(this);
            let $icon $clicked_btn.find('i').first();
            var userProfile = $(this).data("user");

            if ($icon.hasClass("fa-solid fa-rss")) {
                action "subscribe";
            } else if ($icon.hasClass("fa-solid fa-user-check")) {
                action "unsubscribe";
            }

            $.ajax ({
                url"<?= base_url(); ?>/users/members/view_profile/<?= $profile->username;?>",
                type"post",
                dataType"json",
                data: {
                    [csrfName]: csrfHash,
                    "action"action,
                    "user_profile"userProfile,
                },
                headers: {
                    'X-Requested-With''XMLHttpRequest',
                },
                success: function(data) {
                    var res data;
                    csrfName res.csrfName;
                    csrfHash res.csrfHash;

                    if (action == "subscribe") {
                        $icon.removeClass("fa-solid fa-rss");
                        $('.subscribe-button').html('<i class="fa-solid fa-user-check"></i> Subscribed');
                    } else if (action == "unsubscribe") {
                        $icon.removeClass("fa-solid fa-user-check");
                        $('.subscribe-button').html('<i class="fa-solid fa-rss"></i> Subscribe');
                    }
                }
            });
        });
    });
</
script



RE: CSRF Protection with multiple js scripts - includebeer - 07-06-2022

I think the problem is each script has it's own local variables csrfName and csrfHash. When you update the variables after the ajax request has returned, you only update the local variables. It doesn't update the ones in the other script. 
Code:
// Update CSRF hash
csrfName = res.csrfName;
csrfHash = res.csrfHash;

You should probably make these variables global so both scripts can use the same variables.