Wednesday, October 17, 2012

ADF Essentials Security Implementation for Glassfish Deployment

ADF Essentials includes all the key ADF technologies, only one is missing - ADF Security. This is related to ADF Security technical implementation dependency on WebLogic security. However, lack of ADF Security support is not a show stopper - we can enable JAAS security model. This would protect page resources from ADF application, but not ADF Task Flows with Fragments. One of the most common ADF architectures nowadays - use of ADF Task Flows with Fragments through dynamic regions based on single page. This means security implementation to protect ADF Task Flows with Fragments, when rendered through dynamic region is very important.

In this post I will provide solutions, implemented in the sample application - MultiTaskFlowApp_gfsec.zip for:

1. Configuring JAAS security for ADF application
2. Configuring ADF application for Glassfish security
3. Restricting access to ADF Task Flows with Fragments

Sample application contains SecurityController class - custom class, responsible to check if task flow can be accessed. Logic is pretty simple - we check current dynamic region task flow address, compare it along with a security check (globalaccess role). This is simplified example, in real life most likely you would retrieve mapping between task flow and security role from the database:


Now the key part - from where this logic is invoked. It is invoked from task flow activation property (conditional activation). This means, dynamic region will be activated only if task flow will be viewable (security access is granted) based on the custom security logic from our method above:


This is how we can control ADF Task Flow with Fragments access.

Now let's take a look how security infrastructure is configured for deployment. Firstly you need to define JAAS security constraint in web.xml:


As you can see here, all pages (/faces/*) are restricted to be accessed only for authorized roles. These roles are mapped with groups. Groups are defined on Glassfish server. This is the same concept as with WebLogic, only that we need to use glassfish-web.xml (create it manually) configuration file in WEB-INF where roles are mapped with groups:


We can test it now - login as redsam (GlobalUser):


Open task flow for Departments:


Login now as sking (RegionalUser):


This user doesn't have access to the Departments task flow, task flow will not be activated as per our security check implementation:


You can create local user in Glassfish, just in the same way as you do in WebLogic - go to file realm and press Manage Users:


You can manage users from here:

18 comments:

Anonymous said...

hi,

what does it take to make this application run back on WebLogic?
It's a bit boring testing applications on Glassfish...
So i'd prefer all-stage-development in JDeveloper, then final deployment to Glassfish.
I followed to Shay Shmeltser blog's recommendation on deployement to Glasssfish and reversed it.
During runtime i get the error:
While trying to lookup 'jdbc.ncsDS'
didn't find subcontext 'jdbc'.Resolved
What might cause it?
i set for both DeployPlatform

Andrejus Baranovskis said...

Agree 100%.

This error means Data Source is not defined on on your server, you must configure it.

Andrejus

Anonymous said...

Andrejus,
i have an application running in weblogic with shared libraries. From JDev i deploy those as shared libraries.
Is it possible in Glassfish?
Tks.

Andrejus Baranovskis said...

I will need to test this.

Andrejus

Anonymous said...

Andrejus did you test the shared libraries in Glassfish?

Andrejus Baranovskis said...

Not yet - this is on my list. Quite busy... :)

Andrejus

fakhri kharrat said...

Hi Andrejus,
thanks for the post.
for the login page is it the same as shown with weblogic:

public String doLogin1() {
String un = (String)login1.getValue();
String pass;
pass = (String)password1.getValue();
byte[] pw = pass.getBytes();
FacesContext ctx = FacesContext.getCurrentInstance();

HttpServletRequest request = (HttpServletRequest)ctx.getExternalContext().getRequest();
try {
Subject subject = Authentication.login(new URLCallbackHandler(un, pw));
weblogic.servlet.security.ServletAuthentication.runAs(subject, request);

String loginUrl = "/adfAuthentication?success_url=/faces/index.jsf";
//String loginUrl = "/adfAuthentication?success_url=/faces/main.jsf";

HttpServletResponse response = (HttpServletResponse)ctx.getExternalContext().getResponse();

sendForward(request, response, loginUrl);
} catch (FailedLoginException fle) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Incorrect Username or Password", "An incorrect Username or Password was specified");
//setPassword(null);
//setUser(null);
ctx.addMessage(null, msg);
} catch (LoginException le) {
reportUnexpectedLoginError("LoginException", le);
}

return null;
}

fakhri kharrat said...

hi andrejus,

when I login using Glassfish server in first time, the login page appear but when i want to login with another user i refresh the page but the login window did not appear!
how can i login with another user?

Thanks

Anonymous said...

Hello Andrejus,

about the security in ADF Essentials.
We have a non functional requirement to restrict access for users not only to some page or region but also to the records of the table.
For that reason we use Oracle database context solution, the context is set depending by the user, which is logged in. We use another framework, but are thinking about migration to ADF.
What solution do You suggest to use in ADF for solving restriction by records question?

Thank You.

Andrejus Baranovskis said...

Hi,

You can set DB proxy user from ADF BC and continue using DB security. Read more: http://andrejusb.blogspot.ca/2012/03/testing-adf-bc-proxy-user-db-connection.html

Andrejus

Anonymous said...

Hi,

thank You for great post!

Don't You recommend to write own security module for Essentials?

If You keep and manage users and roles in the glassfish server, every time administrator wants to manage security rights, he has to do it in glassfish console which is not so convenient than to do it directly in the application.
In some other frameworks (i.e. Oracle Forms) we have own security modules, where You can administrate users, roles, functions that can be executed bu role, etc. Application administrator can manage them directly in the application.
What would be Your recommendation: write own security module or use some other, for example, to use user and roles administration in Glassfish like in Your example?

Thank You.

Andrejus Baranovskis said...

Hi,

There are two things - enforce security and manager users/roles. Here I describe how to enforce security. Users and roles can be stored in DB, then you need to define SQL Authenticator. Users/Roles can be managed then in similar way as it is done in Forms.

Andrejus

rakesh menon said...

Hi Andrejus,

Great Post.

But I was wondering if i am suppose to give anonymous access to a page say login .. how can i define these? because i would like to use form based authentication.

Andrejus Baranovskis said...

Yes, if you want to define login page, it must be granted with anonymous access. You can define new security constrain in web.xml.

Andrejus

Darren ADF said...

Do you know what is the Glassfish equivalent of the Java code to authenticate against the container? I would like to implement an additional login form in the template header of my web app's pages - and such a login is only possible in ADF by doing the login programmatically in a backing bean method.
Can this even be done with Glassfish?

There is an API called ProgrammaticLogin - but I'm not convinced that's what I need to work with.

Thanks,
Darren

Mehabub Sheikh said...

Hi,

I have a page where I have buttons Create, Update and Delete. I want to enable those buttons only if the user logged in as Admin in ADF running on Glassfish Open Source edition. I am new to this world. If you can guide me then that will be great.

Thanks,
Mehabub

Anonymous said...

Thx Andrejus. Just a quick question:
Where should I change security realm from file to jdbcrealm. I have already configured it under glassfish server.

محمد حسن said...

thanks andrejus really great