cancel
Showing results for 
Search instead for 
Did you mean: 

Authentication alternatives for REST Webapp

b_schnarr
Champ in-the-making
Champ in-the-making
Hello at all,

we have an Enterprise Content Management System and want to trigger the activiti rest services from that ecm system. The ECM application and the activiti rest webapp are using the same LDAP directory. The problem is, that the rest services need username and password as basic authentication. When the user is logged into the ECM Application, it is not possible to readout the password of the current logged in user. So we can not send the login data to the rest webapp. Is there another possibility to send credentials to the rest services?

Thanks and best regards
Ben
23 REPLIES 23

frederikherema1
Star Contributor
Star Contributor
You can plug in a custom org.activiti.rest.common.filter.RestAuthenticator:

/* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*      http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.activiti.rest.common.filter;

import org.restlet.Request;


/**
* Allows enabling/disabling authentication on specific requests and allows authorisation of request after successful
* authentication.
*
* @author Frederik Heremans
*/
public interface RestAuthenticator {

  /**
   * Called before check is done to see if the request originates from a valid user.
   * Allows disabling authentication and authorisation for certain requests.
   *
   * @return true, if the request requires a valid and authorised user. Return false, if the request
   * can be executed without authentication or authorisation. If false is returned, the {@link #isRequestAuthorized(Request)}
   * won't be called for this request.
   */
  boolean requestRequiresAuthentication(Request request);
 
 
  /**
   * Called after a user is successfully authenticated against the Activiti identity-management. The logged in user
   * can be retrieved from the request's clientInfo object.
   *
   * @return true, if the user is authorised to perform the request. Return false, if the request is not authorised
   * for the given user.
   */
  boolean isRequestAuthorized(Request request);
 
}

Create an implementation of that class, that implements the requestRequiresAuthentication() method. ALWAYS return false here, to prevent the default mechanism of BASIC to kick in. On top of that, check the request for authentication using the mechanism you're using in the ECM.
- If the request is authenticated valid, just do "return false" to skip any activiti-specific authentication. Also, best to populate the org.activiti.engine.impl.identity.Authentication.setAuthenticatedUserId() in this method, to let the engine know which user is performing the REST-operation (important for history/initiator).

- If the request is invalid (user not authenticated), throw an exception from this method. If you want to have a 401-response (instead of a 500/400), throw a new org.restlet.resource.ResourceException, which allows you to set the status-code and error-message which is picked up and nicely returned to the client.

frederikherema1
Star Contributor
Star Contributor
The custom implementation fo the RestAuthenticator can be set on the instance of the org.activiti.rest.common.application.ActivitiRestApplication (or org.activiti.rest.service.application.ActivitiRestServicesApplication).

jordan_blair
Champ in-the-making
Champ in-the-making
In regards to the details of setting the custom implementation of the RestAuthenticator…   would you recommend just extending org.activiti.rest.service.application.ActivitiRestServicesApplication with your own instance.. which then calls the setRestAuthenticator(), setting the custom implementation.  Then just update the web.xml to define the org.restlet.application to point to your custom Application implementation.  Or would there be a better way to use Spring to inject the custom RestAuthenticator instance on the ActivitiRestServicesApplication class. 

Which do you recommend?  Thanks in advance.

Jordan

frederikherema1
Star Contributor
Star Contributor
Depends on how you bootstrap the REST-services. If you're using Spring to wire the REST into your app, you can use the default rest-app and use the bean property. If you're using the REST-war as-is, it's perfectly fine to create a custom web.xml, pointing to a subclass of the application-class, with your magic in it.

Short answer: both alternatives are fine Smiley Wink

frederikherema1
Star Contributor
Star Contributor
Yes, that's exactly what you need to do.

jordan_blair
Champ in-the-making
Champ in-the-making
I went with the second option and it works well… thanks!!!!!

b_schnarr
Champ in-the-making
Champ in-the-making
@frederikheremans, thank you very much for this detailed manual. I have another question on that:
I need to handout some config parameters to the rest-app. I thought that the <code>org.activiti.spring.SpringProcessEngineConfiguration</code> bean would be a good place. Therefore, I created 3 Strings and the corresponding getters and setters in SpringProcessEngineConfiguration.java.
Now, I can set the values in the <code>activiti-rest/WEB-INF/classes/activiti-context.xml</code>

Now my question: I created an implementation of the custom org.activiti.rest.common.filter.RestAuthenticator in the same package. How can I access the config parameters in my implementation class?

Thanks and best regards
Ben

b_schnarr
Champ in-the-making
Champ in-the-making
No ideas? I need an easy way to access the SpringProcessEngineConfiguration to add Parameters to the Rest API. With the explorer, this was much easier because I use the ExplorerApp Bean (activiti-ui-context.xml) which was available in all classes as singleton.
I do not want to create a new Spring Bean.

Thanks for your answers
Ben

trademak
Star Contributor
Star Contributor
There's no direct way to get to the configuration.
Is there no way to inject the configuration in your custom RestAuthenticator bean?
You can always access the Spring application context and get the configuration bean from that.

Best regards,