Is it possible to forward to Siteminder login.fcc from a JSF action? - jsf

I have a "custom" (JSF) login page for my application. My company uses Siteminder for authentication. So, in order to login to Siteminder with a "custom" page, I have to have a form that posts to /login.fcc with the appropriate form fields (username/password and a couple of Siteminder specific hidden fields).
What I am trying to do is to continue to leverage the form validations and such of JSF and still post to login.fcc.
Here is a stripped down version of my custom form:
<rich:messages />
<h:form id="adminLogin" prependId="false">
<h:panelGrid columns="2" styleClass="center">
<h:outputLabel value="HUB USERNAME:" />
<h:inputText id="USER" label="Username" size="12" required="true" />
<h:outputLabel value="HUB PASSWORD:" />
<h:inputSecret id="PASSWORD" label="Password" size="12" required="true" />
<input type="hidden" name="target" value="#{loginController.smTarget}" />
<input type="hidden" name="smagentname" value="#{loginController.smAgentName}" />
</h:panelGrid>
<h:panelGroup layout="block" styleClass="max-width button-panel">
<a4j:commandButton id="adminLoginBtn" value="LOGIN"
styleClass="login-btn"
action="#{loginController.managerLogin}" />
</h:panelGroup>
</h:form>
Note that I have used standard hidden inputs for the target and smagentname fields. This is because I have no need to have both setters and getters in my controller for these fields. I simply want the controller to provide the values when the page renders.
My controller method looks like this:
public void managerLogin()
{
LoginController.LOG.debug("manager is logging in...");
LoginController.LOG.debug("user: " + getRequestParameterValue("USER"));
LoginController.LOG.debug("smagent: " + getRequestParameterValue("smagentname"));
LoginController.LOG.debug("target: " + getRequestParameterValue("target"));
forwardTo(LoginController.SM_LOGIN_FCC);
}
You can see that I am logging the values from all fields except the password field and they all print correctly in my log...so I know I am getting the values. My "forwardTo()" method simply gets the ExternalContext and calls dispatch() on it...passing in the path to the login.fcc page (which is "/forms/login.fcc").
When I input values in the form and click the login button, I see my values in the console but I get a 404 message in my browser.
I can manually put the "/forms/login.fcc" page in the address line and I have no problems with the GET rendering the login.fcc page. But I, of course, don't want to render the login.fcc (GET) I want to peform the Siteminder login (via POST).
It is my understanding that all request parameters are made available through a forward process I was expecting this to work.
I can take this same form and un-JSF-ize it...and make the login button simply submit the form (whose action would be the /forms/login.fcc via POST and it works fine too, but then I loose the benefits of the form/field validations that JSF provides.
Any ideas?

Use the following process:
Follow the SiteMinder redirect
Send your credentials (username/password)
Follow the SiteMinder redirect again
Send the SiteMinder cookies
Here is an article which explains the process in detail:
How to Connect to a SiteMinder Protected Resource

Related

JSF link to external site without showing username and password in the URL

I was able to do a SSO(Single sign on) on click of external link from the code below. SSO works but username/password is seen on url.
https://example.org/index.php?userLogin=user1&userPassword=pass123
<h:outputLink styleClass="ui-menuitem-link ui-corner-all"
value="https://example.org/index.php">
<h:outputText value="Ext Tool" />
<h:outputText styleClass="ui-icon ui-icon-suitcase"
style="float:left" rendered="#{userBean.in}" />
<f:param name="userLogin" value="#{userBean.user.eUser}" />
<f:param name="userPassword" value="#{userBean.user.ePass}" />
</h:outputLink>
I also used tried as below...
<h:commandLink action="#{userBean.eSubmit()}">
<h:outputText value="Ext Tool" />
<f:param name="userLogin" value="#{userBean.user.eUser}" />
<f:param name="userPassword" value="#{userBean.user.ePass}" />
</h:commandLink>
In the bean.. My coding is like this
public void eSubmit() throws IOException{
FacesContext fc = FacesContext.getCurrentInstance();
fc.getExternalContext().redirect("https://example.org/index.php?userLogin=" + user.getUser() + "&userPassword=" + user.getPass());
}
Even for the above code with commandLink - UserName and password are visible in the URL. Please guide me to hide password in the URL.
Am new to JSF so please help me understand...
A redirect instructs the client to create a new GET request on the specified URL. That's why you see it being reflected in browser's address bar.
As to performing a POST to an external site, you don't necessarily need JSF here. You're not interested in updating JSF model nor invoking a JSF action. Just use a plain HTML POST form.
<form method="post" action="https://example.org/index.php">
<input type="hidden" name="userLogin" value="#{userBean.user.eUser}" />
<input type="hidden" name="userPassword" value="#{userBean.user.ePass}" />
<input type="submit" value="Ext Tool" />
</form>
If necessary, throw in some CSS to make the submit button look like a link, or some JS to let a link submit that form.

jsf compositeComponent stateHelper reset after updating form

I'm using a compositeComponent in my application which allows a user to input an address. I store some specific data in the stateHelper to retreive it afterwards on submitting the form. The problem is when I click my button which submits AND updates the form, the stateHelper value is null. But if I add a panel layer under the form and update this one, they keep their values. Does anyone know how or why this is behaving like this?
ExampleCode (doesn't work):
...
<form id="inputForm>
<custComp:inputAddress />
<p:commandButton value="submitForm" update="inputForm/>
</form>
Example code (works)
<form id="inputForm">
<p:panel id="inputPanel">
<custComp:inputAddress />
<p:commandButton value="submitForm" update="inputPanel" />
</p:panel>
</form>

Keep url parameters after clicking <h:commandButton>

I've got a page which takes an id as a url parameter and uses it to get an object and display data about it. On this page we've got a modal which includes a file upload component, so we cannot use ajax to process the save. Instead we do this:
<rich:modalPanel domElementAttachment="parent" id="profilePanel" styleClass="popUp" resizeable="false" moveable="false" autosized="true" zindex="200" top="-10">
<a4j:form enctype="multipart/form-data" id="profilePanelFormId">
<q:box title="Edit Advocacy Profile" width="width6x" wantFocus="true">
<s:div id="profilePanelForm">
<rich:messages rendered="#{messagesUtil.errorsExist}"/>
<a4j:include viewId="/panel/advocacy/advocateProfileEdit.xhtml"/>
</s:div>
<h:commandButton id="cancel" immediate="true" value="Cancel" action="#{advocateManager.cancelEditCommitment}" styleClass="button cancel" tabindex="100"/>
<h:commandButton id="save" value="Save" action="#{advocateManager.saveCommitment}" styleClass="submit" tabindex="101"/>
</q:box>
</a4j:form>
</rich:modalPanel>
We populate the parameter in pages.xml like so:
<page view-id="/advocacy/advocateCommitmentView.xhtml" login-required="true">
<param name="confirmationCode" value="#{advocateManager.commitmentId}"/>
</page>
So far so good. The problem we're running into is when a user clicks save or cancel the url gets rewritten without the necessary id parameter. If the user then refreshes the page it throws errors because it doesn't have this key. Does anyone know how I can call my save method without using ajax and still keep the url parameter or intercept the call and add the parameter back in?
Put ?includeViewParams=true at the end of the action string.
This happens because <h:commandButton/> posts the form, and form posts do not include parameters in the URL. To add the parameters, create a navigation rule that redirects to the same page:
<navigation from-action="#{advocateManager.saveCommitment}">
<rule>
<redirect view-id="/same-page.xhtml" />
</rule>
</navigation>
When doing the redirect, page parameters are encoded and added to the URL. Note that this requires that #{advocateManager.commitmentId} is populated when the redirect is done.

jsf inputtext to bean

In my JSF Application, I have a page with several inputtext components. When the page is displayed, those inputtext components are populated with data from the database. When I hit the submit button, I want to pass those values as parameters to the next facelet.
What is happening is when I hit Submit, the old values are being passed, and not the updated values that the user has typed in. Here is what one of the inputtext components looks like:
<div align="center">
<h:outputLabel value="Product Quantity " />
<h:inputText id="quantity" value="#{product.quantity}" />
</div>
Then, in the submit button I am trying to get the values that the user types in:
<h:button value="Save Edits" outcome="welcome">
<f:param name="quantity" value="#{product.quantity}" />
</h:button>
Let's say that 100 was the original quantity that the field was populated with. When the user changes it to 110, and hits submit, the welcome facelet still thinks 100 is the value. Any ideas?
Is there any particular reason you've decided to use a <h:button/> instead of an <h:commandButton/>? Because that's the reason why your parameters are not making it to the next page
<h:commandButton/> processes it's enclosing <h:form/>, submitting it's content to the server in a POST request (and the JSF processing lifecycle kicks in e.t.c.) while the <h:button/> will generate a GET request. <h:button/> is generally used for navigation. Stick to <h:commandButton/> if you want to do more than navigate

JSF Authentication: cannot intercept error messages

I have developed a simple login form to be used in my JSF + PrimeFaces page:
<form action="j_security_check" method="post">
<p:dialog modal="true" header="Login" widgetVar="loginDlg">
<h:panelGrid columns="3" cellpadding="5">
<h:outputLabel for="j_username">Username:</h:outputLabel>
<h:inputText id="j_username" required="true" />
<h:message for="j_username" />
<h:outputLabel for="j_password">Password:</h:outputLabel>
<h:inputSecret id="j_password" required="true" />
<h:message for="j_password" />
<br />
<h:commandButton value="Login" />
</h:panelGrid>
</p:dialog>
</form>
Tried with an empty password, but the missing password (that is required) is not caught by h:message component. I have also switched to a p:commandButton thinking that the problem could have been in the Ajax behaviour of the button, but the page is not rendered because PrimeFaces complains about the CommandButton not being inside a form element. The exception thrown by the container is:
com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Access denied on empty password for user pippo
To summarize, I have 2 questions:
Why the missing password doesn't produce a message before the form is submitted?
How can I catch a LoginException and display the error message inside the dialog?
The j_security_check request is handled by the web container, not by JSF. That explains that the required="true" won't work. It works only when you use JSF <h:form> and programmatic login by HttpServletRequest#login() in the action method associated with the command button.
Best what you can do is to confiure a <form-error-page> in web.xml pointing to the very same URL as the <form-login-page>. You could then check if the request has been forwarded by j_security_check itself, which would mean that a login error has occurred.
<h:panelGroup rendered="#{requestScope['javax.servlet.forward.servlet_path'] == '/j_security_check'}">
<h:outputText value="Unknown login, please try again" styleClass="error" />
</h:panelGroup>
Use this instead of the <h:message>.
As to why <p:commandButton> complains that there's no form is simply because you didn't use <h:form>.
Unrelated to the concrete problem, that <form> (or <h:form> whenever you would decide to switch to programmatic login) can better be placed in the body of <p:dialog>, not outside. The <p:dialog> can by JS be relocated to end of body which would cause it not to be in a form anymore.

Resources