CRT-450 Salesforce Certified Platform Developer – Process Automation and Logic – 38% Part 5
- 3.15- Programmatic techniques to prevent security vulnerabilities
This lecture is about programmatic techniques to prevent security vulnerabilities. The topics of this lecture are cross site scripting attacks, circuit injections cross site requests forgery Attacks data access control using the wish sharing keyword, this lecture discusses several security risks in Apex and Visual Force, and what are the different ways to mitigate them. Apex and VisualForce pages can expose an. org to different types of security risks like cross site scripting attacks, cross site request forgery, and so called injections. In order to prevent such attacks, it’s very important to understand the different ways to prevent these risks and the considerations related to the use of some attributes like, let’s say, static queries, bind variables, and existing protections offered by Salesforce like antic SRF tokens. To better understand security risks in Apex, please sign up for this Salesforce developer. org that shows these security risks as examples.
This developer. org has various examples of these risks. So once you sign up for this, by following this link, you can see different examples in this and then you can test them yourself. On top of that, I highly advise you to do this. Trailhead Module let’s now start with the cross site scripting or XSS security Risk as you are aware, in the past web pages were very simple and static, and they relied on HTML with just the content displayed and nothing dynamic. On the other hand, current web pages are in fact nonstatic web applications. They are dynamic and update based on the action taken by the end user. So, for example, a simple mouse click can create a popup window or it can play music and so on. crosssite scripting or XSS attack occurs when a user input, like for example, entering a specific text and a form on a web page is reflected in the HTML of the web page for that. This kind of attacks can take this user input and execute it as code due to the poor separation between code context and user data. As mentioned, cross site scripting results when user input is executed as code.
This is an example that will make it much more easier for you to understand it. Let’s say that we have a website that has an input field, and this input field is taken and shown in another part of the web page. So any value that we enter in this input field will be taken and it will be shown as an output field. So let’s simply enter this text and as you can see, it is displaying in this other output field without any problem. So you can see on the right side we have this input field and then we did enter this text. We clicked on Createscroll, and then we have this value of this input field displaying in this output field. Now, let’s get a little bit more sneaky. What happens if we enter some HTML code into this text box and execute? What will happen? Now let’s enter this. Instead of a simple text. Let’s enter a text. But this text should be between two HTML tags. So we will choose the U tag, we will open it and then we will close it. What happens when we click on the button?
Well, because the Entertain contained an HTML tag which is the underlying tag, and because the website was not designed to deal with this kind of risks of attacks, the underlying HTML tag is now part of the page source and the result at the bottom is an underlined text. Let’s now try this. We will use the image source tag and then inside this tag we will use the on error attribute. This will result in a pop up because the entertain and the input field led to that. Both of these two examples are very simple and harmless, but you can see that this can get ugly quickly with more sophisticated input and can interact with the host server. Now that we have seen the dangers that cross site scripting attacks can do, let’s see what you can do to protect against this kind of attack. As we mentioned previously, cross site scripting is caused by weak separation between code context, the actual underlying application, and user data, which is any information submitted by the user. There are two basic techniques that we can use to protect against cross site scripting. First we have the input filtering, and then we have the output encoding. The first mitigation technique for cross site scripting is the input filtering. Input filtering works on the idea that malicious attacks are best code on the point of user input. For example, if the user inputs a text between the B tag and the page strips or blocks the code, then no unauthorized code will run. There are two types of input filtering. First, we have the blacklisting, where specific bad characters or combination of characters are banned, meaning that they cannot be entered or stored. And the developer creates a list of known bad characters like HTML or script tags and throws an error if any bad character are in the input. And second, we have whitelisting, where only characters or words from a known list of entries are permitted preventing malicious input.
For example, if the user enters anything besides numbers and a phone number field, the application will throw an error. The second mitigation technique for cross site scripting attacks is the output encoding. While input filtering techniques work by preventing bad data from entering the system, output encoding techniques take the opposite way they prevent malicious payloads already in the system from executing. In fact, output encoding is often considered much more necessary than input encoding because it doesn’t rely on any upstream or downstream protections and it cannot be bypassed by alternative input pathways. How does it work? Well, this should be covered on the code side by using the appropriate encoding on the browser side. For example, in the case of the less than character, you can replace this character with the string and lt semicolum and your browser will understand that you want the text version of the less than character, not the HTML version. As a developer you can use the same concept to mitigate cross site scripting attacks because characters that can act as code are not represented and they’re meaningful version inside a block of code only the characters text equivalents appear.
Now let’s talk about so called injection. So cool. Injection involves taking users applied input and using those values in a dynamic soccer query. Let’s see this in an example. As you can see here we have a simple VisualForce page. You can see that this is a page that is using a custom controller. It has a page block with this title and then it has a four tag. As you can see inside this we have an output field and then we have an input field with value equals to name. And then we have a button that calls the action query. At the bottom part we have a page block table element. Inside this we have two column elements. The page block table element has the value equal to cons and then it has a variable equal to con which is being used in the column components. Now on the right side we have the equivalent controller. As you can see this is the name of the class which is the controller of the VF page. It has a string and the string is called name with a gutter and etc. And it also has a list of contact which is called cons. As you can see the action query which is a method. This is equivalent to this action on the left side. And what does it do? It just has a string called query string that has a so called query and then it’s calling the database query method to invoke this string which is the so called query.
And then this is now being fed to the cons variable which is listed on this page block table. One very important note here as you can see that this is the string and then inside this we are defining the so called query. And then we are using this database query method to dynamically run this query. The very close of this query has this it has Is deleted equal to force a name like name. So if we input anything on this side this will be used inside this query and this name is equivalent to the input field. So if you enter anything on the VF page this will be used in the query. And you can notice that we also have the is deleted equal to false. So this is a very important point to shed light on. As you can see I took the very close from the previous example and put it here on the top. Now let’s see two different examples. When the user enters bob and the input field this is the result of the where clause. It is a very simple query that appears normal. But now let’s say that we have another value entered by the user when the user enters this string into the input field.
So as you can see this is exactly what the user entered test and then this sign and then one code and then one parentheses or and all of that. So if we take this input and replace name in the so called query with this input you can see that this is the result of the so called query. This is the result of the string that is being used to build the Socall query. As you can see, if we run this you can see that the result of the so called query will be much more different than the result of entering any simple string. The resulting query will show all contacts. Why? Because as you can see the user entered this string and because he entered a closing parentheses, this parentheses is taken to close this first wave close part and then this user entered or name like anything, which means that now we are looking for any contact be deleted or no. So this is a clear example of a sockwell injection that can be used to modify the intended logic of a query.
Now, what can we use to prevent sockwell injection attacks? To prevent a Socalled injection attack, avoid using dynamic Socalled queries and instead use static queries and binding variables. Let me give an example. As you can see, the method on the top is the one that we had in the previous example. To fix it we can use instead a static query with a bind variable and not a dynamic query as you can see in the code at the bottom. So instead of using this dynamic so called query, so instead of using a string that will be used to construct the query and then the variable of the user will be there, we can instead build our variable that is exactly the user input and not the whole Socalled query. So this is basically a static query and this is a dynamic query. So if we use a dynamic query we are risking a so called injection. Finally, if you must use a dynamic Socalled query, use the escape single quotes method to sanitize user supplied input. This method adds the escape character to all single quotation marks and a string that is passed in from a user. The method ensures that all single quotation marks are treated as enclosing strings instead of database commands.
Now let’s talk about cross site request. Forgery or CSRF. Cross site request Forgery causes a user’s browser to perform an unwanted action on a trusted website for which the user is currently authenticated. Let me give you an example. Let’s say that an attacker has a web page called attacker. com. This could be any web page that you can visit. But this is just an example. Now let’s say that this website has an HTML tag that looks like this one image source and then we have a link. And then this link has different attributes. So as you can see, it looks like a simple link and then you can see that we have these different parameters or attributes that are added to this link. So the attackers page contains a URL that performs an action on another page. So if I visit the attacker. com page, this will be executed. Now let’s see how this attack works. If the user who is visiting attacker. com is currently logged in at the same time to webpagea. com, then the above code will run and the URL ad is retrieved and the action will be performed because the browser maintains the logged in user session and the user is still authenticated on webpagea. com. To make it more clear, let’s say that you have logged in to your Gmail account and then you have closed the browser. After five minutes you have reopened the browser and you went to your Gmail account. In this case you will not need to reload in again to your Gmail account because the browser maintained the session. This is the exact same thing here.
The catch is that the user is already logged in to web page A by his her normal username and password and the session is maintained. And let’s say that this user is an admin on web page A. Now, because attacker. com executes a code on web page A without the user knowing, and because the user has an open session with web page A, then this code will execute. So the code that we run in this case is this one. As you can see, we have webpagea. com and because the user has an active session with Webpagea. com, this whole thing will run which will create a new user with that email and with that type. So by running this code without knowing, the user has created a new user for the attacker. This is another example. Imagine that you are the user and you visited the website towncriier. com. So as you can see here, this is you. You went to this website, this website had this hidden code and then you already had a session with this website open.
Because you had this session open, all of this code could run. And as you can see here, we are invoking some API and then we are if you aren’t creating a user on this website. So you are creating a user without knowing, because the code of creating a user was hidden in this bad website and because you had a session open with this website. So without knowing, you created a user for the hacker. So in other words, the attacker got the user’s browser to perform an unwanted action on a trusted site for which the user is currently authenticated. To prevent these attacks, Salesforce has implemented an anti CSRF token. This is a setting in your Salesforce. org that is enabled by default. The protection can only be disabled by contacting Salesforce support and you can see the CSRF settings by going to setup security controls and session settings. How does this protection work? This is an example for the same request as before, but this time with the Cross site Request Forgery protection turned on.
With the protection turn on, every request to Salesforce requires another parameter, which is a token, which is a number of random unique characters. So when the attacker website tries to execute its Bad code, the Bad code does not have the token to be accepted by Salesforce server. For that it will be denied. This token will change on every request for further protection and upon the next page load, the application checks the validity of the token and only executes the command when the token matches the expected value. This feature protects you when using all of the standard controllers. Admitted, it all seems good with cross site Request Forgery, but even though Salesforce implements an anti CSRF token, there are ways to fall and the trap. This is a visual force example. As you can see, there is an action parameter that calls the Perform in it action method and the controller.
Let’s see this controller. This method parses the user ID parameters applied in the URL and uses it to update the user as nite in the system. So you can see on the top we have a VF page and this VF page has this action, which means that this action will load before loading the page. And what does this action do? It will do all of that. So the main problem here is that before the VisualForce page renders and the user browsers, the Perform Edit action method is called. And since this action executes before the rest of the page loads, it bypasses the default CSRF protection provided by the platform. To prevent this, block the application from performing operations on a page load by removing the action attribute and change any output link that gets its value from the action attribute operation on page load to a command button. So when the user clicks on the link, it executes the Apex code rather than refreshing the page. And the final piece of this lecture is the with sharing keyword.
As you are aware, each object in Salesforce has its own sharing permissions and each user has a predefined access to a certain records based on the sharing. When using standard controllers, the sharing settings are enforced, meaning that when a VisualForce page is using a standard controller, the user will only be able to access the records that they can access within Salesforce. This is called system mode. But when using a custom controller, the builtin user permissions object and fieldlevel security and sharing settings are not respected during execution. Which means that a user will be able to access all of the records even though his or her sharing settings don’t allow this. This is called system mode. This is the default behavior and custom controllers. An Apex class has the ability to read and update all data within the the with sharing keyword on class definition forces the use of the security sharing permissions of the user currently logged in. In the first example, all contact records are returned, even if the currently logged in user does not have access to all of these contact records. But when we add the with sharing keyword, only the contacts that the logged end user has access to will be returned. Note that this keyword only affects records access and does not affect field level security or object level security.
And that’s it for this lecture. In this lecture, we have talked about how to minimize security risks in Apex. In general, there are several risks that we should be aware of. Cross site scripting occurs when the user supplied input is reflected in the HTML of a web page. To prevent this, we can use input filtering and output encoding. Soccer injection involves taking usersupplied input and using those values in a dynamic sockle query. To prevent this, avoid using dynamic soccer queries and instead use static queries and binding variables. Cross site request forgery attacks cause a user’s browser to perform an unwanted action on a trusted site by which the user is currently authenticated.
To prevent this, make sure that the CSRF protection is turned on and avoid performing operations on page load and change any output link to a command button so when the user clicks the link, it executes Apex code rather than refreshing the page. And finally, we have talked about the with sharing keyword that is used to control data access as it directs the platform to use the security sharing permissions of the user correctly logged in. This keyword only features sharing rules and does not include feed level security or object level security, which is also called Grant. And finally, as usual, thanks for watching.
- 3.16- Using Declarative functionality and Apex together
This lecture is about using the curative functionality and Apex together, the topics of this lecture are invocable methods, invokeable variables, invoking Apex from a process, invoking Apex from a flow, and invoking a flow from Apex. As you are aware, a process and a flow can perform many different actions. For example, a process can can create a record, it can update a record, it can call another process, it can call a flow and many other actions. A flow can even do more things like deleting records and many other actions. But what if you need the process or the flow to perform actions that can only be done by Apex? For more advanced scenarios where Apex is the only way, you might need to engage Apex within a flow or a process. And indeed, Apex can be engaged by a process or by a flow.
Not any Apex method can be run by a process or by a flow. And to be able to be used by a flow or by a process, you should use the invocable method annotation to identify methods that can be run as invocable actions. If a flow invokes Apex, the running user must have the corresponding Apex class security in their user profile or in their permission sets. As mentioned, an invocable method is tagged by the invocable method annotation. This is simply the add sign followed by invokeable method right before the method definition. An invocable method must be static, and it must also be public or global. And its class must be an outer class. It cannot be an inner class. Only one method in a class can have the at invocable method annotation. So we cannot have two different methods with the same annotation in the same class. For that, separate classes must be created for separate admirable methods. Other annotations cannot be used with the Atmarkable method annotation. So for example, we cannot use the at future method annotation on a method that is annotated with the add invocable method annotation. Now, let’s talk about the parameters that an invocable method can take. There can be at most one input parameter, and its data type must be one of the following a list or a list of lists of a primitive data type like ID of a specific s object type like account. And of a generic S object type and a list of a userdefined type containing variables of the supported types above or userdefined apex types. If the return type is not null, the data type returned by the method must be one of the following. So it’s exactly the same list of the parameters.
So if I go back, you can see I have this is the list of the parameters, I have this list, and then if I go forward, I have the same list. So the return type and the parameters are of the same type. But of course I can have a return type that is different from the parameter, but both of them belong to the same set. And of course I can have a void as a return data type modifiers can be added to an invocable method. These are added right after the annotation as you can see in this example. So I have the add invokeable method annotation and then between the two parentheses I have a different modifiers. So I have label, I have description and I have category and this is the explanation of each. We have label which appears as the action name in Flow Builder and in Process Builder. The default is the method name. We also have description which appears as the action description. In Flow builder. The default is null. And finally we have category, which appears as the action category in Flow Builder. And if no category is provided which is the default, actions will appear under the uncategorized category. And finally, note that these modifiers are all optional.
We can also use another type of annotation, this time for variables that are used in user defined custom classes that are used by invocable methods. So the invocable variable annotation is used to identify variables used by invocable methods and custom classes. But why we need them? What are these? Well, invocable variables are used to identify a variable that is used as an input or an output parameter for an invocable method methods in vocable action. This way we make these variables available in the flow or in the process. Other annotations cannot be used with the invocable variable annotation. Only global and public variables can be invokeable variables and the data type of the invocable variable must be one of the following a primitive an s object, either the generic s object or a specific one and a list or a list of lists of primitives s objects. Objects created from Apex classes or collections modifiers can be added to an invocable variable.
These are added right after the annotation as you can see in this example. So we can see add invocable variable and then we have the different modifiers. We have label, we have description and then we have required and this is the expansion of each. We have label, which is the label of the variable. The default is the variable name. This label appears in Flow Builder for the action element that corresponds to an invokeable method. This labels helps admins understand how to use the variable. And the flow description is simply the description of the variable and the default is none. And Required specifies whether the variable is required or not. If not specified, the default is false, the value is ignored for output variables. And finally, note that these modifiers are all optional. Now this is an example of a class with an in vocable method. As you can see, we have the at invokeable method annotation highlighted in blue. And this annotation uses the three optional modifiers. So I have the class name.
So the name of the class is account query action. And then just like any other class, we have methods. The only difference between any method and the unborable method is this annotation. So as you can see I have the annotation and then I have the optional modifiers. So everything between the parentheses is optional. I can get rid of it, but it’s a good practice to keep it because it will help any admin to know what is the use of this method. And then as you can see we have the return type which is a list of string and then we have the parameter which is a list of IDs. So this is a primitive data type and this is also a primitive data type. So we have to return a list, we cannot return a single element. And then we have the name of the method which is get account names. So the job of this method is to take a list of IDs and then as you can see I am creating a new list of string called account names. And then you can see that I have a list of account. I’m creating a new list of account called accounts that is calling a so-called query. The so called query will get the name from account where ID is in the list of IDs that I have in the parameter.
And then I’m doing a for loop on the account and then I’m adding the name of each account to the account names list which is being returned. So this is a simple method. The only difference between this method and any other method is the add invocable method annotation which means that I can see this method in a flow or in a process under Apex actions. This is another example, but this time with a specific as object parameter. So as you can see I have the class name and then I have the method name which is insert account and then I have the add invocable method annotation with a label, with a description and with a category, but the difference is the parameter. So I have a list of accounts. So in this case I don’t have a list of primitive data type, but I have a list of a specific s object type. And then you can see that this is a very simple method and it will return a list of IDs. This is the third example that uses a custom class that is used as a parameter by the invocable method. So as you can see here I have a class called Math utility and then I have a method called add which is annotated by the add invocable method annotation and then it only has a label.
So as you can see here the ad method takes this parameter which is a little bit strange. Why? Because it’s not a primitive data type, it’s not s object specific or generic. So this is mainly a userdefined inner class. So as you can see here. Within the math until class, I have another inner class called flow input. Flow input has two different variables. It has the nt one and it has the n two. And we are passing the flow input as a parameter for this method, which means that now by passing this, I can pass the variables within this enter class. So this is the only difference between a primitive data type and a user defined data type. And because these two variables within the flow input enter class are tagged with the at invokeable variable annotation, they can be seen by a process or by a flow. So I can specify in the process or in the flow, both int one and into. This is the way to pass more than one parameter and directly to an Apex method within a process or within a flow. So in this case, I can pass int one and then I can pass n two. And this method will take this inner class which has nt one and n two, and then it will return the sum of these two. Now that the Apex class is made, how to invoke it from a process? Well, as you are aware now, Apex code can be invoked from a process builder to add advanced functionality to a process. And to do so, an Apex class with the invokeable method annotation should be created. We now know how to do that. And then when configuring the process, an Apex action can be created and added to the process to invoke Apex code.
So as you can see here, we have a process and then by choosing the action type to be Apex, I will be able to select the Apex class at method and then I can specify the name of this action. So in this case, any in vocable method will appear here. Finally, note that the user whose action triggers the process also executes the Apex class. This is an example at the bottom, as you can see, we have a class that has an invocable method that takes a list of book records. And this method does not return anything. So the return type is void. But instead it calls another application that we can mimic using the system debug. So this is, let’s say, a third party rest API that we want to call. But of course we will mimic this by the system debug. Within the process and the Apex actions, we should specify the Apex class and we should also specify the parameter value. In this case, the parameter is a list of book records so we can pass a book record. This Apex action is called like any other action and the process depending on the criteria we configure and the process. So, as you can see here, we have the call Apex action, which is the last part of a process. Before getting to this step, we have to specify the object. We have to specify if you want this process to run on creation or on creation and edit, we have to specify the criteria and then we have to specify the action. So in this case we specify the Apex action. Once we are here, we specify the name which is a friendly name, and then we specify the class. And because the class has only one invoke able method, this is the method that will appear here. So the list of input that you can see there or the one input is the input of the method of this class. So the class is Book edit action, as you can see here.
And then this is the parameter of the only in vocable method that we can see here. So this is the parameter of the edit box method. The same can be done with a flow. After all, a process uses the flow engine and in fact a process is simply a flow. But with a simplified user interface to call Apex from a flow, the flow can use the action element. We have two options to make an Apex class available as an action element for a flow. We have the invocable method and then we have the process plugin interface. We now know the invocable method and in fact this invocable method option provides more functionality than the process plugin interface and Salesforce recommends using it instead of the process that plugin interface. This is the difference between the two options. As you can see here, each option supports a list of parameters. The process that plugin interface option does not support these data types as parameters blob collection, as Object and Time whereas the invoke able method annotation method does not support the generic object, sets, maths or enable parameters.
Bulk operation is only supported with the in vocable method annotation option. And there are some other differences that you can go through here. But the thing to keep in mind is that Salesforce recommends the invocable method option. So building a class with an invocable method is the way to go unless you require something that is only available with the other option. This is a comparison between the two options. On the left side we have the invocable method option that we already know. It is simply a class that has one method tagged with the add in vocable method annotation. This annotation can take optional modifiers like label. We have seen all of this until now. And then on the right side we have a class with many more lines that is implementing the process plugin interface. This is the class name and then you can see Implements Process plugin interface and then we have the class. Both of these two will achieve the exact same thing. Salesforce commands using the add in vocable method and then you also have to use it all the time unless you have something that needs the Implements Process plugin option.
So the way to go is the invocable method. If not, you have to use this one. I will not go through the details of this code, but of course you can look at the Implements, Process, Plugin Option and the Salesforce documentation. This is an example of invoking Apex from a flow. This example deals with logging a record. Remember, logging a record is available through approval processes. But here we are using Apex to make it available right from the user interface without the need of an approval process. To do so, we should first enable Apex logging unlocking from Setup automation settings. So we have to go to Setup, we have to search for automation settings. And then there is a checkbox that we have to enable. This is the logging unlocking from Setup. This is simply to allow Apex to lock and unlock records instead of only approval processes. And then the Apex class should be created with an invocable method. This method takes a list of book records as a parameter and it simply uses the method Approval Lock on the list to lock. Of course you can change the method and expand it according to your needs. But this is just a quick example that I can show you. After that, the flow will be created with an action that calls the invocable method that locks the record.
And to launch the flow, we can add an action that calls the flow from within the book lightning page. If you are logged in as a system admin, you will not notice any difference when the record is locked. This is because a system admin can still edit logged records. So to verify that a record is locked, you either have to log in with another user or you can simply run this Apex code system debug. And then we have the string locked. And then we are calling this method which is called Approval is Locked. So the class is Approval, the method is locked and we are passing the ID of the record. This will return true or false based on if the record with this record ID is locked or no. Now that we have seen how to invoke Apex from a process and a flow, how can we invoke a flow from Apex? Well, there are some methods that we can use to do so. To begin, the start method of the Flow interview class can be used to launch an auto Launch flow or User Provisioning flow from Apex.
But before the start method, a flow interview should be initiated with the parameter. Then, to get the result back from the flow, the Get Variable value method can be used to return the value of the specified flow variable. Note that the start method does not have a return type, while the Get Variable value method has the return type of object. And finally, a flow needs to be active to allow users to invoke it from Apex. This is an example to show you. Let’s first create a simple flow called square that takes an input number and returns the square of this number. This flow is configured with one input variable called input, one output variable called result and one assignment element that assigns a formula called square to the result output variable. Now, to call this flow from Apex, let’s create a flow interview from anonymous Apex.
The first step is to create a map of string and object that is called params that is used to specify the input. And as you can see, this map contains the variable name input and the value five. So with this we are passing the value five to the flow variable input. The next step is to initiate the flow interview using the highlighted code flow interview square myflow equal to new flow interview square. And then we pass the parameters. Next we use the start method and finally we get the result of the flow by using the get variable value method and the flow output variable name result as the parameter.
And to read the result, we use the system debug. So this is the way to call a flow from Apex. This is a rare case that we need to have to call a flow from Apex. But this is just to show you that this can indeed be done. The exact same thing can be achieved with a small difference when initiating the flow interview. This time, instead of using flow interview that square my flow, I will use flow interview myflow equal to flow interview that create interview square parameters.
So as you can see here, we are passing the flow name as a parameter to the create interview method of the flow interview class. So if I go back, you can see here that I am not passing the name of the flow as a parameter. I’m not doing that, but I’m passing it here. So you can see here that square. But if I go forward, you can see here that the flow name is a parameter that is being passed to this method. Why this is important? Well, this is important because now I can build methods that will accept parameters and then within the body of this method, I can call this method. So this is mainly a dynamic way to call flow from within Apex. And that’s it for this lecture. In this lecture we have talked about in vocable methods which are nothing but regular Apex methods, but with a special annotation which is add invocable method which is used to identify that a method can be called by a process or by a flow. An invocable method must be public or global and it must be static, and it can only be used once in a class and it cannot be used with another annotation.
An invocable method can take only one input parameter which can be one of the following list or list of lists of a primitive data type, a specific s object or a generic s object list of userdefined type with containing variables that are supported. It can return these same types. In addition to void the atenvokable method, annotation can take three optional modifiers. We have label description and category. Label and Description will display in flow to make it easier for the user to choose a method. They will also display in process and category specifies the action category. Inflow invocable variables can be used in custom classes that are used by invocable methods, and they are used to pass more than one input and to get more than one output.
Similar to the inviable method modifiers in evocable, variables can also take three optional modifiers label, Description and Required are the three option modifiers. Label and Description will display in flow and make it easier for the user, and Required will make it a required input. Once an invocable method is built, it can be called by a process or by a flow. There exists another less popular way to use Apex classes within a flow, which is the process that plugin interface. And finally, a flow can be invoked by Apex through two methods the flow interview and the flow interview that create interview, which is the dynamic way of creating a flow interview. And finally, as usual, thanks for watching.