We have a java 8 project with JSF Mojarra implementation with PrimeFaces 3.5. We are implementing the authentication OIDC using Spring Security.
The front has to include in each HTTP Request the header Authorization with the bearer token.
We couldn't find how to add a header in a call any Primefaces component (commandbutton,etc).
When I use for example the commandLink tag (https://www.tutorialspoint.com/jsf/jsf_commandlink_tag.htm) I need that the rendered method mojarra.jsfcljs to send the Authorization header with my token when it calls the backend.
Is there any way of send customized headers with Mojarra in order to implement OIDC protocol?
Related
I have a web application which uses JSF 2.3 for the front end and offers also an API which is consumed by the front end with Jersey 2.29.1 running on a Tomcat 9 server.
The front end offers a login which will store the authenticated user in a #SessionScoped AuthenticationBean. The API methods should only be consumable if the user is logged in on the front end.
#Path("/service")
public class ApiService {
#GET
#Path("/data")
#Produces(MediaType.APPLICATION_JSON)
public String loadData() {
final AuthenticationBean authBean = CDI.current().select(AuthenticationBean.class).get();
if (authBean != null && authBean.isLoggedIn()) {
// Do business logic
}
else {
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
}
}
On the JSF page the API is consumed with a 'basic' jQuery AJAX call $.ajax() and updates some visual content based on the JSON response. The URL which I pass to the AJAX call is "#{request.contextPath}/api/service/data".
Everything works fine as expected, until I disable the cookies in the browser. If the cookies are disabled, the session ID is added to the URL (instead of being stored in a session cookie) by the servlet engine. So if I do not explicitly append the session ID to the URL for the AJAX call I have no access to the current session in the API service method, e.g. "#{request.contextPath}/api/service/data;jsessionid=#{session.id}" and therefore I can not check whether the user is logged in or not.
My question is now if I do have to add the jsessionid manually for every AJAX request or is there any other 'clean' possibility to pass the session ID to the service methods? Or do I have to access the session in any other way in the API service?
... explicitly append the session ID to the URL ...
The HttpServletResponse#encodeURL() does exactly that task, see also javadoc (emphasis mine):
Encodes the specified URL by including the session ID, or, if encoding is not needed, returns the URL unchanged. The implementation of this method includes the logic to determine whether the session ID needs to be encoded in the URL. For example, if the browser supports cookies, or session tracking is turned off, URL encoding is unnecessary.
So, basically:
#{request.contextPath}#{response.encodeURL('/api/service/data')}
The same method is by the way delegated by ExternalContext#encodeResourceURL().
Return the input URL, after performing any rewriting needed to ensure that it will correctly identify an addressable resource in the current application.
Jakarta Servlet: This must be the value returned by the javax.servlet.http.HttpServletResponse method encodeURL(url).
So, technically you can also do
#{request.contextPath}#{facesContext.externalContext.encodeResourceURL('/api/service/data')}
But this is a bit less convenient to type down. Moreover, using #{request.contextPath} already indicates that you're using JSF on top of servlets, not portlets, so using #{response} should be perfectly fine. You might want to make it yet shorter by defining a custom utility method in an application scoped bean. E.g.
#{functions.encodeURL('/api/service/data')}
#Named #ApplicationScoped
public class Functions {
public String encodeURL(String uri) {
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
return ec.getRequestContextPath() + ec.encodeResourceURL(uri);
}
}
This 'Answer' is not an answer to your real question but an explanation on why this is in no way JSF related (at the end there is a hint though to an answer)
JSF is an api and Jersey is an implementation of an api (JAX-RS). They effectively are complementary technologies and have no relation to one another in any way. It's the same like asking can I use JPA and Jersey in one application. Your actual questions have like stated no relation to JSF whatsover. JSF uses the session mechanism provided by the servlet engine, just like jax-rs does.
The second thing that is unclear is what your definition of 'front-end' is and where you run what. JSF in the JavaEE 'stack' is a front-end technology. JSF has a server side part in which you declare the components(See What is the definition of "component" in JSF) and when the html is generated they have client side html/javascript/css counterparts which communicate with the server in a way that is specified in the JSF specs. JSF 'components' by themselves do nothing if not backed by 'glue logic' on the server that in turn calls services (See JSF Controller, Service and DAO)
It might by now be clear that
is it possible for a JSF component to have called a Jersey service by an AJAX call?
is 'vague' and most likely given by your lack of knowledge of what the JSF is/does and how Jersey fits in (Jersey should be 'rest' here or jax-rs if you mean the api), See also How to implement JAX-RS RESTful service in JSF framework
JSF Components' html part on the client side communicates with the server in a JSF specific way, so
Rest is not needed there to get the client-side to communicate with the server (superfluous)
Trying to get rest in there makes things overly (overly) complex and without a real advantage
If you are trying to get the JSF server side components to communicate via REST
The server side is for interaction with the client side by means of the JSF spec for it
They are backed by code that in turn calls services. In this you can call a rest service, database or whatever
If, like I suspect, you want a non-jsf related $.ajax to call some rest service
You totally can, but read How to implement JAX-RS RESTful service in JSF framework
You can do anything with it to update the client side html
You can even update the html generated by JSF components
When doing 3, do NOT expect them to still work al the time, JSF is not to blame here
So after all this, your session id problem is not a jsf related problem. You'd have the same problem when using plain jsp or even plain html that has triggered a session.
HINT
So a better title would have been "jsessionid in url not added to ajax call in jquery" I posted this one in a search engine and added site:stackoverflow.com: jsessionid in url not added to ajax call in jquery site:stackoverflow.com
One of the results is effectively a duplicate of your question:
Appending my jsession ID at every ajax call by Jquery
I been working in a project with JSF 2.2 and a requeriment is to pass the Acunetix vulnerabilities validation.
I active protected-views (https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/JSF-CSRF-Demo/JSF2.2CsrfDemo.html) but still the validator says that the site isnt protected for CSRF attacks.
In the documentation says that I need a input hidden for POST request, but in JSF 2.2 says that with protected-views activated its Ok.
Do you know how to solve this problem? Do you have an implementation to solve this?
I am using Liferay 6.2-ce-ga3, primefaces 6 and JSF2.1. I have enabled CSRF protection for my portlet adding the follow code in liferay portal-ext.properties and portlet portal-ext.properties:
auth.token.check.enabled=true
auth.token.impl=com.liferay.portal.security.auth.SessionAuthToken
futhermore, I've added in portlet.xml
<init-param>
<name>check-auth-token</name>
<value>true</value>
</init-param>
For test, I removed p_auth=<code> from my form url then I submitted the form and it's worked. That's not good, I't should not allow the request without the token.
did I forget add a filter in configuration?
how liferay check the p_auth?
should I check manually p_auth token in my bean like this tutorial?
Liferay's p_auth token protects against CSRF during the ACTION_PHASE of the portlet lifecycle. I believe that it is enabled by default in Liferay 6.2, so you shouldn't need to configure anything for it.
The p_auth token must be present for a form to submit without error during the ACTION_PHASE. However, the p_auth parameter has no effect during the RESOURCE_PHASE which is the phase where JSF Ajax form submissions are executed. So you may be dealing with a JSF Ajax request. Thankfully, JSF also has its own CSRF protection enabled by default in the view state. So you are safe from CSRF with both Ajax and non-Ajax form submissions when you use Liferay Faces.
If you confirm that p_auth has no effect during a non-Ajax form submission, there may be a security vulnerability (or an issue with your configuration). You should update to the latest version of Liferay Portal* and retest. If you are still having issues, report a secure issue: https://issues.liferay.com/secure/CreateIssue.jspa?pid=10952&issuetype=1.
*Liferay Portal 6.2 GA6 is the latest in the 6.2 line, and Liferay Portal 7.0 GA7 is the latest CE release overall. Of course there are EE releases that may have more bug fixes as well.
Is there a standard mechanism in JSF 2.2 allowing me to include an HTTP header in all HTTP requests, regular or partial ?
I am looking for a solution to have the content of the "Authentication" header copied from the server reply and added to all queries. This way, I could easily use JWT tokens in my JSF apps.
If there is no standard mechanism, one specific to MyFaces 2.2 would be a solution too.
CSRF protection for a JSF based web app and Tomcat6 backend without using any external packages.
Kindly help.
JSF has already builtin protection against CSRF by the javax.faces.ViewState hidden field which is to be linked with the state of the component tree in the server side. If this hidden field is missing or contains a wrong value, then JSF simply won't process the POST request. On JSF 1.x the key is only a bit too easy to guess, see also JSF impl issue 812 and JSF spec issue 869. This is fixed in JSF 2.1.
Your major concern should be XSS. A succesful XSS attack can form a source for a guaranteed-to-be-succesful CSRF attack. To avoid XSS, ensure that you don't redisplay user-controlled input with <h:outputText escape="false" />. Other than that, JSF will already by default escape HTML entities.