function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Daniel BallingerDaniel Ballinger 

Cross-Site Request Forgery (CSRF/XSRF) safe Custom Button action

I've inherited an application that uses custom Visualforce pages to perform actions when a user presses a custom button.

 

E.g. There is a custom button on Opportunity that links to the Visualforce page and passes a query string parameter. When the users GET request arrives at the visual force page an action is fired in the custom controller to a method. The method calls out to some web services and ultimately updates the database.

 

This opens the user up to CSRF issues with the GET request ultimately updating the database.

 

CSRF and apex:page and Apex and Visualforce Applications suggest changing the visualforce page and custom controller to using a apex:form and button to trigger the database updating action though a POST. This allows the inbuilt com.salesforce.visualforce.ViewStateCSRF to ensure the user triggered the action and help avoid CSRF issues.

 

However, this requires the user to perform an extra button press.

 

Is there an alternative approach I can use to safely perform the action from the button on Opportunity without opening up CSRF issues?

 

The same question has been posted on StackOverflow: CSRF safe Custom button linked to Apex method

Best Answer chosen by Admin (Salesforce Developers) 
bob_buzzardbob_buzzard

None that I'm aware of.  The fundamental problem is the side effect of accessing the page - updating the database based on information from the URL.  If you don't insert a step where the user has to validate the action, all you are doing is changing the mechanism rather than the effect itself. 

 

I've seen solutions in the past that create a form in a page, populate with the details from the URL and then use javascript to submit the form, which then includes the ViewStateCSRF in the request.  However, the net effect is the same - the information from the URL updates the database without involvement from the user.

All Answers

bob_buzzardbob_buzzard

None that I'm aware of.  The fundamental problem is the side effect of accessing the page - updating the database based on information from the URL.  If you don't insert a step where the user has to validate the action, all you are doing is changing the mechanism rather than the effect itself. 

 

I've seen solutions in the past that create a form in a page, populate with the details from the URL and then use javascript to submit the form, which then includes the ViewStateCSRF in the request.  However, the net effect is the same - the information from the URL updates the database without involvement from the user.

This was selected as the best answer
Amit Singh1989Amit Singh1989

Hi DanielBallinger ,

 

i faced this situation earlier ,

 

and you can avoid extra clicks, you need to follow this code.

 

i was trying to override the standar delete with my visualforce page (to fix navigation issue),

here is the code

<apex:page standardController="Your_Object__c" extensions="Your Extension Class" showHeader="false" sidebar="false">
 
        <script>
           window.onload=function()
           {
             doInit();
           };
        </script> 
  
        <apex:form >
           <apex:actionFunction name="doInit" action="{!checkDelete}"/> 
        </apex:form> 
  
</apex:page>

 

Thanks

Daniel BallingerDaniel Ballinger

Hi Amit,

 

Thats an interesting idea using a custom controller extension over the standard controller for the sObject. Using Javascript to automatically submit the form will pick up the ViewStateCSRF in the subsequent POST request.

 

As Bob Buzzard points out above, I'm not sure this has addressed the CSRF issue. The user has arrived at the first page using a GET request and the database has been updated without their involvement.

 

I'm thinking the most probable way this could be made to work would be by generating and passing something like the ViewStateCSRF as a query string parameter. This would require Salesforce to expose some new methods to both generate and verify the value. Then if a third party tried to send you to the URL they wouldn't be able to generate the ViewStateCSRF query string parameter without knowing your session details and how Salesforce generates the ViewStateCSRF. It’s more likely that this won't be supported as a POST is the supported way to work around this.

Daniel BallingerDaniel Ballinger

I've added the Idea Invoking Apex code from the standard Entity Details pages with CSRF protection to see if they can add support for CSRF safe custom buttons.

Daniel BallingerDaniel Ballinger

Another approach that doesn't use custom buttons is to inline a Visualforce page containing just the required button within the standard page layout.

 

The Visualforce page must use the standard object controller (Opportunity in my case) to appear in the list of available Visualforce pages on the page layout. The Visualforce page itself can be very minimal with just a commandButton inside a form.

 

This should protect against CSRF as the commandButton will pick up the "com.salesforce.visualforce.ViewStateCSRF" hidden input with the post back to the server.

Sure@DreamSure@Dream
Hi all..

In one visualforce page..i am having a menu links. On click of each link..i will rerender corresponding iframe.
One link is working fine..but when I click another link, its giving me an error, saying--"The link you followed is not valid. This page requires a CSRF confirmation token.Report this error to your salesforce Administrator".

I am not performing any DML operations in that page.  So I have made the "Require CSRF Protection on Get Requests to false". Now its working fine.
Will it be a mistake to do like this??

Bob can you help me in understanding..how CSRF works...when used in iframes..
vijaymindvijaymind
Hi All,

I am just trying to display read only data on targetted VF page based on query string parameter, there no DML still getting CSRF protection error.
Apart from this newly added flag on VF page configuration Require CSRF protection on GET requests, what does it mean ? Do we need to make this checkbox true even if we use a intermediate page and custom button inside form to execute the action ?

Also I check Require CSRF protection on GET requests is only works for delete operation as per the other blog.  http://salesforce.stackexchange.com/questions/7574/cross-site-request-forgery-csrf

below is the apex code.
PageReference p = new PageReference('/apex/CreateCaseComment?id='+caseID+'&ga='+globalAcctName);

controller.
caseID = ApexPages.currentPage().getParameters().get('Id');
caseList = [select id, CaseNumber, Subject, Priority,
                    CreatedDate, Status, Owner.Name, Contact.Name
                    FROM Case
                    WHERE ParentId =: caseID limit 10];

What can be way around to escape this error ? Do I need to these line of code from java script as bob suggested. 

vijaymindvijaymind
Hi All,
What is case if I redirect to new VF page using java script rather than pagereference method in apex controller.
<script>
           window.onload=function()
           {
             window.open('/apex/pageName?Id='+'{!HTMLENCODE(recordId)}');
           };
</script>

Will this protect CSRF ?

Thanks
Vijay