Thursday, March 10, 2011

How to Enable Create Operation Security Check for ADF BC

Out of the box in ADF BC, we don't have control over create operation security. In order to prevent unauthorized create operations, we need to define update operation security permissions, this will disable input fields for newly created record - user will not be able to insert blank record into database (validation will fail). However, sometimes this is not enough, we had requirement recently to protect EO from unauthorized create operations in advance, before blank row will be inserted. While I was working on this blog post, I saw Frank Nimphius post on ADF Code Corner for the same topic this week (coincidence), check sample 76. While its same topic, I will post my sample application as well, I will be looking more from functional requirements side and project based use case. Thanks to Frank's post, I was able to improve my sample. Please refer to chapter 39.10 Declaratively Preventing Insert, Update, and Delete from ADF Developer Guide - I will prevent create operation, using on described methods.

Download sample application - CreateOperationSecurityADFBC.zip. JDeveloper 11g PS3 comes with updated ADF Security wizard, now we can define our custom ADF Security Resource. This works also with PS2, but no wizard support. I will define CustomADFBC ADF Security Resource and create operation - press green plus sign next to the Resource Type field:


Once new resource type is created, you should define resource itself - will name it AllowCreate:


In standard case we have pages and ADF task flows as resources, here we define our custom resource - AllowCreate. Now we can add Application Roles, same as we would do for pages or ADF task flows:


Next, select create action checkbox for added Application Roles:


Sample application contains three predefined users (password: welcome1). Two users (redsam1 and redsam2) are granted permission to create new rows, user scott is not granted with such permission:


There is EO extension class in Model project, it contains overriden method to prevent unauthorized new row creation:


Method - isInsertAllowed, scans ADF Security and checks custom permission to verify if user can insert rows into current EO or no. There is one very important practical thing here, you should pay attention. For sample application, it would be enough to check hardcoded security resource names and it would work. However its not enough in reality, especially when we have generic EO Implementation class. Different EO's may work with different security resources. This can be handled with EO custom properties. Every EO, where custom security permission needs to be applied, should define custom permission information:


Generic method will retrieve available properties, and if there are any - will do authorization check for create operation:


This will ensure proper authorization check for EO create method, if security check will fail - there will be no row inserted - see overriden methods. If unauthorized create operation happens, I'm throwing JboException.

Additionally, we can protect UI layer - but this is only visual, is not critical anymore. You can set disabled property for Create button and reference our custom security resource (make sure you are using logical negate sign for this expression):


Let's do some tests, another Create button will not set any expression for disabled property - will be always enabled:


Insert Row button will not call create operation directly, it will call navigation action and will trigger CreateInsert operation through ADF task flow Method Call activity. As we know, if JboException will happen while calling Method Call, this will end-up into Controller error and will break application view. In order to prevent such ugly behavior, I have defined separate Method Call activity and marked it as Exception Handler:


Exception Handler Method Call is invoking my custom method from managed bean:


You should see from ADF task flow navigation, once Exception Handler Method Call will be completed, navigation will be returned back original page. This means user should not notice any undesired behavior. Exception Handler method checks for currently available Controller exception and presents it to the user through JSF Faces Message:


Now its time to test our solution. We login as user scott, without permission to create new records:


As you can see, first Create button is disabled as expected, based on Expression Language statement. Another button is active, we can press it and try to insert new row:


We are informed - No permission to insert new record. Such user friendly behavior happens only because there is custom Exception Handler Method Call defined, otherwise it would be system error. User scott is not allowed to insert new records:


User redsam1 - is granted with permission to insert new records:


Authorization check is passed:


3 comments:

Phan Tuan said...

Hi, my name Tuan.

First, I want to say thank you. Your articles help me a lot.

In this article, one point I don't understand: How the CustomEntityEmpj class be used?
I think when insert data, somewhere will call method of this class to check permission. But I don't find where you call this class.

If you can, give me more detail about that.
Thank you in advance.

Andrej Baranovskij said...

Hi Tuan,

Framework methods from EntityImpl are invoked automatically by ADF BC, this is a part of the framework.

Regards,
Andrejus

Phan Tuan said...

Hi Andrejus,
Thank for your quick answer,

You mean, because CustomEntityEmpl extends EntityImpl and overrides create(), so the framework will invoke create() of CustomEntityEmpl automatically, right ?

If so, what happen if we have more classes extending EntityImpl. How does the framework know what method to be invoked?

Thank you in advance and have a nice day,
Tuan.