Question on crsfProtection, I am sharing my Code t...
# cfml-general
g
Question on crsfProtection, I am sharing my Code to automatically add the token to the request, but my code has some issues, unable to bypass ajax Pages, I would like someone to respond and update the code so it can be widely used if needed i can create a repo on github or share a code here is my code https://pastebin.com/NQ6Wt8HS
a
So you don't want to check the token for AJAX requests?
g
i want to but as of now, i added a piece of code which was giving me 403, the js code is this
Copy code
document.addEventListener('DOMContentLoaded', function() {
    var statsData = {
        browser: navigator.userAgent,
        operatingSystem: navigator.platform,
        device: /Mobile|iP(hone|od|ad)|Android|BlackBerry|IEMobile/.test(navigator.userAgent) ? 'Mobile' : 'Desktop',
        screenResolution: screen.width + 'x' + screen.height,
        screenSize: window.innerWidth + 'x' + window.innerHeight,
        pageUrl: window.location.pathname
    };

    // Send data to server
    fetch('trackStats.cfm', {
        method: 'POST',
        credentials: 'include',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify(statsData)
    });
});
and everytime this page was called, it was going into 403 security issue, so i have to comment the code to make it work, there are ajax forms too which i want to make it work but something was not right so not sure what i should do
a
Yeah - so that code you have there is not passing the token so would fail (I note that you are looking for the
X-CSRF-Token
header though, so you could just set that in your AJAX call.
You can usually detect an AJAX request with something like this:
Copy code
boolean function isAjax(){
  var headers = GetHttpRequestData().headers;
  if ( structKeyExists( headers, "X-Requested-With" ) ) {
    return headers[ "X-Requested-With" ] ==  "XMLHttpRequest";
  }
  return false;
}
g
the function you gave me if cf based and how it will do in javascript or how can i write a common ajax function which will include headers like this based upon what you mentioned i wrote this
Copy code
function safeAjax(options) {
    // Default options
    const defaults = {
      url: '',
      method: 'GET',
      data: null,
      headers: {},
      csrfToken: null,
      useFormData: false
    };

// Merge provided options with defaults
const settings = { ...defaults, ...options };

// Add CSRF token to headers if provided
if (settings.csrfToken) {
    settings.headers['X-CSRF-TOKEN'] = settings.csrfToken;
}

// Prepare the request data
let requestData = settings.data;
if (settings.useFormData && !(settings.data instanceof FormData)) {
    requestData = new FormData();
    for (const key in settings.data) {
    requestData.append(key, settings.data[key]);
    }
}

// Function to handle the response
const handleResponse = (response) => {
    if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();
};

// Perform the request using fetch
if (window.fetch) {
    return fetch(settings.url, {
    method: settings.method,
    headers: settings.headers,
    body: requestData
    }).then(handleResponse);
} 
// Fallback to XMLHttpRequest if fetch is not available
else {
    return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();
    xhr.open(settings.method, settings.url, true);
    
    // Set headers
    for (const header in settings.headers) {
        xhr.setRequestHeader(header, settings.headers[header]);
    }

    xhr.onload = function() {
        if (this.status >= 200 && this.status < 300) {
        resolve(JSON.parse(xhr.response));
        } else {
        reject(new Error(`HTTP error! status: ${xhr.status}`));
        }
    };

    xhr.onerror = function() {
        reject(new Error('Network error'));
    };

    xhr.send(requestData);
    });
}
}
but this piece of code is still a problem, its unable to inject the token in the forms <cffunction name="onRequestEnd" returntype="void"> <cfargument name="targetPage" type="string" required="true"> <cfset var response = getPageContext().getResponse()> <cfset var contentType = response.getContentType()> <cfdump var="#response#"> <<cfif isNull(contentType) or contentType contains "text/html"> <cfoutput>#injectCsrfToken(contentType)#</cfoutput> </cfif> </cffunction>
a
There are so many random bits of code you are posting I'm sorry but I'm not going read through a wall of code
You should be able to debug this
g
in my first post, i posted the entire code
a
Open up the browser console. Look at the HTTP request being fired from your JS. Does it have a
X-CSRF-TOKEN
header? If NO then your JS needs work, if yes your CF needs work.
g
i shared everything i have, this is not random code
a
Hey look - I'm helping you for free in my own time. I will give you pointers but I'm not going to write code for you I'm afraid. So far you've basically said "it doesn't work". What specifically doesn't work? Is it the CF or the Javascript? Etc etc
Did you write that code or copy and paste it from various sources? If you wrote it then you should be able to debug it.
g
i wrote it
👍 1
i will debug it, Thanks for the help
a
You said at the start "unable to bypass ajax Pages" I showed you how to detect and ignore checking for CSRF tokens when it's an AJAX request hitting the server.
g
sure, thanks in my main question, i also wrote it might need some extra help because there was another issues which i will share
but no worries i will fix it
a
OK, so your browser console is going to be your best friend here as you'll see if the header is being sent
g
sure
a
The csrf token is generate by CF - so is server side. You need to expose it somehow so the JS can read and send it.
BTW: if
window.fetch
isn't supported then the browser won't like
const
either.
I'd go back to basics and just get it working with
windows.fetch
(modern) and then add support for older browsers if you need to
g
k