Monday, April 11, 2011

During a partner workshop I was showing to the developers how the eXo IDE can help them to develop new features quickly and push them to the users in few minutes. A person asked me if it is possible to put some restriction in services and gadgets based on user profile.
As you can guess the answer is YES WE CAN!

How to access the security context in a REST service

How to check is a user is member of a group and manage permission from this information

How to consume this service in a gadget and leverage the security to protect resources

Not-authorized

Authorized

If you are not interested to follow steps by step the explanations you can directly jump to the complete REST Service code or download the full eXo IDE Project from GitHub

Access the User Profile from your REST Service

As you probably know eXo Platform uses JAX-RS as API to develop and deploy REST Services. eXo developers can create REST services using their favorite Java IDE, but here I am using the eXo IDE package with eXo Platform.

To access the security and user information in your service method it is possible to use the SecurityContext class of the JAX-RS API. Your method signature will look like:

In lines 7 and 8, I import the classes needed to inject the security context in the method getSystemInfo() in line 16. For now let's forget about the other part of the code.
With the Security Context object you can now access many things in your code. Two methods are quite interesting for this example: getUserPrincipal() and isUserInRole(), since our goal is to check if a user is allowed to execute or not a part of the business logic.
It is important here to remember that we cannot directly use the isUserInRole() method since this method uses the logical JavaEE roles that are defined at the Java application level. In our case we are interested to know if a user is present in a "eXo User Identity" Group, for example member of the /platform/administrators group. This information is populated during the login process and comes from the user provider that could be LDAP, the eXo Database or JCR, or any other source since developers can extend this API to plug their own provider.
Let's create an helper method that check, using the eXo Identity Service, if the user that executes the method is present in a group.

In this example for simplicity reason I have hard coded the group to check, you can obviously use smarter code to user external configuration to inject a list of group to check for example. I manage the security logic of my method using simple if statement and return a string. You can also depending of your needs, manage the status of your response and use HTTP Code for example return an HTTP 403. For this you just need to return a different response using following code:

return Response.status(Response.Status.FORBIDDEN).build();

For simplicity reason I will stay with a single Response status (OK) and manage the permission in my client code.

Complete REST Service

Let's take a look to the full service now, this service allows administrators to get the list of the System Properties, other users get an status string "NOT-ALLOWED":

Line 26 : Initialization of a simple ResponseWrapper defined on line 51, that contains a status and data. That will be serialized in JSON by the eXo REST engine.

Line 28 : the method check if a user is connected and member of /platform/administrator. If not it send response with the status NO-ALLOWED.

Line 31/32 : The response object is sent. This response contains an OK status and the data (system properties list)

Line 42 : Using the eXo Identity Service, the method check if the connected user is member of a specific group.

Consume the service into a Gadget

I can now take this service and consume it into an Gadget. I also develop this Gadget using the eXo IDE.
The following code shows the Javascript part of the Gadget that calls the service, check the security and push the response content in Gadget body. For productivity I use JQuery framework.

Here some quick explanation about this code:

Line 23: To call the REST service, I use the $.getJSON() method. This method is really easy to use when you are executing the Gadget is in the same container than the portal that consumes it. When you are using the gadget.io.MakeRequest is interesting to proxy a request and you need to re-authenticate, for example using oAuth.

Line 3 : This is the call back method, as you can see in this method I use the ResponseWrapper to check the code in the status attribute. Depending of the status OK or not I do print the value.

Conclusion

In this how-to you have learned how to:

Get the security context in your REST Service

Check the membership of a user using the eXo Identity Service

Create a gadget that consume this service and expose only data to user with correct profile