Redirect loop when liferay integrated with OpenSSO - liferay

My softwares are:
Liferay 6.0.6 with Tomocat 6.0.29, OpenSSO 9.5.2_RC1 Build 563 with tomcat 6.0.35, CentOS 6.2 Operating system
Setup:
I have setup both liferay and opensso on the same CenOS machine, making sure that both of its tomcat run on very different port, I have installed and configured OpenSSO with Liferay as per the guidelines availaible on liferay forums
Problem:
when i hit my application URL i get redirected to Opensso login page which is what i want, when i login with proper authentication details it trys to redirect to my application which is exactly how it should behave, however this redirect goes in a loop and i don't see my application dashboard. The conclusion i come to is that the redirect is trying to authenticate in liferay but somehow it does not get what it is looking for and goes back to opensso and this repeats infinitely. I can find similar issues been reported here. Unfortunetly, it did not work.
Later i decided to debug the liferay code and i put a break point on com.liferay.portal.servlet.filters.sso.opensso.OpenSSOUtil and com.liferay.portal.servlet.filters.sso.opensso.OpenSSOFilter. The way i understand this code is written is it first goes to the OpenSSOUtil.processFilter() method which get's the openSSO setting information that i have configured on liferay and later checks if it is authenticated by calling the method OpenSSOUtil.isAuthenticated(). This particular implementation basically reads the cookie information sent and tries to set the cookie property on liferay by calling the method OpenSSOUtil._setCookieProperty(). This is where it fails, it tries to read the cookie with name [iPlanetDirectoryPro] from the liferay class com.liferay.util.CookieUtil using the HttpServletRequest object but all it get's a NULL. this value set's the authenticate status to false and hence the loop executes.
Following is the code from class com.liferay.util.CookieUtil
public static String get(HttpServletRequest request, String name) {
Cookie[] cookies = request.getCookies();
if (cookies == null) {
return null;
}
for (int i = 0; i < cookies.length; i++) {
Cookie cookie = cookies;
String cookieName = GetterUtil.getString(cookie.getName());
if (cookieName.equalsIgnoreCase(name)) {
return cookie.getValue();
}
}
return null;
}
Can anyone please let me know why liferay is not able to find the cookie that opensso sent. If its related to Opensso setting about enable cookie value, then i have done that already which is here
In OpenSSO go to: Configuration -> Servers and Sites -> -> Security -> Cookie -> check Encode Cookie Value (set to Yes)
What works:
when this loop is executing i open another tab and login to my application explicitly, from my application when i signout it get's signout from opensso also. This is strange to me.
For more information, while this redirect loop happens, following URL's give me these set of information
http://opensso.ple.com:9090/openam/identity/getCookieNameForToken
string=iPlanetDirectoryPro
http://opensso.ple.com:9090/openam/identity/isTokenValid
boolean=true

Related

Java EE Container based Certificate authentication logout

In our Java EE application we use container based certificate authentication. We have created JAASLoginModule, which implements LoginModule interface with all required methods. We have configured our Wildfly and TomEE server to use this module both for authentication and ssl channel security, and everything goes smoothly with user login:
the user opens the browser and the app;
selects a certificate;
a JSF session is created, and now he is logged in;
A different story is with the logout. Just destroying the JSF session is not enough - after logout, if you just click back, the browser will get the certificate info from cache, recreate a session and lets you do the same stuff. Sometimes even browser restart does not help.
I could not find an effective way to call the logout method from the LoginModule from the JSF managed bean.
Any way to solve this problem?
Your problem is directly with the browser, so what you need is to tell the browser to "restart" the cache from your page every time it logs out, this, in order for it to think it's the first time the client is trying to get into that page. Kind of the same that private windows in Chrome and Firefox do.
Try this code:
//...
response.setHeader("Cache-Control","no-cache"); //Forces caches to obtain a new copy of the page from the origin server
response.setHeader("Cache-Control","no-store"); //Directs caches not to store the page under any circumstance
response.setDateHeader("Expires", 0); //Causes the proxy cache to see the page as "stale"
response.setHeader("Pragma","no-cache"); //HTTP 1.0 backward compatibility
//can check userId or something likes this.In this sample, i checked with userName.
String userName = (String) session.getAttribute("User");
if (null == userName) {
request.setAttribute("Error", "Session has ended. Please login.");
RequestDispatcher rd = request.getRequestDispatcher("login.jsp");
rd.forward(request, response);
}
Source: How to clear browser cache using java

