Securing Your Mendix App
In Mendix, ensuring that data is properly validated is critical for maintaining both application security and data integrity. This article will explore common pitfalls in entity validation and present three robust methods for securing your application..
There are many topics around Mendix security. This article focuses on the importance of validating your entities. We’ll look at a simple case here, although in real-world applications, these scenarios are often more complex.
Let’s say we have an entity called Animal, and we want only objects with a name starting with a capital ‘L’ to be entered.
We let Mendix generate the overview pages, then we end up with something like this:
If we run this, there is no validation at all. Let’s add some validation.
Now we have a validation flow that looks something like this:
When we try to add an animal whose name doesn’t start with the letter “L,” we get a helpful error.
So, we’ve secured our application, and we’re only allowed to enter animals whose names start with the letter “L.” But is there a catch?
Using the Mendix client API, we can also create or edit objects. Let’s try that in the console of the browser:
mx.data.create({
entity: "Part2.Animal",
callback: function(mxObject) {
//set attribute
mxObject.set("StartWithL", "Elephant");
console.log("Object created");
mx.data.commit({
mxobj: mxObject,
callback: function(){
console.log("Object committed");
},
error: function(error){
console.log("Could not commit object:", error);
}
})
},
error: function(error) {
console.log("Could not create object:", e);
}
});
If we take a look in the app, we see the following.
We’ve created an object with an animal that doesn’t start with an “L.” What’s going on here?
Let’s examine the domain model:
As you can see, the User role has read and write access to the StartWithL attribute. Which means the user can change this attribute using the client API. Adding validation behind a button is not sufficient for proper security.
I will explain three methods for correctly implementing effective validation.
- Use before commit validation
- Use a non-persistent entity
- Use a custom JAVA before commit check
1. Use Before Commit Validation
Let’s add the “before commit” handler.
If we try our JavaScript again, we get an error message, so this approach works.
In this simple case, it will work well. However, in more complex cases, you may need additional context, and there could be many more checks requiring different conditions. Implementing this can become a significant effort in such cases.
2. Use a Non-Persistent Entity
Another option is using a non-persistent entity. Here, we change the entity so that the user doesn’t need write access to the attribute. Our JavaScript client action will no longer work.
We also create a non-persistent copy of the entity, associating it with the original entity.
All user interactions with the Animal entity must be done through the non-persistent entity:
- When creating a new object, create the non-persistent entity first.
- When editing an object, copy the attribute values to the non-persistent entity and open it.
- On save, perform validation on the non-persistent entity. If valid, create or modify the actual object.
The following actions handle this process:
This method also works but can be a lot of work and may have a significant impact on the application.
3. Use a Custom JAVA Before Commit Check
I’d like to introduce an alternative way to prevent changes to the Animal entity. This method uses a Java action before the commit. The action checks whether attributes have changed that are not specified in a new attribute called “AllowedToChange.” If changes are detected in attributes not specified, the Java action will return an error.
This means that all commits in Mendix should contain a list of attribute names separated by a semicolon (;).
Here’s the setup:
- Create an attribute (“AllowedToChange”) with no rights for users.
- A before commit microflow which runs the JAVA action.
- An extra Change Object Action to specify which attributes are allowed to change.
Now, if we try the JavaScript again, we get an error in the browser console, and we also see detailed logging in Mendix.
This introduces a safer and simpler method for implementing validation. The advantage is that it has the least impact on your app. The disadvantage is that it’s not a standard Mendix solution. You have to specify the list of attributes manually, and the attribute names aren’t automatically updated if their names change, which means the “find usages” feature in Studio Pro won’t work.
I hope that Mendix will offer this kind of functionality out of the box in the future.
If you’re interested in the module that performs the checks, it will be available on the marketplace. I’m waiting for approval.
In the meantime The Mendix project containing all the cases above can be downloaded here.
Conclusion
To sum up, proper validation in Mendix is essential for ensuring both data integrity and security. The three methods outlined above provide different ways to achieve this, depending on the complexity of your application and the level of security required.
If you’ve faced similar validation challenges or have other security tips for Mendix users, I’d love to hear your thoughts in the comments! And if you have any concerns about the security of your Mendix app, feel free to reach out to me, and we can schedule a security assessment of your application.