Wednesday, March 1, 2017

Authentication and Authorization in ADF Essentials 12.2.1.x on Glassfish 4

I think I’ve said before how much I appreciate that Oracle provides a subset of ADF functionality for free, in the library called ADF Essentials.  ADF Essentials will let you write ADF applications that can be deployed to pretty much any JEE standard application server, and Glassfish is specifically supported.  I find that this is a good selling point for ADF because my clients may find Oracle WebLogic Server (WLS) a bit hefty for their needs, and may balk at the licensing and support costs for WLS.

One of the problems with the early versions of ADF Essentials is that they are intended for Glassfish 3.1.2 and may not work properly with the latest version, Glassfish 4.1.1.  So I was delighted when ADF 12.2.1.0 was released, and included ADF Essentials from the beginning.  And it was certified for Glassfish 4.  I set to work, and soon I had my standard test application on the HR sample schema working in Glassfish 4.1.1 with ADF Essentials 12.2.1.1.  It ran just as well on Glassfish as it did on the Integrated WLS, maybe even as little faster.  Glassfish 4.1.1 has a few bugs and quirks that I wish would be fixed, and I’m sorry to say that Oracle is phasing out its support for the Open Source Glassfish project – so members of the community are going to have to step forth to continue the work.  But generally, it works.

Now for the next stage of my test application which was adding authentication and authorization.  One of the missing pieces in the ADF Essentials subset that is part of full ADF is ADF Security.  This is missing, because it relies on some capabilities that are part of WLS, and not part of the JEE standard.  This doesn’t mean that you can’t write secure applications with ADF Essentials, but you must use the capabilities that are part of the JEE standard or a third party library like Spring Security.  I’d done this before with ADF 12.1.3 and Glassfish 3.2.1, so I had some experience with setting it up.  The steps are:
  1. Add a security realm to Glassfish.  ADF defaults to using the name, “myrealm”, but you can change this and use pretty much any name you like.  For simple testing, you might want to use the “file” ream, which will allow you to add test users and their security groups in the Glassfish admin console.  Later, you can replace this with a realm based on an LDAP directory or some database tables.
  2. Optionally, add one or more security roles in web.xml.  These roles are used for authorization to govern what users may do in your application.  If you don’t use roles, you’ll have to authorize by username, so I always do this.
  3. Add one or more security constraints in web.xml.  In the simplest configuration, a constraint will protect particular pages in the application, and allow only certain users or users with certain roles to access these pages.  It can be more complex than that, but let’s stick with the simple case.  The application will require authentication only when the user tries to access a protected page, and has not yet been authenticated.
  4. Configure authentication in web.xml with the login-config element.  This tells the application server how to get the username and password.  There are several ways to do this, and the most common way is with a login form, so you may have to add a page with the required login fields.
  5. Add a glassfish-web.xml file in WEB-INF if you don’t already have one, and use it to map the security roles in web.xml to the security groups that will be returned from your Glassfish security realm.  You may need this file anyway to map the data sources used by your application to the data sources that you added to Glassfish.
So, I did these with my test application, re-deployed it, and tried it.  It showed the login page as expected, showed the error page if I typed in an incorrect username and/or password, but when I typed in the correct username and password, I saw the following error:
javax.servlet.ServletException: Filter execution threw an exception
root cause
java.lang.NoClassDefFoundError: Could not initialize class
 oracle.adf.share.security.identitymanagement.UserProfile 

After making sure that I had made no discernible error, I posted a question in the JDeveloper and ADF Forum on the Oracle Communities - Filter exception ADF Essentials 12.2.1.1 on Glassfish 4.  There was a considerable amount of discussion, and other people reported the same problem.  Several of us did some additional testing.  One thing I immediately learned is that the application works fine in the Integrated WebLogic Server.  This points to a problem that is related to running with ADF Essentials on Glassfish.

As far as I can determine, there has been a change to the ADF Controller that is part of ADF 12.2.1 including the one that is part of ADF Essentials.  When a user authenticates, the user’s name is in the userPrincipal property of the external context of the application.  The ADF Controller is probably picking up that this is not null and not equal “anonymous” and deciding that it needs to initialize a UserProfile for the user.  The library with this class is adf-share-ca.jar which IS part of ADF Essentials, but the constructor for this class must be calling something that is unique to WLS, and not available in Glassfish.  So it fails.  It does not matter how the external context property is set.  I tried it with Spring Security, which is an alternative to standard JEE authentication, but still does set the external context.  It had the same problem.

As it stands now, unless the ADF developers listen to our pleas to fix this, it is not possible to use authentication and authorization in an ADF Essentials 12.2.1.x application.  At least, it is not possible with an out-of-the-box deployment of the ADF Essentials libraries.  In my next post, I will detail a work-around.

2 comments:

  1. Hi John,
    Did you have the chance to test if your workaround is still necesary in the new recent release of Jdev 12.2.1.3.0 ??
    Best regards,
    Jose.

    ReplyDelete
    Replies
    1. No, I haven't tried it yet, though the release notes give me some hope. You may have noticed in my most recent posts that my attention has been more on the database side of things recently. I do intend to give it a try sometime, but it will have to be done on the side.

      Delete