Our application that is using Orbeon (4.9) uses forms based authentication in JBoss (an older version, the open source 6.1 not to be confused with the EAP 6 version)
Orbeon runs in it's own war and in production will be in its own appserver process. Our application uses the ClusteredSingleSignOn valve to share the session between the wars via a JSESSIONIDSSO cookie. Configuration in the Orbeon war file matches that in our application war with the settings for form based authentication. The scenario we have that causes problems is when the session is invalidated (via timeout or an explicit logout) and the user requests to view a form via (e.g.) http://localhost:8080/orbeon/fr/cpf/AttachToForm/view/201506112 the form based authentication kicks in and displays a login page (in a popup iframe) the user supplies the credentials and is correctly authenticated but then they get presented with a page that says Orbeon Forms - Unauthorized You do not have access to this page. If you refresh the page then it works as it should without requiring additional authentication. On digging deeper, this error is caused by the call from orbeon to our system via our persistence layer REST service. It turns out that this call is not authenticated, it does not include the appropriate cookies. It should have the current JSESSIONID and JSESSIONIDSSO values but it does not. The second time after the refresh these cookies are present and it works. Now I think that this is a basic problem in the way that the forms authentication is implemented in tomcat. FormAuthenticator is a valve that is run very early in the chain of valves and before all the filters. They way it works is that it "suspends" the user's initial request, performs the authentication sequence (present the login form, handle the post request/authentication) and then restores the original request. This restoration includes the cookies *in the original request*. Unfortunately these are not correct for JSESSIONID and JSESSIONIDSSO. The code that does this (FormAuthenticator.restoreRequest()) looks like this: // Modify our current request to reflect the original one request.clearCookies(); Iterator cookies = saved.getCookies(); while (cookies.hasNext()) { request.addCookie((Cookie) cookies.next()); } So, this request continues to Orbeon and is authenticated so that is OK. But when orbeon makes the persistence API call it uses the cookie values in the request object to pass to our persistence layer. These are the cookie values prior to the authentication taking place. The value of JSESSIONID and JSESSIONIDSSO have changed during the form based authentication, it is a new session after all. So the call to our persistence layer fails as it is unauthenticated. I would welcome any ideas about how I can get around this problem. We have had similar problems before with forms based authentication and I am concerned that there is actually no good solution to this problem. thanks brian wallis... |
Administrator
|
Brian,
We have also found that forwarding cookies is a headache, and there is no reliable way to figure them out while processing an initial request. For this reason, in Orbeon Forms 4.7 we have moved Orbeon Forms's internal service calls to purely internal calls (they do not incur HTTP requests at all), which solves the issue for services internal to Orbeon Forms, including calling the persistence and other APIs. For external APIs and services, they should probably never be protected by form-based auth. It just doesn't make any sense as they are not user-facing end points. They should always be protected by a separate username/password or something else, and not reach a web app which prompts form-based auth. For example, services could be in their own web app protected by BASIC auth over SSL. Is that something that can work for you? -Erik |
Thanks Eric,
We have a number of REST services that are invoked from Orbeon forms to collect information from our system for validation and pre-filling and to read and save forms and templates using our persistence implementation. These services all require authentication and are all called on behalf of the user who is interacting with the form. They all need to be authenticated as that user for security and audit logging purposes so we cannot use a pre-configured account with basic auth. To enable a single point of authentication for all of our services we use the jboss/tomcat clustered SSO implementation in the ClusteredSingleSignOn valve. This provides a credential cache and a cookie, JSESSIONIDSSO, to identify the current user in requests. All of our webapps use a common FORM based login configuration and classes. We include this in our re-packaged Orbeon war as well. All of our REST services use BASIC auth, hopefully over SSL but that is our customer's decision. This all works fine as long as the session is valid, but when it times out or is otherwise invalidated then we need to prompt the user for credentials and continue on as if nothing had happened. This is where the problem occurs. There are actually two problems but this post only covers one of these. The second issue is to do with orbeon ajax calls. We have a solution to the first problem now using a simple valve that follows on immediately after the form authentication valve. All it does is detect the condition of a resumed re-authenticated request and copies the correct JSESSIONIDSSO cookie value into the request object where it is then available for Orbeon to copy into any outgoing REST requests. This is working now (I wrote it yesterday) but not extensively tested. I'm looking into the second problem now but this will require a bit of time I think. |
Administrator
|
Brian,
Thanks for the explanation. I understand the need to call services on behalf of the current user. -Erik |
Free forum by Nabble | Edit this page |