live.users.enabled=true property and AutoLoginFilter in liferay 6.1.1

I want to monitor live users session in liferay. I found the solution for that need to put the property live.users.enabled=true in portal-ext.properties file. By that We can see the live user sessions from Control Panel->Portal->Monitoring tab of liferay server. But if try to call jsonws for login purpose from mobile application it give me error of AutoLoginFilter. The error is as below :
07:57:46,519 ERROR [bio-http-'8080'][AutoLoginFilter:238] Current URL
/sample-portlet/api/secure/jsonws?parameterAutoLoginLogin=test#liferay.com&
parameterAutoLoginPassword=test&j_username=test#liferay.com&j_password=test :
generates exception : Session already invalidated
I am able to login in liferay from browser with same credentials.
I figure out some issues that AutoLoginFilter not working when property live.users.enabled=true . One of them is here https://issues.liferay.com/browse/LPS-29871 .
So I want to monitor the live users sessions and AutoLoginFilter is work correctly. How can i achieve that. Please give me solution if any one can have.
You can hook the Autologin filter in this case. Remove following snippet from the getLoginRemoteUser method. (line 94)
else if (PropsValues.LIVE_USERS_ENABLED) {
UserTracker userTracker = UserTrackerLocalServiceUtil.fetchUserTracker(userId);
if ((userTracker == null) && (session.getAttribute(WebKeys.USER) == null)) {
session.invalidate();
return null;
}
}

WebClient with credentials still not downloading file

I am trying to download files from a website with username/password. You need to pay for a registered account in order to download files - which we have done. I am attempting to pass in the username/password and download a file as follows:
if (docUrl != null)
{
if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(password))
this.WebClientInstance.Credentials = new NetworkCredential(username, password);
fileData = this.WebClientInstance.DownloadData(docUrl);
this.WebClientInstance.Dispose();
isDataDownloaded = true;
}
WebClientInstance is a System.Net.WebClient. I debugged and verified that it is hitting the line to set credentials. Instead of downloading the PDF, I end up with an HTML page that prompts me to log in to get access to the file. I have verified that the username/password is correct. I use the same credentials to scrape the website with WatiN.
Is there something else that I'm supposed to be doing here?
UPDATE
Okay, I've done some sniffing around and found some useful info on this issue. I still haven't gotten it to work, but I think I'm closer. First, you need to create a cookie aware WebClient that extends the WebClient class, as follows:
public class CookiesAwareWebClient : WebClient
{
public CookieContainer CookieContainer { get; private set; }
public CookiesAwareWebClient()
{
this.CookieContainer = new CookieContainer();
}
protected override WebRequest GetWebRequest(Uri address)
{
var webRequest = base.GetWebRequest(address);
if (webRequest is HttpWebRequest)
(webRequest as HttpWebRequest).CookieContainer = this.CookieContainer;
return webRequest;
}
}
Next is to use the WebClient.UploadValues() method to upload the login info to the target website. The full process of authenticating and downloading the target resource is as follows:
using (var webClient = new CookiesAwareWebClient())
{
var postData = new NameValueCollection()
{
{ "userId", username },
{ "password", password }
};
webClient.UploadValues(docUrl, postData);
fileData = webClient.DownloadData(docUrl);
}
I was wrong about the site using forms auth. It is a JSP website and uses a JSESSIONID. I have verified that I am getting a cookie back with what appears to be a valid 32-byte JSESSIONID value.
However, when I call WebClient.DownloadData() it is still only returning the redirected login page. I've tried to fix this by setting the AllowAutoRedirect property on the HttpWebRequest to false, but then it returns 0 bytes.
Is there something else that I need to do so it won't redirect and will take me to the resource once I have authenticated?
(Answered in a question edit. Converted to a community wiki answer. See Question with no answers, but issue solved in the comments (or extended in chat) )
The OP wrote:
Solved. So the problem was between my ears. I was passing in the URL for the secure resource to the .UploadValues() method, knowing that it would redirect to the login page. However, I really needed to pass in the URL from the login form (where it goes upon submitting) - not the login page itself. Once I did that, it worked correctly. I think I'm going to go find a career in food service now.
LINKS
There were already a few questions posted on SO that addressed this issue. I just didn't know what I was looking for at first so I didn't see those... Anywhere here are a couple good resources that I came across when working on this issue:
how to maintaine cookies in between two Url's in asp.net
Trying to get authentication cookie(s) using HttpWebRequest

Why does CredentialCache.DefaultCredential contain empty strings for domain, username, and password

Does anyone have any ideas as to why CredentialCache.DefaultCredential would return an ICredential instance with empty strings for domain, username, and password? I'm running a WCF service on IIS 7.5. It works fine on one server but never works on another. I have verified that the IIS application has Windows Authentication enabled....
Here is how it's being used:
string url = string.Format("{0}/departments/finance/_vti_bin/listdata.svc", _IntranetAddress);
var financeDataContext = new FinanceDataContext(new Uri(url))
{
Credentials = CredentialCache.DefaultCredentials
};
I am not sure how it is working in one of your servers? I hope you already read this
http://msdn.microsoft.com/en-us/library/system.net.credentialcache.defaultcredentials.aspx
but it clearly says "The ICredentials instance returned by DefaultCredentials cannot be used to view the user name, password, or domain of the current security context."
The NetworkCredential returned from CredentialCache.DefaultCredential is just a placeholder. If you look at it using the Debugger, you'll see that it's of type SystemNetworkCredential. Internal API check for this type to see if integrated authentication should be used or not. There are other ways to get the current username (like WindowsIdentity.GetCurrent()).
EDIT:
To specify impersonation for a WCF operation, add this attribute to the method implementing a contract:
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public void SomeMethod()
{
// do something here
}

SocialAuthManager object ('manager') becomes NULL after redirection in case of SocialAuth libraries with JSF application?

I am using SocialAuth libraries in my JSF application for providing 'login with google/facebook'. As shown below it requires me to stores the SocialAuthManager object ('manager') in the session and then redirect to 'google/facebook' URL
//Create an instance of SocialAuthManager and set config
SocialAuthManager manager = new SocialAuthManager();
manager.setSocialAuthConfig(config);
// URL of YOUR application which will be called after authentication
String successUrl= "http://opensource.brickred.com/socialauthdemo/socialAuthSuccessAction.do";
// get Provider URL to which you should redirect for authentication.
// id can have values "facebook", "twitter", "yahoo" etc. or the OpenID URL
String url = manager.getAuthenticationUrl(id, successUrl);
// Store in session
session.setAttribute("authManager", manager);
Then get the 'manager' from session on succssfull/failure redirection from facebook/redirect as shown below:
// get the social auth manager from session
SocialAuthManager manager = (SocialAuthManager)session.getAttribute("authManager");
// call connect method of manager which returns the provider object.
// Pass request parameter map while calling connect method.
AuthProvider provider = manager.connect(SocialAuthUtil.getRequestParametersMap(request));
// get profile
Profile p = provider.getUserProfile();
The problem is if I am already logged in to facebook or google in a one of the 'tab' of the browser then this works perfectly OK. But if I am not logged in already then session becomes NULL and consequently 'manager' as well.
In other words if redirection from 'my application to facebook to my application' happens then it fails. If I am already logged in to facebook then redirection does not happens and it works.
Can someone help?
NOTE: this works perfectly well in case of IE but does not work in case of Chrome & Mozila
the reason for this behavior is that you are calling the redirected page from different domain so when page redirection happens your session data is lost.
please have a look at this link
http://31stdimension.blogspot.in/2012/04/how-to-connect-facebook-using-jsfjava.html

Resources